mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

neil_a_wilson
14.23.2006 c369bb65ccddc6c59feb5db6c80ad4a7fb2baafe
Make a number of changes to the encode-password tool:

- It is no longer necessary to specify the password storage scheme separately
from the encoded value when comparing an encoded password. This makes this
feature easier to use because it takes the data in the same format as is
created by when encoding a clear-text password and as is stored in the
directory. Issue #971.

- When comparing a clear-text password against an encoded version, you can now
use the --useCompareResultCode option to cause the tool to exit with a return
code of COMPARE_TRUE or COMPARE_FALSE, which is more useful when calling the
utility in a script. Previously, it would always return zero to indicate
that the script completed successfully, regardless of whether the provided
password matched or not. Issue #988.

- I've made the tool easier to call programmatically by adding additional
methods that can be used to invoke it, by making it possible to avoid
reinitializing the server, to provide alternate output and error streams (or
eliminate the output entirely), and to return an integer value rather than
using System.exit. This all kind of falls under the umbrella of issue #987.
1 files added
2 files modified
1400 ■■■■ changed files
opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java 26 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/tools/EncodePassword.java 603 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/EncodePasswordTestCase.java 771 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java
@@ -7302,6 +7302,26 @@
            CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 747;
  /**
   * The message ID for the message that will be used if the encoded password is
   * not valid according to the user password syntax.  This takes a single
   * argument, which is a message explaining why it is invalid.
   */
  public static final int MSGID_ENCPW_INVALID_ENCODED_USERPW =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 748;
  /**
   * The message ID for the message that will be used as the description of the
   * useCompareResultCode argument.  This does not take any arguments.
   */
  public static final int MSGID_ENCPW_DESCRIPTION_USE_COMPARE_RESULT =
       CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 749;
  /**
   * Associates a set of generic messages with the message IDs defined in this
   * class.
@@ -7349,6 +7369,9 @@
    registerMessage(MSGID_ENCPW_DESCRIPTION_AUTHPW,
                    "Use the authentication password syntax rather than the " +
                    "user password syntax");
    registerMessage(MSGID_ENCPW_DESCRIPTION_USE_COMPARE_RESULT,
                    "Use the LDAP compare result as an exit code for the " +
                    "password comparison");
    registerMessage(MSGID_ENCPW_DESCRIPTION_USAGE,
                    "Displays this usage information.");
    registerMessage(MSGID_ENCPW_CANNOT_INITIALIZE_ARGS,
@@ -7398,6 +7421,9 @@
    registerMessage(MSGID_ENCPW_PASSWORDS_DO_NOT_MATCH,
                    "The provided clear-text and encoded passwords do not " +
                    "match.");
    registerMessage(MSGID_ENCPW_INVALID_ENCODED_USERPW,
                    "The provided password is not a valid encoded " +
                    "user password value:  %s.");
    registerMessage(MSGID_ENCPW_ENCODED_PASSWORD,
                    "Encoded Password:  \"%s\".");
    registerMessage(MSGID_ENCPW_CANNOT_ENCODE,
opendj-sdk/opends/src/server/org/opends/server/tools/EncodePassword.java
@@ -28,6 +28,8 @@
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.ConcurrentHashMap;
@@ -39,10 +41,13 @@
import org.opends.server.core.PasswordStorageSchemeConfigManager;
import org.opends.server.extensions.ConfigFileHandler;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.schema.AuthPasswordSyntax;
import org.opends.server.schema.UserPasswordSyntax;
import org.opends.server.types.ByteString;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.InitializationException;
import org.opends.server.types.NullOutputStream;
import org.opends.server.util.args.ArgumentException;
import org.opends.server.util.args.ArgumentParser;
import org.opends.server.util.args.BooleanArgument;
@@ -74,17 +79,80 @@
   */
  public static void main(String[] args)
  {
    int returnCode = encodePassword(args, true, System.out, System.err);
    if (returnCode != 0)
    {
      System.exit(returnCode);
    }
  }
  /**
   * 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.
   */
  public static int encodePassword(String[] args)
  {
    return encodePassword(args, true, System.out, System.err);
  }
  /**
   * 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.
   */
  public static int encodePassword(String[] args, boolean initializeServer,
                                   OutputStream outStream,
                                   OutputStream errStream)
  {
    PrintStream out;
    if (outStream == null)
    {
      out = NullOutputStream.printStream();
    }
    else
    {
      out = new PrintStream(outStream);
    }
    PrintStream err;
    if (errStream == null)
    {
      err = NullOutputStream.printStream();
    }
    else
    {
      err = new PrintStream(errStream);
    }
    // Define the command-line arguments that may be used with this program.
    BooleanArgument   authPasswordSyntax  = null;
    BooleanArgument   listSchemes         = null;
    BooleanArgument   showUsage           = null;
    StringArgument    clearPassword       = null;
    FileBasedArgument clearPasswordFile   = null;
    StringArgument    encodedPassword     = null;
    FileBasedArgument encodedPasswordFile = null;
    StringArgument    configClass         = null;
    StringArgument    configFile          = null;
    StringArgument    schemeName          = null;
    BooleanArgument   authPasswordSyntax   = null;
    BooleanArgument   useCompareResultCode = null;
    BooleanArgument   listSchemes          = null;
    BooleanArgument   showUsage            = null;
    StringArgument    clearPassword        = null;
    FileBasedArgument clearPasswordFile    = null;
    StringArgument    encodedPassword      = null;
    FileBasedArgument encodedPasswordFile  = null;
    StringArgument    configClass          = null;
    StringArgument    configFile           = null;
    StringArgument    schemeName           = null;
    // Create the command-line argument parser for use with this program.
@@ -158,18 +226,25 @@
      argParser.addArgument(authPasswordSyntax);
      useCompareResultCode =
           new BooleanArgument("usecompareresultcode", 'r',
                               "useCompareResultCode",
                               MSGID_ENCPW_DESCRIPTION_USE_COMPARE_RESULT);
      argParser.addArgument(useCompareResultCode);
      showUsage = new BooleanArgument("usage", 'H', "help",
                                      MSGID_ENCPW_DESCRIPTION_USAGE);
      argParser.addArgument(showUsage);
      argParser.setUsageArgument(showUsage);
      argParser.setUsageArgument(showUsage, out);
    }
    catch (ArgumentException ae)
    {
      int    msgID   = MSGID_ENCPW_CANNOT_INITIALIZE_ARGS;
      String message = getMessage(msgID, ae.getMessage());
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      System.exit(1);
      err.println(wrapText(message, MAX_LINE_WIDTH));
      return 1;
    }
