com.cws.esolutions.security.main.PasswordUtility.java Source code

Java tutorial

Introduction

Here is the source code for com.cws.esolutions.security.main.PasswordUtility.java

Source

/*
 * Copyright (c) 2009 - 2017 CaspersBox Web Services
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.cws.esolutions.security.main;

import java.io.File;
import org.slf4j.Logger;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import org.slf4j.LoggerFactory;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.io.FileUtils;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.lang.RandomStringUtils;

import com.cws.esolutions.security.SecurityServiceBean;
import com.cws.esolutions.security.utils.PasswordUtils;
import com.cws.esolutions.security.config.xml.SystemConfig;
import com.cws.esolutions.security.SecurityServiceConstants;
import com.cws.esolutions.security.config.xml.SecurityConfig;
import com.cws.esolutions.security.exception.SecurityServiceException;
import com.cws.esolutions.security.config.xml.PasswordRepositoryConfig;
import com.cws.esolutions.security.config.xml.SecurityConfigurationData;
import com.cws.esolutions.security.listeners.SecurityServiceInitializer;

/*
 * Project: eSolutionsSecurity
 * Package: com.cws.esolutions.security
 * File: PasswordUtility.java
 *
 * History
 *
 * ----------------------------------------------------------------------------
 * cws-khuntly @ Jul 28, 2014 1:27:05 PM
 *     Created.
 */
@SuppressWarnings("static-access")
public class PasswordUtility {
    private static Options options = null;

    private static final String CNAME = PasswordUtility.class.getName();
    private static final SecurityServiceBean svcBean = SecurityServiceBean.getInstance();
    private static final String LOG_CONFIG = System.getProperty("user.home")
            + "/.etc/SecurityService/logging/logging.xml";
    private static final String SEC_CONFIG = System.getProperty("user.home")
            + "/.etc/SecurityService/config/ServiceConfig.xml";

    static final Logger DEBUGGER = LoggerFactory.getLogger(SecurityServiceConstants.DEBUGGER);
    static final boolean DEBUG = DEBUGGER.isDebugEnabled();
    private static final Logger ERROR_RECORDER = LoggerFactory
            .getLogger(SecurityServiceConstants.ERROR_LOGGER + CNAME);

    static {
        Option entryNameOption = OptionBuilder.withLongOpt("entry").hasArg(true).withArgName("entry")
                .withDescription("Name for the entry").withType(String.class).isRequired(true).create();

        Option usernameOption = OptionBuilder.withLongOpt("username").hasArg(true).withArgName("username")
                .withDescription("Username for the entry").withType(String.class).isRequired(true).create();

        Option passwordOption = OptionBuilder.withLongOpt("password").hasArg(true).withArgName("password")
                .withDescription("Username for the entry").withType(String.class).isRequired(false).create();

        Option writeToFile = OptionBuilder.withLongOpt("store").hasArg(false)
                .withDescription("Store the entry in the data files").isRequired(false).withType(Boolean.class)
                .create();

        Option replaceEntry = OptionBuilder.withLongOpt("replace").hasArg(false)
                .withDescription("Replace an existing entry").isRequired(false).withType(Boolean.class).create();

        Option encryptOption = OptionBuilder.withLongOpt("encrypt").hasArg(false).withArgName("entry")
                .withArgName("username").withArgName("password").withArgName("store")
                .withDescription("Encrypt the provided string").withType(Boolean.class).isRequired(false).create();

        OptionGroup encryptOptionsGroup = new OptionGroup().addOption(encryptOption).addOption(entryNameOption)
                .addOption(usernameOption).addOption(passwordOption).addOption(writeToFile).addOption(replaceEntry);

        Option decryptOption = OptionBuilder.withLongOpt("decrypt").hasArg(false).withArgName("entry")
                .withArgName("username").withDescription("Decrypt the provided string").withType(Boolean.class)
                .isRequired(false).create();

        OptionGroup decryptOptionsGroup = new OptionGroup().addOption(decryptOption).addOption(entryNameOption)
                .addOption(usernameOption);

        options = new Options();
        options.addOptionGroup(encryptOptionsGroup);
        options.addOptionGroup(decryptOptionsGroup);
    }

