EncodePassword.java revision ff1293486c5e276c25f0c2c040ffda78520249c5
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2006-2010 Sun Microsystems, Inc.
* Portions Copyright 2011-2015 ForgeRock AS.
*/
/**
* This program provides a utility that may be used to interact with the
* password storage schemes defined in the Directory Server. In particular,
* it can encode a clear-text password using a specified scheme, and it can also
* determine whether a given encoded password is the encoded representation of a
* given clear-text password. Alternately, it can be used to obtain a list of
* the available password storage scheme names.
*/
public class EncodePassword
{
/**
* Processes the command-line arguments and performs the requested action.
*
* @param args The command-line arguments provided to this program.
*/
{
if (returnCode != 0)
{
}
}
/**
* Processes the command-line arguments and performs the requested action.
*
* @param args The command-line arguments provided to this program.
*
* @return An integer value that indicates whether processing was successful.
*/
{
}
/**
* Processes the command-line arguments and performs the requested action.
*
* @param args The command-line arguments provided to this
* program.
* @param initializeServer Indicates whether to initialize the server.
* @param outStream The output stream to use for standard output, or
* <CODE>null</CODE> if standard output is not
* needed.
* @param errStream The output stream to use for standard error, or
* <CODE>null</CODE> if standard error is not
* needed.
*
* @return An integer value that indicates whether processing was successful.
*/
{
// Define the command-line arguments that may be used with this program.
// Create the command-line argument parser for use with this program.
new ArgumentParser("org.opends.server.tools.EncodePassword",
toolDescription, false);
// Initialize all the command-line argument types and register them with the
// parser.
try
{
listSchemes = new BooleanArgument(
"listschemes", 'l', "listSchemes",
"interactivePassword", 'i',
"interactivePassword",
false, true, INFO_CLEAR_PWD.get(),
encodedPassword = new StringArgument(
"encodedpw", 'e', "encodedPassword",
false, false, true, INFO_ENCODED_PWD_PLACEHOLDER.get(),
false, false, INFO_FILE_PLACEHOLDER.get(),
true, false, true,
configClass.setHidden(true);
true, false, true,
null,
configFile.setHidden(true);
false, true,
"authpasswordsyntax", 'a',
"authPasswordSyntax",
"useCompareResultCode",
}
catch (ArgumentException ae)
{
return OPERATIONS_ERROR;
}
// Parse the command-line arguments provided to this program.
try
{
}
catch (ArgumentException ae)
{
return OPERATIONS_ERROR;
}
// If we should just display usage or version information,
// then we've already done it so just return without doing anything else.
if (argParser.usageOrVersionDisplayed())
{
return SUCCESS;
}
// Checks the version - if upgrade required, the tool is unusable
try
{
}
catch (InitializationException e)
{
return 1;
}
// Check for conflicting arguments.
{
ERR_TOOL_CONFLICTING_ARGS.get(clearPassword.getLongIdentifier(), clearPasswordFile.getLongIdentifier()));
return OPERATIONS_ERROR;
}
{
ERR_TOOL_CONFLICTING_ARGS.get(clearPassword.getLongIdentifier(), interactivePassword.getLongIdentifier()));
return OPERATIONS_ERROR;
}
{
return OPERATIONS_ERROR;
}
{
ERR_TOOL_CONFLICTING_ARGS.get(encodedPassword.getLongIdentifier(), encodedPasswordFile.getLongIdentifier()));
return OPERATIONS_ERROR;
}
// If we are not going to just list the storage schemes, then the clear-text
// password must have been provided. If we're going to encode a password,
// then the scheme must have also been provided.
if (!listSchemes.isPresent()
&& !encodedPassword.isPresent()
&& !encodedPasswordFile.isPresent()
&& !schemeName.isPresent())
{
argParser.displayMessageAndUsageReference(err, ERR_ENCPW_NO_SCHEME.get(schemeName.getLongIdentifier()));
return OPERATIONS_ERROR;
}
// Determine whether we're encoding the clear-text password or comparing it
// against an already-encoded password.
boolean compareMode;
if (encodedPassword.hasValue())
{
compareMode = true;
}
else if (encodedPasswordFile.hasValue())
{
compareMode = true;
}
else
{
compareMode = false;
}
// Perform the initial bootstrap of the Directory Server and process the
// configuration.
if (initializeServer)
{
try
{
}
catch (Exception e)
{
return OPERATIONS_ERROR;
}
try
{
configFile.getValue());
}
catch (InitializationException ie)
{
return OPERATIONS_ERROR;
}
catch (Exception e)
{
return OPERATIONS_ERROR;
}
// Initialize the Directory Server schema elements.
try
{
}
catch (ConfigException | InitializationException e)
{
return OPERATIONS_ERROR;
}
catch (Exception e)
{
return OPERATIONS_ERROR;
}
// Initialize the Directory Server core configuration.
try
{
}
catch (ConfigException | InitializationException e)
{
return OPERATIONS_ERROR;
}
catch (Exception e)
{
return OPERATIONS_ERROR;
}
{
return -1;
}
// Initialize the password storage schemes.
try
{
}
catch (ConfigException | InitializationException e)
{
return OPERATIONS_ERROR;
}
catch (Exception e)
{
return OPERATIONS_ERROR;
}
}
// If we are only trying to list the available schemes, then do so and exit.
if (listSchemes.isPresent())
{
if (authPasswordSyntax.isPresent())
{
}
else
{
}
return SUCCESS;
}
// Either encode the clear-text password using the provided scheme, or
// compare the clear-text password against the encoded password.
if (compareMode)
{
// Check to see if the provided password value was encoded. If so, then
// break it down into its component parts and use that to perform the
// comparison. Otherwise, the user must have provided the storage scheme.
if (authPasswordSyntax.isPresent())
{
try
{
}
catch (DirectoryException de)
{
return OPERATIONS_ERROR;
}
catch (Exception e)
{
return OPERATIONS_ERROR;
}
if (storageScheme == null)
{
return OPERATIONS_ERROR;
}
{
{
return OPERATIONS_ERROR;
}
}
final boolean authPasswordMatches =
if (useCompareResultCode.isPresent())
{
}
return SUCCESS;
}
else
{
{
try
{
String[] userPWElements =
if (storageScheme == null)
{
return OPERATIONS_ERROR;
}
}
catch (DirectoryException de)
{
return OPERATIONS_ERROR;
}
catch (Exception e)
{
return OPERATIONS_ERROR;
}
}
else
{
if (! schemeName.isPresent())
{
return OPERATIONS_ERROR;
}
if (storageScheme == null)
{
return OPERATIONS_ERROR;
}
}
{
{
return OPERATIONS_ERROR;
}
}
boolean passwordMatches =
if (useCompareResultCode.isPresent())
{
}
return SUCCESS;
}
}
else
{
// Try to get a reference to the requested password storage scheme.
if (authPasswordSyntax.isPresent())
{
if (storageScheme == null)
{
return OPERATIONS_ERROR;
}
}
else
{
if (storageScheme == null)
{
return OPERATIONS_ERROR;
}
}
if (authPasswordSyntax.isPresent())
{
try
{
{
{
return OPERATIONS_ERROR;
}
}
}
catch (DirectoryException de)
{
return OPERATIONS_ERROR;
}
catch (Exception e)
{
return OPERATIONS_ERROR;
}
}
else
{
try
{
{
{
return OPERATIONS_ERROR;
}
}
}
catch (DirectoryException de)
{
return OPERATIONS_ERROR;
}
catch (Exception e)
{
return OPERATIONS_ERROR;
}
}
}
// If we've gotten here, then all processing completed successfully.
return SUCCESS;
}
{
if (storageSchemes.isEmpty())
{
}
else
{
{
{
}
else
{
}
}
{
}
}
}
{
if (passwordMatches)
{
return INFO_ENCPW_PASSWORDS_MATCH.get();
}
return INFO_ENCPW_PASSWORDS_DO_NOT_MATCH.get();
}
{
// Initialize the Directory Server crypto manager.
try
{
}
catch (ConfigException | InitializationException e)
{
return false;
}
catch (Exception e)
{
return false;
}
//Attempt to bring up enough of the server to process schemes requiring
//secret keys from the trust store backend (3DES, BLOWFISH, AES, RC4) via
//the crypto-manager.
try {
new CryptoManagerSync();
} catch (InitializationException | ConfigException e) {
return false;
}
return true;
}
throws InitializationException, ConfigException {
try {
} catch (Exception e) {
getExceptionMessage(e));
throw new ConfigException(message, e);
}
if (backendRoot == null) {
throw new ConfigException(message);
}
if((backendCfg instanceof TrustStoreBackendCfg
|| backendCfg instanceof LDIFBackendCfg)
&& backendCfg.isEnabled())
{
Class<?> backendClass;
try {
} catch (Exception e) {
ERR_CONFIG_BACKEND_CANNOT_INSTANTIATE.get(className, backendCfg.dn(), stackTraceToSingleLineString(e)));
continue;
}
try {
} catch (Exception e) {
ERR_CONFIG_BACKEND_CANNOT_INITIALIZE.get(className, backendCfg.dn(), stackTraceToSingleLineString(e)));
}
try {
} catch (Exception e)
{
err, WARN_CONFIG_BACKEND_CANNOT_REGISTER_BACKEND.get(backendCfg.getBackendId(), getExceptionMessage(e)));
}
}
}
}
/**
* Get the clear password.
* @param out The output to ask password.
* @param err The error output.
* @param argParser The argument parser.
* @param clearPassword the clear password
* @param clearPasswordFile the file in which the password in stored
* @param interactivePassword indicate if the password should be asked
* interactively.
* @return the password or null if an error occurs.
*/
{
if (clearPassword.hasValue())
{
}
else if (clearPasswordFile.hasValue())
{
}
else if (interactivePassword.isPresent())
{
try
{
{
}
else
{
return null;
}
}
catch (IOException e)
{
return null;
}
}
else
{
argParser.displayMessageAndUsageReference(err, ERR_ENCPW_NO_CLEAR_PW.get(clearPassword.getLongIdentifier(),
return null;
}
}
/**
* Get the password from JDK6 console or from masked password.
* @param prompt The message to print out.
* @return the password
* @throws IOException if an issue occurs when reading the password
* from the input
*/
{
try
{
{
throw new IOException("No console");
}
}
catch (Exception e)
{
// Try the fallback to the old trick method.
// Create the thread that will erase chars
password = "";
// block until enter is pressed
while (true)
{
// assume enter pressed, stop masking
if (c == '\r')
{
if (c == '\n')
{
break;
}
}
else if (c == '\n')
{
break;
}
else
{
// store the password
password += c;
}
}
}
return password;
}
/**
* Thread that mask user input.
*/
private class ErasingThread extends Thread
{
private boolean stop;
/**
* The class will mask the user input.
* @param prompt
* The prompt displayed to the user
*/
{
}
/**
* Begin masking until asked to stop.
*/
public void run()
{
while (!stop)
{
try
{
// attempt masking at this rate
}
catch (InterruptedException iex)
{
}
if (!stop)
{
}
}
}
/**
* Instruct the thread to stop masking.
*/
public void stopMasking()
{
this.stop = true;
}
}
}