@@ -183,21 +258,43 @@
      int    msgID   = MSGID_ENCPW_ERROR_PARSING_ARGS;
      String message = getMessage(msgID, ae.getMessage());
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      System.err.println(argParser.getUsage());
      System.exit(1);
      err.println(wrapText(message, MAX_LINE_WIDTH));
      err.println(argParser.getUsage());
      return 1;
    }
    // If we should just display usage information, then print it and exit.
    // If we should just display usage information, then we've already done it
    // so just return without doing anything else.
    if (showUsage.isPresent())
    {
      System.exit(0);
      return 0;
    }
    // If we are not going to just list the storage schemes, then the clear
    // password and scheme name must have been provided.
    // Check for conflicting arguments.
    if (clearPassword.isPresent() && clearPasswordFile.isPresent())
    {
      int    msgID   = MSGID_TOOL_CONFLICTING_ARGS;
      String message = getMessage(msgID, clearPassword.getLongIdentifier(),
                                  clearPasswordFile.getLongIdentifier());
      err.println(wrapText(message, MAX_LINE_WIDTH));
      return 1;
    }
    if (encodedPassword.isPresent() && encodedPasswordFile.isPresent())
    {
      int    msgID   = MSGID_TOOL_CONFLICTING_ARGS;
      String message = getMessage(msgID, encodedPassword.getLongIdentifier(),
                                  encodedPasswordFile.getLongIdentifier());
      err.println(wrapText(message, MAX_LINE_WIDTH));
      return 1;
    }
    // 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.
    ASN1OctetString clearPW = null;
    if (! listSchemes.isPresent())
    {
@@ -214,18 +311,18 @@
        int    msgID = MSGID_ENCPW_NO_CLEAR_PW;
        String message = getMessage(msgID, clearPassword.getLongIdentifier(),
                                    clearPasswordFile.getLongIdentifier());
        System.err.println(wrapText(message, MAX_LINE_WIDTH));
        System.err.println(argParser.getUsage());
        System.exit(1);
        err.println(wrapText(message, MAX_LINE_WIDTH));
        err.println(argParser.getUsage());
        return 1;
      }
      if (! schemeName.hasValue())
      if ((! encodedPassword.isPresent()) && (! schemeName.isPresent()))
      {
        int    msgID   = MSGID_ENCPW_NO_SCHEME;
        String message = getMessage(msgID, schemeName.getLongIdentifier());
        System.err.println(wrapText(message, MAX_LINE_WIDTH));
        System.err.println(argParser.getUsage());
        System.exit(1);
        err.println(wrapText(message, MAX_LINE_WIDTH));
        err.println(argParser.getUsage());
        return 1;
      }
    }