    public static void main(final String[] args) {
        final String methodName = PasswordUtility.CNAME + "#main(final String[] args)";

        if (DEBUG) {
            DEBUGGER.debug("Value: {}", methodName);
        }

        if (args.length == 0) {
            HelpFormatter usage = new HelpFormatter();
            usage.printHelp(PasswordUtility.CNAME, options, true);

            System.exit(1);
        }

        BufferedReader bReader = null;
        BufferedWriter bWriter = null;

        try {
            // load service config first !!
            SecurityServiceInitializer.initializeService(PasswordUtility.SEC_CONFIG, PasswordUtility.LOG_CONFIG,
                    false);

            if (DEBUG) {
                DEBUGGER.debug("Options options: {}", options);

                for (String arg : args) {
                    DEBUGGER.debug("Value: {}", arg);
                }
            }

            CommandLineParser parser = new PosixParser();
            CommandLine commandLine = parser.parse(options, args);

            if (DEBUG) {
                DEBUGGER.debug("CommandLineParser parser: {}", parser);
                DEBUGGER.debug("CommandLine commandLine: {}", commandLine);
                DEBUGGER.debug("CommandLine commandLine.getOptions(): {}", (Object[]) commandLine.getOptions());
                DEBUGGER.debug("CommandLine commandLine.getArgList(): {}", commandLine.getArgList());
            }

            final SecurityConfigurationData secConfigData = PasswordUtility.svcBean.getConfigData();
            final SecurityConfig secConfig = secConfigData.getSecurityConfig();
            final PasswordRepositoryConfig repoConfig = secConfigData.getPasswordRepo();
            final SystemConfig systemConfig = secConfigData.getSystemConfig();

            if (DEBUG) {
                DEBUGGER.debug("SecurityConfigurationData secConfig: {}", secConfigData);
                DEBUGGER.debug("SecurityConfig secConfig: {}", secConfig);
                DEBUGGER.debug("RepositoryConfig secConfig: {}", repoConfig);
                DEBUGGER.debug("SystemConfig systemConfig: {}", systemConfig);
            }

            if (commandLine.hasOption("encrypt")) {
                if ((StringUtils.isBlank(repoConfig.getPasswordFile()))
                        || (StringUtils.isBlank(repoConfig.getSaltFile()))) {
                    System.err.println("The password/salt files are not configured. Entries will not be stored!");
                }

                File passwordFile = FileUtils.getFile(repoConfig.getPasswordFile());
                File saltFile = FileUtils.getFile(repoConfig.getSaltFile());

                if (DEBUG) {
                    DEBUGGER.debug("File passwordFile: {}", passwordFile);
                    DEBUGGER.debug("File saltFile: {}", saltFile);
                }

                final String entryName = commandLine.getOptionValue("entry");
                final String username = commandLine.getOptionValue("username");
                final String password = commandLine.getOptionValue("password");
                final String salt = RandomStringUtils.randomAlphanumeric(secConfig.getSaltLength());

                if (DEBUG) {
                    DEBUGGER.debug("String entryName: {}", entryName);
                    DEBUGGER.debug("String username: {}", username);
                    DEBUGGER.debug("String password: {}", password);
                    DEBUGGER.debug("String salt: {}", salt);
                }

                final String encodedSalt = PasswordUtils.base64Encode(salt);
                final String encodedUserName = PasswordUtils.base64Encode(username);
                final String encryptedPassword = PasswordUtils.encryptText(password, salt,
                        secConfig.getSecretAlgorithm(), secConfig.getIterations(), secConfig.getKeyBits(),
                        secConfig.getEncryptionAlgorithm(), secConfig.getEncryptionInstance(),
                        systemConfig.getEncoding());
                final String encodedPassword = PasswordUtils.base64Encode(encryptedPassword);

                if (DEBUG) {
                    DEBUGGER.debug("String encodedSalt: {}", encodedSalt);
                    DEBUGGER.debug("String encodedUserName: {}", encodedUserName);
                    DEBUGGER.debug("String encodedPassword: {}", encodedPassword);
                }

                if (commandLine.hasOption("store")) {
                    try {
                        new File(passwordFile.getParent()).mkdirs();
                        new File(saltFile.getParent()).mkdirs();

                        boolean saltFileExists = (saltFile.exists()) ? true : saltFile.createNewFile();

                        if (DEBUG) {
                            DEBUGGER.debug("saltFileExists: {}", saltFileExists);
                        }

                        // write the salt out first
                        if (!(saltFileExists)) {
                            throw new IOException("Unable to create salt file");
                        }

                        boolean passwordFileExists = (passwordFile.exists()) ? true : passwordFile.createNewFile();

                        if (!(passwordFileExists)) {
                            throw new IOException("Unable to create password file");
                        }

                        if (commandLine.hasOption("replace")) {
                            File[] files = new File[] { saltFile, passwordFile };

                            if (DEBUG) {
                                DEBUGGER.debug("File[] files: {}", (Object) files);
                            }

                            for (File file : files) {
                                if (DEBUG) {
                                    DEBUGGER.debug("File: {}", file);
                                }

                                String currentLine = null;
                                File tmpFile = new File(FileUtils.getTempDirectory() + "/" + "tmpFile");

                                if (DEBUG) {
                                    DEBUGGER.debug("File tmpFile: {}", tmpFile);
                                }

                                bReader = new BufferedReader(new FileReader(file));
                                bWriter = new BufferedWriter(new FileWriter(tmpFile));

                                while ((currentLine = bReader.readLine()) != null) {
                                    if (!(StringUtils.equals(currentLine.trim().split(",")[0], entryName))) {
                                        bWriter.write(currentLine + System.getProperty("line.separator"));
                                        bWriter.flush();
                                    }
                                }

                                bWriter.close();

                                FileUtils.deleteQuietly(file);
                                FileUtils.copyFile(tmpFile, file);
                                FileUtils.deleteQuietly(tmpFile);
                            }
                        }

                        FileUtils.writeStringToFile(saltFile, entryName + "," + encodedUserName + "," + encodedSalt
                                + System.getProperty("line.separator"), true);
                        FileUtils.writeStringToFile(passwordFile, entryName + "," + encodedUserName + ","
                                + encodedPassword + System.getProperty("line.separator"), true);
                    } catch (IOException iox) {
                        ERROR_RECORDER.error(iox.getMessage(), iox);
                    }
                }

                System.out.println("Entry Name " + entryName + " stored.");
            }

            if (commandLine.hasOption("decrypt")) {
                String saltEntryName = null;
                String saltEntryValue = null;
                String decryptedPassword = null;
                String passwordEntryName = null;

                if ((StringUtils.isEmpty(commandLine.getOptionValue("entry"))
                        && (StringUtils.isEmpty(commandLine.getOptionValue("username"))))) {
                    throw new ParseException("No entry or username was provided to decrypt.");
                }

                if (StringUtils.isEmpty(commandLine.getOptionValue("username"))) {
                    throw new ParseException("no entry provided to decrypt");
                }

                String entryName = commandLine.getOptionValue("entry");
                String username = commandLine.getOptionValue("username");

                if (DEBUG) {
                    DEBUGGER.debug("String entryName: {}", entryName);
                    DEBUGGER.debug("String username: {}", username);
                }

                File passwordFile = FileUtils.getFile(repoConfig.getPasswordFile());
                File saltFile = FileUtils.getFile(repoConfig.getSaltFile());

                if (DEBUG) {
                    DEBUGGER.debug("File passwordFile: {}", passwordFile);
                    DEBUGGER.debug("File saltFile: {}", saltFile);
                }

                if ((!(saltFile.canRead())) || (!(passwordFile.canRead()))) {
                    throw new IOException(
                            "Unable to read configured password/salt file. Please check configuration and/or permissions.");
                }

                for (String lineEntry : FileUtils.readLines(saltFile, systemConfig.getEncoding())) {
                    saltEntryName = lineEntry.split(",")[0];

                    if (DEBUG) {
                        DEBUGGER.debug("String saltEntryName: {}", saltEntryName);
                    }

                    if (StringUtils.equals(saltEntryName, entryName)) {
                        saltEntryValue = PasswordUtils.base64Decode(lineEntry.split(",")[2]);

                        break;
                    }
                }

                if (StringUtils.isEmpty(saltEntryValue)) {
                    throw new SecurityException("No entries were found that matched the provided information");
                }

                for (String lineEntry : FileUtils.readLines(passwordFile, systemConfig.getEncoding())) {
                    passwordEntryName = lineEntry.split(",")[0];

                    if (DEBUG) {
                        DEBUGGER.debug("String passwordEntryName: {}", passwordEntryName);
                    }

                    if (StringUtils.equals(passwordEntryName, saltEntryName)) {
                        String decodedPassword = PasswordUtils.base64Decode(lineEntry.split(",")[2]);

                        decryptedPassword = PasswordUtils.decryptText(decodedPassword, saltEntryValue,
                                secConfig.getSecretAlgorithm(), secConfig.getIterations(), secConfig.getKeyBits(),
                                secConfig.getEncryptionAlgorithm(), secConfig.getEncryptionInstance(),
                                systemConfig.getEncoding());

                        break;
                    }
                }

                if (StringUtils.isEmpty(decryptedPassword)) {
                    throw new SecurityException("No entries were found that matched the provided information");
                }

                System.out.println(decryptedPassword);
            } else if (commandLine.hasOption("encode")) {
                System.out.println(PasswordUtils.base64Encode((String) commandLine.getArgList().get(0)));
            } else if (commandLine.hasOption("decode")) {
                System.out.println(PasswordUtils.base64Decode((String) commandLine.getArgList().get(0)));
            }
        } catch (IOException iox) {
            ERROR_RECORDER.error(iox.getMessage(), iox);

            System.err.println("An error occurred during processing: " + iox.getMessage());
            System.exit(1);
        } catch (ParseException px) {
            ERROR_RECORDER.error(px.getMessage(), px);

            System.err.println("An error occurred during processing: " + px.getMessage());
            System.exit(1);
        } catch (SecurityException sx) {
            ERROR_RECORDER.error(sx.getMessage(), sx);

            System.err.println("An error occurred during processing: " + sx.getMessage());
            System.exit(1);
        } catch (SecurityServiceException ssx) {
            ERROR_RECORDER.error(ssx.getMessage(), ssx);
            System.exit(1);
        } finally {
            try {
                if (bReader != null) {
                    bReader.close();
                }

                if (bWriter != null) {
                    bReader.close();
                }
            } catch (IOException iox) {
            }
        }

        System.exit(0);
    }
}