@@ -249,125 +346,128 @@
    // configuration.
    DirectoryServer directoryServer = DirectoryServer.getInstance();
    try
    if (initializeServer)
    {
      directoryServer.bootstrapClient();
      directoryServer.initializeJMX();
    }
    catch (Exception e)
    {
      int msgID = MSGID_ENCPW_SERVER_BOOTSTRAP_ERROR;
      String message = getMessage(msgID, stackTraceToSingleLineString(e));
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      System.exit(1);
    }
      try
      {
        directoryServer.bootstrapClient();
        directoryServer.initializeJMX();
      }
      catch (Exception e)
      {
        int msgID = MSGID_ENCPW_SERVER_BOOTSTRAP_ERROR;
        String message = getMessage(msgID, stackTraceToSingleLineString(e));
        err.println(wrapText(message, MAX_LINE_WIDTH));
        return 1;
      }
    try
    {
      directoryServer.initializeConfiguration(configClass.getValue(),
                                              configFile.getValue());
    }
    catch (InitializationException ie)
    {
      int    msgID   = MSGID_ENCPW_CANNOT_LOAD_CONFIG;
      String message = getMessage(msgID, ie.getMessage());
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      System.exit(1);
    }
    catch (Exception e)
    {
      int    msgID   = MSGID_ENCPW_CANNOT_LOAD_CONFIG;
      String message = getMessage(msgID, stackTraceToSingleLineString(e));
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      System.exit(1);
    }
      try
      {
        directoryServer.initializeConfiguration(configClass.getValue(),
                                                configFile.getValue());
      }
      catch (InitializationException ie)
      {
        int    msgID   = MSGID_ENCPW_CANNOT_LOAD_CONFIG;
        String message = getMessage(msgID, ie.getMessage());
        err.println(wrapText(message, MAX_LINE_WIDTH));
        return 1;
      }
      catch (Exception e)
      {
        int    msgID   = MSGID_ENCPW_CANNOT_LOAD_CONFIG;
        String message = getMessage(msgID, stackTraceToSingleLineString(e));
        err.println(wrapText(message, MAX_LINE_WIDTH));
        return 1;
      }
    // Initialize the Directory Server schema elements.
    try
    {
      directoryServer.initializeSchema();
    }
    catch (ConfigException ce)
    {
      int    msgID   = MSGID_ENCPW_CANNOT_LOAD_SCHEMA;
      String message = getMessage(msgID, ce.getMessage());
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      System.exit(1);
    }
    catch (InitializationException ie)
    {
      int    msgID   = MSGID_ENCPW_CANNOT_LOAD_SCHEMA;
      String message = getMessage(msgID, ie.getMessage());
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      System.exit(1);
    }
    catch (Exception e)
    {
      int    msgID   = MSGID_ENCPW_CANNOT_LOAD_SCHEMA;
      String message = getMessage(msgID, stackTraceToSingleLineString(e));
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      System.exit(1);
    }
      // Initialize the Directory Server schema elements.
      try
      {
        directoryServer.initializeSchema();
      }
      catch (ConfigException ce)
      {
        int    msgID   = MSGID_ENCPW_CANNOT_LOAD_SCHEMA;
        String message = getMessage(msgID, ce.getMessage());
        err.println(wrapText(message, MAX_LINE_WIDTH));
        return 1;
      }
      catch (InitializationException ie)
      {
        int    msgID   = MSGID_ENCPW_CANNOT_LOAD_SCHEMA;
        String message = getMessage(msgID, ie.getMessage());
        err.println(wrapText(message, MAX_LINE_WIDTH));
        return 1;
      }
      catch (Exception e)
      {
        int    msgID   = MSGID_ENCPW_CANNOT_LOAD_SCHEMA;
        String message = getMessage(msgID, stackTraceToSingleLineString(e));
        err.println(wrapText(message, MAX_LINE_WIDTH));
        return 1;
      }
    // Initialize the Directory Server core configuration.
    try
    {
      CoreConfigManager coreConfigManager = new CoreConfigManager();
      coreConfigManager.initializeCoreConfig();
    }
    catch (ConfigException ce)
    {
      int    msgID   = MSGID_ENCPW_CANNOT_INITIALIZE_CORE_CONFIG;
      String message = getMessage(msgID, ce.getMessage());
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      System.exit(1);
    }
    catch (InitializationException ie)
    {
      int    msgID   = MSGID_ENCPW_CANNOT_INITIALIZE_CORE_CONFIG;
      String message = getMessage(msgID, ie.getMessage());
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      System.exit(1);
    }
    catch (Exception e)
    {
      int    msgID   = MSGID_ENCPW_CANNOT_INITIALIZE_CORE_CONFIG;
      String message = getMessage(msgID, stackTraceToSingleLineString(e));
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      System.exit(1);
    }
      // Initialize the Directory Server core configuration.
      try
      {
        CoreConfigManager coreConfigManager = new CoreConfigManager();
        coreConfigManager.initializeCoreConfig();
      }
      catch (ConfigException ce)
      {
        int    msgID   = MSGID_ENCPW_CANNOT_INITIALIZE_CORE_CONFIG;
        String message = getMessage(msgID, ce.getMessage());
        err.println(wrapText(message, MAX_LINE_WIDTH));
        return 1;
      }
      catch (InitializationException ie)
      {
        int    msgID   = MSGID_ENCPW_CANNOT_INITIALIZE_CORE_CONFIG;
        String message = getMessage(msgID, ie.getMessage());
        err.println(wrapText(message, MAX_LINE_WIDTH));
        return 1;
      }
      catch (Exception e)
      {
        int    msgID   = MSGID_ENCPW_CANNOT_INITIALIZE_CORE_CONFIG;
        String message = getMessage(msgID, stackTraceToSingleLineString(e));
        err.println(wrapText(message, MAX_LINE_WIDTH));
        return 1;
      }
    // Initialize the password storage schemes.
    try
    {
      PasswordStorageSchemeConfigManager storageSchemeConfigManager =
           new PasswordStorageSchemeConfigManager();
      storageSchemeConfigManager.initializePasswordStorageSchemes();
    }
    catch (ConfigException ce)
    {
      int    msgID   = MSGID_ENCPW_CANNOT_INITIALIZE_STORAGE_SCHEMES;
      String message = getMessage(msgID, ce.getMessage());
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      System.exit(1);
    }
    catch (InitializationException ie)
    {
      int    msgID   = MSGID_ENCPW_CANNOT_INITIALIZE_STORAGE_SCHEMES;
      String message = getMessage(msgID, ie.getMessage());
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      System.exit(1);
    }
    catch (Exception e)
    {
      int    msgID   = MSGID_ENCPW_CANNOT_INITIALIZE_STORAGE_SCHEMES;
      String message = getMessage(msgID, stackTraceToSingleLineString(e));
      System.err.println(wrapText(message, MAX_LINE_WIDTH));
      System.exit(1);
      // Initialize the password storage schemes.
      try
      {
        PasswordStorageSchemeConfigManager storageSchemeConfigManager =
             new PasswordStorageSchemeConfigManager();
        storageSchemeConfigManager.initializePasswordStorageSchemes();
      }
      catch (ConfigException ce)
      {
        int    msgID   = MSGID_ENCPW_CANNOT_INITIALIZE_STORAGE_SCHEMES;
        String message = getMessage(msgID, ce.getMessage());
        err.println(wrapText(message, MAX_LINE_WIDTH));
        return 1;
      }
      catch (InitializationException ie)
      {
        int    msgID   = MSGID_ENCPW_CANNOT_INITIALIZE_STORAGE_SCHEMES;
        String message = getMessage(msgID, ie.getMessage());
        err.println(wrapText(message, MAX_LINE_WIDTH));
        return 1;
      }
      catch (Exception e)
      {
        int    msgID   = MSGID_ENCPW_CANNOT_INITIALIZE_STORAGE_SCHEMES;
        String message = getMessage(msgID, stackTraceToSingleLineString(e));
        err.println(wrapText(message, MAX_LINE_WIDTH));
        return 1;
      }
    }
@@ -382,7 +482,7 @@
        {
          int msgID = MSGID_ENCPW_NO_STORAGE_SCHEMES;
          String message = getMessage(msgID);
          System.err.println(wrapText(message, MAX_LINE_WIDTH));
          err.println(wrapText(message, MAX_LINE_WIDTH));
        }
        else
        {
@@ -400,11 +500,11 @@
          for (String storageSchemeName : nameArray)
          {
            System.out.println(storageSchemeName);
            out.println(storageSchemeName);
          }
        }
        System.exit(0);
        return 0;
      }
      else
      {
@@ -414,7 +514,7 @@
        {
          int msgID = MSGID_ENCPW_NO_STORAGE_SCHEMES;
          String message = getMessage(msgID);
          System.err.println(wrapText(message, MAX_LINE_WIDTH));
          err.println(wrapText(message, MAX_LINE_WIDTH));
        }
        else
        {
@@ -432,39 +532,11 @@
          for (String storageSchemeName : nameArray)
          {
            System.out.println(storageSchemeName);
            out.println(storageSchemeName);
          }
        }
        System.exit(0);
      }
    }
    // Try to get a reference to the requested password storage scheme.
    PasswordStorageScheme storageScheme;
    if (authPasswordSyntax.isPresent())
    {
      String scheme = schemeName.getValue();
      storageScheme = DirectoryServer.getAuthPasswordStorageScheme(scheme);
      if (storageScheme == null)
      {
        int    msgID   = MSGID_ENCPW_NO_SUCH_AUTH_SCHEME;
        String message = getMessage(msgID, scheme);
        System.err.println(wrapText(message, MAX_LINE_WIDTH));
        System.exit(1);
      }
    }
    else
    {
      String scheme = toLowerCase(schemeName.getValue());
      storageScheme = DirectoryServer.getPasswordStorageScheme(scheme);
      if (storageScheme == null)
      {
        int    msgID   = MSGID_ENCPW_NO_SUCH_SCHEME;
        String message = getMessage(msgID, scheme);
        System.err.println(wrapText(message, MAX_LINE_WIDTH));
        System.exit(1);
        return 0;
      }
    }
@@ -473,15 +545,20 @@
    // 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())
      {
        String authInfo  = null;
        String authValue = null;
        String scheme;
        String authInfo;
        String authValue;
        try
        {
          String encodedPWString = encodedPassword.getValue();
          StringBuilder[] authPWElements =
               AuthPasswordSyntax.decodeAuthPassword(encodedPWString);
               AuthPasswordSyntax.decodeAuthPassword(encodedPW.stringValue());
          scheme    = authPWElements[0].toString();
          authInfo  = authPWElements[1].toString();
          authValue = authPWElements[2].toString();
        }
@@ -489,48 +566,181 @@
        {
          int    msgID   = MSGID_ENCPW_INVALID_ENCODED_AUTHPW;
          String message = getMessage(msgID, de.getErrorMessage());
          System.err.println(wrapText(message, MAX_LINE_WIDTH));
          System.exit(1);
          err.println(wrapText(message, MAX_LINE_WIDTH));
          return 1;
        }
        catch (Exception e)
        {
          int    msgID   = MSGID_ENCPW_INVALID_ENCODED_AUTHPW;
          String message = getMessage(msgID, e);
          System.err.println(wrapText(message, MAX_LINE_WIDTH));
          System.exit(1);
          String message = getMessage(msgID, String.valueOf(e));
          err.println(wrapText(message, MAX_LINE_WIDTH));
          return 1;
        }
        PasswordStorageScheme storageScheme =
             DirectoryServer.getAuthPasswordStorageScheme(scheme);
        if (storageScheme == null)
        {
          int    msgID   = MSGID_ENCPW_NO_SUCH_AUTH_SCHEME;
          String message = getMessage(msgID, scheme);
          err.println(wrapText(message, MAX_LINE_WIDTH));
          return 1;
        }
        if (storageScheme.authPasswordMatches(clearPW, authInfo, authValue))
        {
          int    msgID   = MSGID_ENCPW_PASSWORDS_MATCH;
          String message = getMessage(msgID);
          System.out.println(wrapText(message, MAX_LINE_WIDTH));
          out.println(message);
          if (useCompareResultCode.isPresent())
          {
            return LDAPResultCode.COMPARE_TRUE;
          }
          else
          {
            return 0;
          }
        }
        else
        {
          int    msgID   = MSGID_ENCPW_PASSWORDS_DO_NOT_MATCH;
          String message = getMessage(msgID);
          System.out.println(wrapText(message, MAX_LINE_WIDTH));
          out.println(message);
          if (useCompareResultCode.isPresent())
          {
            return LDAPResultCode.COMPARE_FALSE;
          }
          else
          {
            return 0;
          }
        }
      }
      else
      {
        if (storageScheme.passwordMatches(clearPW, encodedPW))
        PasswordStorageScheme storageScheme;
        String                encodedPWString;
        if (UserPasswordSyntax.isEncoded(encodedPW))
        {
          try
          {
            String[] userPWElements =
                 UserPasswordSyntax.decodeUserPassword(encodedPW.stringValue());
            encodedPWString = userPWElements[1];
            storageScheme =
                 DirectoryServer.getPasswordStorageScheme(userPWElements[0]);
            if (storageScheme == null)
            {
              int    msgID   = MSGID_ENCPW_NO_SUCH_SCHEME;
              String message = getMessage(msgID, userPWElements[0]);
              err.println(wrapText(message, MAX_LINE_WIDTH));
              return 1;
            }
          }
          catch (DirectoryException de)
          {
            int    msgID   = MSGID_ENCPW_INVALID_ENCODED_USERPW;
            String message = getMessage(msgID, de.getErrorMessage());
            err.println(wrapText(message, MAX_LINE_WIDTH));
            return 1;
          }
          catch (Exception e)
          {
            int    msgID   = MSGID_ENCPW_INVALID_ENCODED_USERPW;
            String message = getMessage(msgID, String.valueOf(e));
            err.println(wrapText(message, MAX_LINE_WIDTH));
            return 1;
          }
        }
        else
        {
          if (! schemeName.isPresent())
          {
            int    msgID   = MSGID_ENCPW_NO_SCHEME;
            String message = getMessage(msgID, schemeName.getLongIdentifier());
            err.println(wrapText(message, MAX_LINE_WIDTH));
            return 1;
          }
          encodedPWString = encodedPW.toString();
          String scheme = toLowerCase(schemeName.getValue());
          storageScheme = directoryServer.getPasswordStorageScheme(scheme);
          if (storageScheme == null)
          {
            int    msgID   = MSGID_ENCPW_NO_SUCH_SCHEME;
            String message = getMessage(msgID, scheme);
            err.println(wrapText(message, MAX_LINE_WIDTH));
            return 1;
          }
        }
        if (storageScheme.passwordMatches(clearPW,
                                          new ASN1OctetString(encodedPWString)))
        {
          int    msgID   = MSGID_ENCPW_PASSWORDS_MATCH;
          String message = getMessage(msgID);
          System.out.println(wrapText(message, MAX_LINE_WIDTH));
          out.println(message);
          if (useCompareResultCode.isPresent())
          {
            return LDAPResultCode.COMPARE_TRUE;
          }
          else
          {
            return 0;
          }
        }
        else
        {
          int    msgID   = MSGID_ENCPW_PASSWORDS_DO_NOT_MATCH;
          String message = getMessage(msgID);
          System.out.println(wrapText(message, MAX_LINE_WIDTH));
          out.println(message);
          if (useCompareResultCode.isPresent())
          {
            return LDAPResultCode.COMPARE_FALSE;
          }
          else
          {
            return 0;
          }
        }
      }
    }
    else
    {
      // Try to get a reference to the requested password storage scheme.
      PasswordStorageScheme storageScheme;
      if (authPasswordSyntax.isPresent())
      {
        String scheme = schemeName.getValue();
        storageScheme = DirectoryServer.getAuthPasswordStorageScheme(scheme);
        if (storageScheme == null)
        {
          int    msgID   = MSGID_ENCPW_NO_SUCH_AUTH_SCHEME;
          String message = getMessage(msgID, scheme);
          err.println(wrapText(message, MAX_LINE_WIDTH));
          return 1;
        }
      }
      else
      {
        String scheme = toLowerCase(schemeName.getValue());
        storageScheme = DirectoryServer.getPasswordStorageScheme(scheme);
        if (storageScheme == null)
        {
          int    msgID   = MSGID_ENCPW_NO_SUCH_SCHEME;
          String message = getMessage(msgID, scheme);
          err.println(wrapText(message, MAX_LINE_WIDTH));
          return 1;
        }
      }
      if (authPasswordSyntax.isPresent())
      {
        try
@@ -539,21 +749,21 @@
          int    msgID   = MSGID_ENCPW_ENCODED_PASSWORD;
          String message = getMessage(msgID, encodedPW.stringValue());
          System.out.println(message);
          out.println(message);
        }
        catch (DirectoryException de)
        {
          int msgID = MSGID_ENCPW_CANNOT_ENCODE;
          String message = getMessage(msgID, de.getErrorMessage());
          System.err.println(wrapText(message, MAX_LINE_WIDTH));
          System.exit(1);
          err.println(wrapText(message, MAX_LINE_WIDTH));
          return 1;
        }
        catch (Exception e)
        {
          int msgID = MSGID_ENCPW_CANNOT_ENCODE;
          String message = getMessage(msgID, stackTraceToSingleLineString(e));
          System.err.println(wrapText(message, MAX_LINE_WIDTH));
          System.exit(1);
          err.println(wrapText(message, MAX_LINE_WIDTH));
          return 1;
        }
      }
      else
@@ -564,24 +774,27 @@
          int    msgID   = MSGID_ENCPW_ENCODED_PASSWORD;
          String message = getMessage(msgID, encodedPW.stringValue());
          System.out.println(message);
          out.println(message);
        }
        catch (DirectoryException de)
        {
          int msgID = MSGID_ENCPW_CANNOT_ENCODE;
          String message = getMessage(msgID, de.getErrorMessage());
          System.err.println(wrapText(message, MAX_LINE_WIDTH));
          System.exit(1);
          err.println(wrapText(message, MAX_LINE_WIDTH));
          return 1;
        }
        catch (Exception e)
        {
          int msgID = MSGID_ENCPW_CANNOT_ENCODE;
          String message = getMessage(msgID, stackTraceToSingleLineString(e));
          System.err.println(wrapText(message, MAX_LINE_WIDTH));
          System.exit(1);
          err.println(wrapText(message, MAX_LINE_WIDTH));
          return 1;
        }
      }
    }
    // If we've gotten here, then all processing completed successfully.
    return 0;
  }
}
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/EncodePasswordTestCase.java
New file
@@ -0,0 +1,771 @@
/*
 * 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
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * 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
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  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
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 */
package org.opends.server.tools;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.opends.server.TestCaseUtils;
import org.opends.server.core.AddOperation;
import org.opends.server.core.DirectoryServer;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.types.Entry;
import org.opends.server.types.OperatingSystem;
import org.opends.server.types.ResultCode;
import org.opends.server.util.Base64;
import static org.testng.Assert.*;
import static org.opends.server.util.ServerConstants.*;
/**
 * A set of test cases for the EncodePassword tool.
 */
public class EncodePasswordTestCase
       extends ToolsTestCase
{
  // The path to the Directory Server configuration file.
  private String configFilePath;
  // The path to the temporary file containing a password.
  private String passwordFilePath;
  /**
   * Ensures that the Directory Server is running and gets the config file path.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @BeforeClass()
  public void startServer()
         throws Exception
  {
    TestCaseUtils.startServer();
    configFilePath = DirectoryServer.getServerRoot() + File.separator +
                     "config" + File.separator + "config.ldif";
    passwordFilePath = TestCaseUtils.createTempFile("password");
  }
  /**
   * Retrieves sets of invalid arguments that may not be used to initialize
   * the EncodePassword tool.
   *
   * @return  Sets of invalid arguments that may not be used to initialize the
   *          EncodePassword tool.
   */
  @DataProvider(name = "invalidArgs")
  public Object[][] getInvalidArgumentLists()
  {
    ArrayList<String[]> argLists   = new ArrayList<String[]>();
    ArrayList<String>   reasonList = new ArrayList<String>();
    String[] args = new String[] {};
    argLists.add(args);
    reasonList.add("No arguments");
    args = new String[]
    {
      "-C",
    };
    argLists.add(args);
    reasonList.add("No value for '-C' argument");
    args = new String[]
    {
      "-f",
    };
    argLists.add(args);
    reasonList.add("No value for '-f' argument");
    args = new String[]
    {
      "-c",
    };
    argLists.add(args);
    reasonList.add("No value for '-c' argument");
    args = new String[]
    {
      "-F",
    };
    argLists.add(args);
    reasonList.add("No value for '-F' argument");
    args = new String[]
    {
      "-e",
    };
    argLists.add(args);
    reasonList.add("No value for '-e' argument");
    args = new String[]
    {
      "-E",
    };
    argLists.add(args);
    reasonList.add("No value for '-E' argument");
    args = new String[]
    {
      "-s",
    };
    argLists.add(args);
    reasonList.add("No value for '-s' argument");
    args = new String[]
    {
      "-I"
    };
    argLists.add(args);
    reasonList.add("Invalid short argument");
    args = new String[]
    {
      "--invalidLongArgument"
    };
    argLists.add(args);
    reasonList.add("Invalid long argument");
    args = new String[]
    {
      "--configFile", configFilePath
    };
    argLists.add(args);
    reasonList.add("No clear password");
    args = new String[]
    {
      "--configFile", configFilePath,
      "--clearPassword", "password"
    };
    argLists.add(args);
    reasonList.add("No storage scheme or encoded password");
    args = new String[]
    {
      "--configFile", configFilePath,
      "--clearPassword", "password",
      "--clearPasswordFile", passwordFilePath,
      "--storageScheme", "SSHA"
    };
    argLists.add(args);
    reasonList.add("Both clear password and clear password file");
    args = new String[]
    {
      "--configFile", configFilePath,
      "--clearPassword", "password",
      "--encodedPassword", "password",
      "--encodedPasswordFile", passwordFilePath
    };
    argLists.add(args);
    reasonList.add("Both encoded password and encoded password file");
    Object[][] returnArray = new Object[argLists.size()][2];
    for (int i=0; i < argLists.size(); i++)
    {
      returnArray[i][0] = argLists.get(i);
      returnArray[i][1] = reasonList.get(i);
    }
    return returnArray;
  }
  /**
   * Tests the EncodePassword tool with sets of invalid arguments.
   *
   * @param  args           The set of arguments to use for the ListBackends
   *                        tool.
   * @param  invalidReason  The reason the provided set of arguments is invalid.
   */
  @Test(dataProvider = "invalidArgs")
  public void testInvalidArguments(String[] args, String invalidReason)
  {
    assertFalse((EncodePassword.encodePassword(args, false, null, null) == 0),
                "Should have been invalid because:  " + invalidReason);
  }
  /**
   * Tests the EncodePassword tool with the --listSchemes argument.
   */
  @Test()
  public void testListSchemes()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--listSchemes"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null), 0);
  }
  /**
   * Tests the EncodePassword tool with the --listSchemes and
   * --authPasswordSyntax arguments.
   */
  @Test()
  public void testListAuthSchemes()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--listSchemes",
      "--authPasswordSyntax"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null), 0);
  }
  /**
   * Tests the EncodePassword tool with the --clearPassword and --storageScheme
   * arguments.
   */
  @Test()
  public void testEncodeClearPassword()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "password",
      "--storageScheme", "SSHA"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null), 0);
  }
  /**
   * Tests the EncodePassword tool with the --clearPassword, --storageScheme,
   * and --authPasswordSyntax arguments.
   */
  @Test()
  public void testEncodeClearAuthPassword()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "password",
      "--storageScheme", "SHA1",
      "--authPasswordSyntax"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null), 0);
  }
  /**
   * Tests the EncodePassword tool with the --clearPasswordFile and
   * --storageScheme arguments.
   */
  @Test()
  public void testEncodeClearPasswordFromFile()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPasswordFile", passwordFilePath,
      "--storageScheme", "SSHA"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null), 0);
  }
  /**
   * Tests the EncodePassword tool with the --clearPasswordFile, --storageScheme,
   * and --authPasswordSyntax arguments.
   */
  @Test()
  public void testEncodeClearAuthPasswordFromFile()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPasswordFile", passwordFilePath,
      "--storageScheme", "SHA1",
      "--authPasswordSyntax"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null), 0);
  }
  /**
   * Tests the EncodePassword tool with the --clearPassword and --storageScheme
   * arguments using an invalid storage scheme.
   */
  @Test()
  public void testEncodeClearPasswordWithInvalidScheme()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "password",
      "--storageScheme", "invalid"
    };
    assertFalse(EncodePassword.encodePassword(args, false, null, null) == 0);
  }
  /**
   * Tests the EncodePassword tool with the --clearPassword, --storageScheme,
   * and --authPasswordSyntax arguments using an invalid storage scheme.
   */
  @Test()
  public void testEncodeClearPasswordWithInvalidAuthScheme()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "password",
      "--storageScheme", "invalid",
      "--authPasswordSyntax"
    };
    assertFalse(EncodePassword.encodePassword(args, false, null, null) == 0);
  }
  /**
   * Tests the EncodePassword tool with the --clearPasswordFile and
   * --storageScheme arguments using an a password file that doesn't exist.
   */
  @Test()
  public void testEncodeClearPasswordFromMissingFile()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPasswordFile", passwordFilePath + ".missing",
      "--storageScheme", "invalid"
    };
    assertFalse(EncodePassword.encodePassword(args, false, null, null) == 0);
  }
  /**
   * Tests the EncodePassword tool with the --clearPasswordFile,
   * --storageScheme, and --authPasswordSyntax arguments using an a password
   * file that doesn't exist.
   */
  @Test()
  public void testEncodeClearAuthPasswordFromMissingFile()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPasswordFile", passwordFilePath + ".missing",
      "--storageScheme", "invalid",
      "--authPasswordSyntax"
    };
    assertFalse(EncodePassword.encodePassword(args, false, null, null) == 0);
  }
  /**
   * Tests the EncodePassword tool by performing a comparison of clear-text
   * with a valid matching encoded password.
   */
  @Test()
  public void testCompareMatchingPasswordsNoScheme()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "password",
      "--encodedPassword", "{CLEAR}password"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null), 0);
  }
  /**
   * Tests the EncodePassword tool by performing a comparison of clear-text
   * with a valid matching encoded password.
   */
  @Test()
  public void testCompareMatchingPasswordsWithScheme()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "password",
      "--storageScheme", "CLEAR",
      "--encodedPassword", "password"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null), 0);
  }
  /**
   * Tests the EncodePassword tool by performing a comparison of clear-text
   * with a valid matching auth password.
   */
  @Test()
  public void testCompareMatchingAuthPasswords()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "password",
      "--encodedPassword", "SHA1$dcKtMsOgc30=$MtHvXqXXJIRgxxw4xRXIY6ZLkQo=",
      "--authPasswordSyntax"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null), 0);
  }
  /**
   * Tests the EncodePassword tool by performing a comparison of clear-text
   * with a non-matching encoded password.
   */
  @Test()
  public void testCompareNonMatchingPasswordsNoScheme()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "wrongpassword",
      "--encodedPassword", "{CLEAR}password"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null), 0);
  }
  /**
   * Tests the EncodePassword tool by performing a comparison of clear-text
   * with a non-matching encoded password.
   */
  @Test()
  public void testCompareNonMatchingPasswordsWithScheme()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "wrongpassword",
      "--storageScheme", "CLEAR",
      "--encodedPassword", "password"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null), 0);
  }
  /**
   * Tests the EncodePassword tool by performing a comparison of clear-text
   * with a non-matching auth password.
   */
  @Test()
  public void testCompareNonMatchingAuthPasswords()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "wrongpassword",
      "--encodedPassword", "SHA1$dcKtMsOgc30=$MtHvXqXXJIRgxxw4xRXIY6ZLkQo=",
      "--authPasswordSyntax"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null), 0);
  }
  /**
   * Tests the EncodePassword tool by performing a comparison of clear-text
   * with a valid matching encoded password using the LDAP compare result as an
   * exit code.
   */
  @Test()
  public void testCompareMatchingPasswordsNoSchemeCompareResult()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "password",
      "--encodedPassword", "{CLEAR}password",
      "--useCompareResultCode"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null),
                 LDAPResultCode.COMPARE_TRUE);
  }
  /**
   * Tests the EncodePassword tool by performing a comparison of clear-text
   * with a valid matching encoded password using the LDAP compare result as an
   * exit code.
   */
  @Test()
  public void testCompareMatchingPasswordsWithSchemeCompareResult()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "password",
      "--storageScheme", "CLEAR",
      "--encodedPassword", "password",
      "--useCompareResultCode"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null),
                 LDAPResultCode.COMPARE_TRUE);
  }
  /**
   * Tests the EncodePassword tool by performing a comparison of clear-text
   * with a valid matching auth password using the LDAP compare result as an
   * exit code.
   */
  @Test()
  public void testCompareMatchingAuthPasswordsCompareResult()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "password",
      "--encodedPassword", "SHA1$dcKtMsOgc30=$MtHvXqXXJIRgxxw4xRXIY6ZLkQo=",
      "--authPasswordSyntax",
      "--useCompareResultCode"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null),
                 LDAPResultCode.COMPARE_TRUE);
  }
  /**
   * Tests the EncodePassword tool by performing a comparison of clear-text
   * with a non-matching encoded password using the LDAP compare result as an
   * exit code.
   */
  @Test()
  public void testCompareNonMatchingPasswordsNoSchemeCompareResult()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "wrongpassword",
      "--encodedPassword", "{CLEAR}password",
      "--useCompareResultCode"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null),
                 LDAPResultCode.COMPARE_FALSE);
  }
  /**
   * Tests the EncodePassword tool by performing a comparison of clear-text
   * with a non-matching encoded password using the LDAP compare result as an
   * exit code.
   */
  @Test()
  public void testCompareNonMatchingPasswordsWithSchemeCompareResult()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "wrongpassword",
      "--storageScheme", "CLEAR",
      "--encodedPassword", "password",
      "--useCompareResultCode"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null),
                 LDAPResultCode.COMPARE_FALSE);
  }
  /**
   * Tests the EncodePassword tool by performing a comparison of clear-text
   * with a non-matching auth password using the LDAP compare result as an
   * exit code.
   */
  @Test()
  public void testCompareNonMatchingAuthPasswordsCompareResult()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "wrongpassword",
      "--encodedPassword", "SHA1$dcKtMsOgc30=$MtHvXqXXJIRgxxw4xRXIY6ZLkQo=",
      "--authPasswordSyntax",
      "--useCompareResultCode"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null),
                 LDAPResultCode.COMPARE_FALSE);
  }
  /**
   * Tests the EncodePassword tool by performing a comparison of clear-text
   * with a malformed encoded auth password.
   */
  @Test()
  public void testCompareInvalidEncodedAuthPassword()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "password",
      "--encodedPassword", "malformedencodedauthpassword",
      "--authPasswordSyntax"
    };
    assertFalse(EncodePassword.encodePassword(args, false, null, null) == 0);
  }
  /**
   * Tests the EncodePassword tool by performing a comparison of clear-text
   * with an encoded password that uses an unknown scheme.
   */
  @Test()
  public void testCompareEncodedPasswordWithUnknownScheme()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "password",
      "--encodedPassword", "{UNKNOWN}unknownscheme"
    };
    assertFalse(EncodePassword.encodePassword(args, false, null, null) == 0);
  }
  /**
   * Tests the EncodePassword tool by performing a comparison of clear-text
   * with an encoded password that uses an unknown scheme.
   */
  @Test()
  public void testCompareEncodedPasswordWithUnknownSeparateScheme()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "password",
      "--storageScheme", "unknown",
      "--encodedPassword", "unknownscheme"
    };
    assertFalse(EncodePassword.encodePassword(args, false, null, null) == 0);
  }
  /**
   * Tests the EncodePassword tool by performing a comparison of clear-text
   * with an encoded auth password that uses an unknown scheme.
   */
  @Test()
  public void testCompareEncodedAuthPasswordWithUnknownScheme()
  {
    String[] args =
    {
      "--configFile", configFilePath,
      "--clearPassword", "password",
      "--encodedPassword", "UNKNOWN$AUTH$SCHEME",
      "--authPasswordSyntax"
    };
    assertFalse(EncodePassword.encodePassword(args, false, null, null) == 0);
  }
  /**
   * Tests the EncodePassword tool with the "--help" option.
   */
  @Test()
  public void testHelp()
  {
    String[] args =
    {
      "--help"
    };
    assertEquals(EncodePassword.encodePassword(args, false, null, null), 0);
  }
}