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

neil_a_wilson
21.17.2006 a800e6c27f55a58df0d6128b2f4502ee29993307
opends/src/server/org/opends/server/tools/LDAPPasswordModify.java
@@ -28,7 +28,8 @@
import java.net.Socket;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
@@ -38,16 +39,23 @@
import org.opends.server.protocols.asn1.ASN1Reader;
import org.opends.server.protocols.asn1.ASN1Sequence;
import org.opends.server.protocols.asn1.ASN1Writer;
import org.opends.server.protocols.ldap.BindRequestProtocolOp;
import org.opends.server.protocols.ldap.BindResponseProtocolOp;
import org.opends.server.protocols.ldap.ExtendedRequestProtocolOp;
import org.opends.server.protocols.ldap.ExtendedResponseProtocolOp;
import org.opends.server.protocols.ldap.LDAPMessage;
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.protocols.ldap.UnbindRequestProtocolOp;
import org.opends.server.types.DN;
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;
import org.opends.server.util.args.FileBasedArgument;
import org.opends.server.util.args.IntegerArgument;
import org.opends.server.util.args.StringArgument;
import static org.opends.server.extensions.ExtensionsConstants.*;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ToolMessages.*;
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.*;
@@ -70,6 +78,22 @@
public class LDAPPasswordModify
{
  /**
   * The fully-qualified name of this class for debugging purposes.
   */
  private static final String CLASS_NAME =
       "org.opends.server.tools.LDAPPasswordModify";
  /**
   * The position at which to wrap long lines.
   */
  public static final int MAX_LINE_WIDTH = 79;
  /**
   * Parses the command-line arguments, establishes a connection to the
   * Directory Server, sends the password modify request, and reads the
   * response.
@@ -78,240 +102,449 @@
   */
  public static void main(String[] args)
  {
    // Define default values for all the configurable arguments.
    boolean provideDNForAuthzID = false;
    boolean provideOldPW        = false;
    int     ldapPort            = 389;
    String  authzID             = null;
    String  bindDN              = null;
    String  bindPW              = null;
    String  ldapHost            = "127.0.0.1";
    String  newPassword         = null;
    String  oldPassword         = null;
    if (args.length == 0)
    int returnCode = mainPasswordModify(args, true, System.out, System.err);
    if (returnCode != 0)
    {
      displayUsage();
      return;
      System.exit(returnCode);
    }
  }
  /**
   * Parses the command-line arguments, establishes a connection to the
   * Directory Server, sends the password modify request, and reads the
   * response.
   *
   * @param  args  The command-line arguments provided to this program.
   *
   * @return  An integer value of zero if everything completed successfully, or
   *          a nonzero value if an error occurred.
   */
  public static int mainPasswordModify(String[] args)
  {
    return mainPasswordModify(args, true, System.out, System.err);
  }
  /**
   * Parses the command-line arguments, establishes a connection to the
   * Directory Server, sends the password modify request, and reads the
   * response.
   *
   * @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.
   * @param  errStream         The output stream to use for standard error.
   *
   * @return  An integer value of zero if everything completed successfully, or
   *          a nonzero value if an error occurred.
   */
  public static int mainPasswordModify(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);
    }
    // Iterate through and process the command-line arguments.
    for (int i=0; i < args.length; i++)
    {
      if (args[i].equals("-h"))
      {
        ldapHost = args[++i];
      }
      else if (args[i].equals("-p"))
      {
        ldapPort = Integer.parseInt(args[++i]);
      }
      else if (args[i].equals("-D"))
      {
        bindDN = args[++i];
      }
      else if (args[i].equals("-w"))
      {
        bindPW = args[++i];
      }
      else if (args[i].equals("-a"))
      {
        authzID = args[++i];
      }
      else if (args[i].equals("-A"))
      {
        provideDNForAuthzID = true;
      }
      else if (args[i].equals("-o"))
      {
        oldPassword = args[++i];
      }
      else if (args[i].equals("-O"))
      {
        provideOldPW = true;
      }
      else if (args[i].equals("-n"))
      {
        newPassword = args[++i];
      }
      else if (args[i].equals("-H"))
      {
        displayUsage();
        return;
      }
      else
      {
        System.err.println("ERROR:  Invalid argument \"" + args[i] + "\"");
        displayUsage();
        System.exit(1);
      }
    }
    // Create the arguments that will be used by this program.
    BooleanArgument   provideDNForAuthzID;
    BooleanArgument   showUsage;
    BooleanArgument   sslBlindTrust;
    BooleanArgument   useSSL;
    BooleanArgument   useStartTLS;
    FileBasedArgument bindPWFile;
    FileBasedArgument currentPWFile;
    FileBasedArgument newPWFile;
    FileBasedArgument sslKeyStorePINFile;
    FileBasedArgument sslTrustStorePINFile;
    IntegerArgument   ldapPort;
    StringArgument    authzID;
    StringArgument    bindDN;
    StringArgument    bindPW;
    StringArgument    currentPW;
    StringArgument    ldapHost;
    StringArgument    newPW;
    StringArgument    sslKeyStore;
    StringArgument    sslTrustStore;
    // Make sure that all the required arguments were provided.
    if (provideOldPW)
    {
      if ((bindPW == null) || (bindPW.length() == 0))
      {
        System.err.println("ERROR:  The -O argument was used but no bind " +
                           "password was provided.");
        displayUsage();
        System.exit(1);
      }
      else
      {
        oldPassword = bindPW;
      }
    }
    // Initialize the argument parser.
    ArgumentParser argParser = new ArgumentParser(CLASS_NAME, false);
    if (provideDNForAuthzID)
    {
      if ((bindDN == null) || (bindDN.length() == 0))
      {
        System.err.println("ERROR:  The -A argument was used but no bind DN " +
                           "was provided.");
        displayUsage();
        System.exit(1);
      }
      else
      {
        authzID = "dn:" + bindDN;
      }
    }
    // Perform the necessary bootstrapping of the Directory Server code.
    DirectoryServer.bootstrapClient();
    // Establish a connection to the Directory Server.
    ASN1Reader reader = null;
    ASN1Writer writer = null;
    try
    {
      Socket socket = new Socket(ldapHost, ldapPort);
      reader = new ASN1Reader(socket);
      writer = new ASN1Writer(socket);
      ldapHost = new StringArgument("ldaphost", 'h', "ldapHost", false, false,
                                    true, "{host}", "127.0.0.1", null,
                                    MSGID_LDAPPWMOD_DESCRIPTION_HOST);
      argParser.addArgument(ldapHost);
      ldapPort = new IntegerArgument("ldapport", 'p', "ldapPort", false, false,
                                     true, "{port}", 389, null, true, 1, true,
                                     65535, MSGID_LDAPPWMOD_DESCRIPTION_PORT);
      argParser.addArgument(ldapPort);
      bindDN = new StringArgument("binddn", 'D', "bindDN", false, false, true,
                                  "{bindDN}", null, null,
                                  MSGID_LDAPPWMOD_DESCRIPTION_BIND_DN);
      argParser.addArgument(bindDN);
      bindPW = new StringArgument("bindpw", 'w', "bindPassword", false, false,
                                  true, "{bindDN}", null, null,
                                  MSGID_LDAPPWMOD_DESCRIPTION_BIND_PW);
      argParser.addArgument(bindPW);
      bindPWFile =
           new FileBasedArgument("bindpwfile", 'W', "bindPasswordFile", false,
                                 false, "{file}", null, null,
                                 MSGID_LDAPPWMOD_DESCRIPTION_BIND_PW_FILE);
      argParser.addArgument(bindPWFile);
      authzID = new StringArgument("authzid", 'a', "authzID", false, false,
                                   true, "{authzID}", null, null,
                                   MSGID_LDAPPWMOD_DESCRIPTION_AUTHZID);
      argParser.addArgument(authzID);
      provideDNForAuthzID =
           new BooleanArgument("providednforauthzid", 'A',"provideDNForAuthZID",
                    MSGID_LDAPPWMOD_DESCRIPTION_PROVIDE_DN_FOR_AUTHZID);
      argParser.addArgument(provideDNForAuthzID);
      newPW = new StringArgument("newpw", 'n', "newPassword", false, false,
                                 true, "{newPassword}", null, null,
                                 MSGID_LDAPPWMOD_DESCRIPTION_NEWPW);
      argParser.addArgument(newPW);
      newPWFile = new FileBasedArgument("newpwfile", 'N', "newPasswordFile",
                                        false, false, "{file}", null, null,
                                        MSGID_LDAPPWMOD_DESCRIPTION_NEWPWFILE);
      argParser.addArgument(newPWFile);
      currentPW =
           new StringArgument("currentpw", 'c', "currentPassword", false, false,
                              true, "{currentPassword}", null,  null,
                              MSGID_LDAPPWMOD_DESCRIPTION_CURRENTPW);
      argParser.addArgument(currentPW);
      currentPWFile =
           new FileBasedArgument("currentpwfile", 'C', "currentPasswordFile",
                                 false, false, "{file}", null, null,
                                 MSGID_LDAPPWMOD_DESCRIPTION_CURRENTPWFILE);
      argParser.addArgument(currentPWFile);
      useSSL = new BooleanArgument("usessl", 'Z', "useSSL",
                                   MSGID_LDAPPWMOD_DESCRIPTION_USE_SSL);
      argParser.addArgument(useSSL);
      useStartTLS = new BooleanArgument("usestarttls", 'q', "useStartTLS",
                             MSGID_LDAPPWMOD_DESCRIPTION_USE_STARTTLS);
      sslBlindTrust =
           new BooleanArgument("blindtrust", 'X', "trustAllCertificates",
                               MSGID_LDAPPWMOD_DESCRIPTION_BLIND_TRUST);
      argParser.addArgument(sslBlindTrust);
      sslKeyStore =
           new StringArgument("sslkeystore", 'k', "sslKeyStore", false, false,
                              true, "{file}", null, null,
                              MSGID_LDAPPWMOD_DESCRIPTION_KEYSTORE);
      argParser.addArgument(sslKeyStore);
      sslKeyStorePINFile =
           new FileBasedArgument("sslkeystorepin", 'K', "sslKeyStorePINFile",
                                 false, false, "{file}", null, null,
                                 MSGID_LDAPPWMOD_DESCRIPTION_KEYSTORE_PINFILE);
      argParser.addArgument(sslKeyStorePINFile);
      sslTrustStore =
           new StringArgument("ssltruststore", 't', "sslTrustStore", false,
                              false, true, "{file}", null, null,
                              MSGID_LDAPPWMOD_DESCRIPTION_TRUSTSTORE);
      argParser.addArgument(sslTrustStore);
      sslTrustStorePINFile =
           new FileBasedArgument("ssltruststorepin", 'T',
                    "sslTrustStorePINFile", false, false, "{file}", null, null,
                    MSGID_LDAPPWMOD_DESCRIPTION_TRUSTSTORE_PINFILE);
      argParser.addArgument(sslTrustStorePINFile);
      showUsage = new BooleanArgument("help", 'H', "help",
                                      MSGID_LDAPPWMOD_DESCRIPTION_USAGE);
      argParser.addArgument(showUsage);
      argParser.setUsageArgument(showUsage, out);
    }
    catch (ArgumentException ae)
    {
      int    msgID   = MSGID_LDAPPWMOD_CANNOT_INITIALIZE_ARGS;
      String message = getMessage(msgID, ae.getMessage());
      err.println(wrapText(message, MAX_LINE_WIDTH));
      return 1;
    }
    // Parse the command-line arguments provided to this program.
    try
    {
      argParser.parseArguments(args);
    }
    catch (ArgumentException ae)
    {
      int    msgID   = MSGID_LDAPPWMOD_ERROR_PARSING_ARGS;
      String message = getMessage(msgID, ae.getMessage());
      err.println(wrapText(message, MAX_LINE_WIDTH));
      err.println(argParser.getUsage());
      return 1;
    }
    // If the usage argument was provided, then we don't need to do anything
    // else.
    if (showUsage.isPresent())
    {
      return 0;
    }
    // Make sure that the user didn't specify any conflicting arguments.
    if (bindPW.isPresent() && bindPWFile.isPresent())
    {
      int    msgID   = MSGID_LDAPPWMOD_CONFLICTING_ARGS;
      String message = getMessage(msgID, bindPW.getLongIdentifier(),
                                  bindPWFile.getLongIdentifier());
      err.println(wrapText(message, MAX_LINE_WIDTH));
      return 1;
    }
    if (newPW.isPresent() && newPWFile.isPresent())
    {
      int    msgID   = MSGID_LDAPPWMOD_CONFLICTING_ARGS;
      String message = getMessage(msgID, newPW.getLongIdentifier(),
                                  newPWFile.getLongIdentifier());
      err.println(wrapText(message, MAX_LINE_WIDTH));
      return 1;
    }
    if (currentPW.isPresent() && currentPWFile.isPresent())
    {
      int    msgID   = MSGID_LDAPPWMOD_CONFLICTING_ARGS;
      String message = getMessage(msgID, currentPW.getLongIdentifier(),
                                  currentPWFile.getLongIdentifier());
      err.println(wrapText(message, MAX_LINE_WIDTH));
      return 1;
    }
    if (useSSL.isPresent() && useStartTLS.isPresent())
    {
      int    msgID   = MSGID_LDAPPWMOD_CONFLICTING_ARGS;
      String message = getMessage(msgID, useSSL.getLongIdentifier(),
                                  useStartTLS.getLongIdentifier());
      err.println(wrapText(message, MAX_LINE_WIDTH));
      return 1;
    }
    // If a bind DN was provided, make sure that a password was given.  If a
    // password was given, make sure a bind DN was provided.  If neither were
    // given, then make sure that an authorization ID and the current password
    // were provided.
    if (bindDN.isPresent())
    {
      if (! (bindPW.isPresent() || bindPWFile.isPresent()))
      {
        int    msgID   = MSGID_LDAPPWMOD_BIND_DN_AND_PW_MUST_BE_TOGETHER;
        String message = getMessage(msgID);
        err.println(wrapText(message, MAX_LINE_WIDTH));
        err.println(argParser.getUsage());
        return 1;
      }
    }
    else if (bindPW.isPresent() || bindPWFile.isPresent())
    {
      int    msgID   = MSGID_LDAPPWMOD_BIND_DN_AND_PW_MUST_BE_TOGETHER;
      String message = getMessage(msgID);
      err.println(wrapText(message, MAX_LINE_WIDTH));
      err.println(argParser.getUsage());
      return 1;
    }
    else
    {
      if (! (authzID.isPresent() && currentPW.isPresent()))
      {
        int    msgID   = MSGID_LDAPPWMOD_ANON_REQUIRES_AUTHZID_AND_CURRENTPW;
        String message = getMessage(msgID);
        err.println(wrapText(message, MAX_LINE_WIDTH));
        err.println(argParser.getUsage());
        return 1;
      }
      if (provideDNForAuthzID.isPresent())
      {
        int    msgID   = MSGID_LDAPPWMOD_DEPENDENT_ARGS;
        String message = getMessage(msgID,
                                    provideDNForAuthzID.getLongIdentifier(),
                                    bindDN.getLongIdentifier());
        err.println(wrapText(message, MAX_LINE_WIDTH));
        err.println(argParser.getUsage());
        return 1;
      }
    }
    // Get the host and port.
    String host = ldapHost.getValue();
    int    port;
    try
    {
      port = ldapPort.getIntValue();
    }
    catch (Exception e)
    {
      System.err.println("ERROR:  Unable to connect to the Directory Server " +
                         ldapHost + ":" + ldapPort + ":");
      e.printStackTrace();
      System.exit(1);
      // This should never happen.
      err.println(e);
      return 1;
    }
    // Send the LDAP bind request if appropriate.
    AtomicInteger nextMessageID = new AtomicInteger(1);
    if ((bindDN != null) && (bindDN.length() > 0) && (bindPW != null) &&
        (bindPW.length() > 0))
    // Perform a basic Directory Server bootstrap if appropriate.
    if (initializeServer)
    {
      BindRequestProtocolOp bindRequest =
           new BindRequestProtocolOp(new ASN1OctetString(bindDN), 3,
                                     new ASN1OctetString(bindPW));
      LDAPMessage requestMessage =
           new LDAPMessage(nextMessageID.getAndIncrement(), bindRequest);
      DirectoryServer.bootstrapClient();
    }
    // Establish a connection to the Directory Server.
    AtomicInteger nextMessageID = new AtomicInteger(1);
    LDAPConnectionOptions connectionOptions = new LDAPConnectionOptions();
    connectionOptions.setUseSSL(useSSL.isPresent());
    connectionOptions.setStartTLS(useStartTLS.isPresent());
    connectionOptions.setVersionNumber(3);
    if(connectionOptions.useSSL() || connectionOptions.useStartTLS())
    {
      try
      {
        writer.writeElement(requestMessage.encode());
        SSLConnectionFactory sslConnectionFactory = new SSLConnectionFactory();
        sslConnectionFactory.init(sslBlindTrust.isPresent(),
                                  sslKeyStore.getValue(),
                                  sslKeyStorePINFile.getValue(),
                                  sslTrustStore.getValue(),
                                  sslTrustStorePINFile.getValue());
        connectionOptions.setSSLConnectionFactory(sslConnectionFactory);
      }
      catch (Exception e)
      {
        System.err.println("ERROR:  Could not send the bind request to the " +
                           "server:");
        e.printStackTrace();
        try
        {
          reader.close();
          writer.close();
        } catch (Exception e2) {}
        System.exit(1);
      }
      LDAPMessage responseMessage = null;
      try
      {
        ASN1Sequence responseSequence = reader.readElement().decodeAsSequence();
        responseMessage = LDAPMessage.decode(responseSequence);
      }
      catch (Exception e)
      {
        System.err.println("ERROR:  Could not read the bind response from " +
                           "the server:");
        e.printStackTrace();
        try
        {
          reader.close();
          writer.close();
        } catch (Exception e2) {}
        System.exit(1);
      }
      BindResponseProtocolOp bindResponse =
           responseMessage.getBindResponseProtocolOp();
      int resultCode = bindResponse.getResultCode();
      if (resultCode != LDAPResultCode.SUCCESS)
      {
        System.err.println("ERROR:  Bind failed with result code " +
                           resultCode);
        String errorMessage = bindResponse.getErrorMessage();
        if ((errorMessage != null) && (errorMessage.length() > 0))
        {
          System.err.println("Error Message:  " + errorMessage);
        }
        DN matchedDN = bindResponse.getMatchedDN();
        if (matchedDN != null)
        {
          System.err.println("Matched DN:  " + matchedDN.toString());
        }
        try
        {
          requestMessage = new LDAPMessage(nextMessageID.getAndIncrement(),
                                           new UnbindRequestProtocolOp());
          writer.writeElement(requestMessage.encode());
        }
        catch (Exception e) {}
        try
        {
          reader.close();
          writer.close();
        } catch (Exception e) {}
        System.exit(resultCode);
        int    msgID   = MSGID_LDAPPWMOD_ERROR_INITIALIZING_SSL;
        String message = getMessage(msgID, String.valueOf(e));
        err.println(wrapText(message, MAX_LINE_WIDTH));
        return 1;
      }
    }
    LDAPConnection connection = new LDAPConnection(host, port,
                                                   connectionOptions, out, err);
    String dn;
    String pw;
    if (bindPW.isPresent())
    {
      dn = bindDN.getValue();
      pw = bindPW.getValue();
    }
    else if (bindPWFile.isPresent())
    {
      dn = bindDN.getValue();
      pw = bindPWFile.getValue();
    }
    else
    {
      dn = null;
      pw = null;
    }
    try
    {
      connection.connectToHost(dn, pw, nextMessageID);
    }
    catch (LDAPConnectionException lce)
    {
      int    msgID   = MSGID_LDAPPWMOD_CANNOT_CONNECT;
      String message = getMessage(msgID, lce.getMessage());
      err.println(wrapText(message, MAX_LINE_WIDTH));
      return lce.getErrorCode();
    }
    ASN1Reader reader = connection.getASN1Reader();
    ASN1Writer writer = connection.getASN1Writer();
    // Construct the password modify request.
    ArrayList<ASN1Element> requestElements = new ArrayList<ASN1Element>(3);
    if (authzID != null)
    if (authzID.isPresent())
    {
      requestElements.add(new ASN1OctetString(TYPE_PASSWORD_MODIFY_USER_ID,
                                              authzID));
                                              authzID.getValue()));
    }
    else if (provideDNForAuthzID.isPresent())
    {
      requestElements.add(new ASN1OctetString(TYPE_PASSWORD_MODIFY_USER_ID,
                                              "dn:" + dn));
    }
    if (oldPassword != null)
    if (currentPW.isPresent())
    {
      requestElements.add(new ASN1OctetString(TYPE_PASSWORD_MODIFY_OLD_PASSWORD,
                                              oldPassword));
                                              currentPW.getValue()));
    }
    else if (provideDNForAuthzID.isPresent())
    {
      requestElements.add(new ASN1OctetString(TYPE_PASSWORD_MODIFY_OLD_PASSWORD,
                                              pw));
    }
    if (newPassword != null)
    if (newPW.isPresent())
    {
      requestElements.add(new ASN1OctetString(TYPE_PASSWORD_MODIFY_NEW_PASSWORD,
                                              newPassword));
                                              newPW.getValue()));
    }
    ASN1OctetString requestValue =
@@ -331,8 +564,9 @@
    }
    catch (Exception e)
    {
      System.err.println("ERROR:  Could not send password modify request:");
      e.printStackTrace();
      int    msgID   = MSGID_LDAPPWMOD_CANNOT_SEND_PWMOD_REQUEST;
      String message = getMessage(msgID, String.valueOf(e));
      err.println(wrapText(message, MAX_LINE_WIDTH));
      try
      {
@@ -348,7 +582,7 @@
        writer.close();
      } catch (Exception e2) {}
      System.exit(1);
      return 1;
    }
@@ -361,8 +595,9 @@
    }
    catch (Exception e)
    {
      System.err.println("ERROR:  Could not read password modify response:");
      e.printStackTrace();
      int msgID = MSGID_LDAPPWMOD_CANNOT_READ_PWMOD_RESPONSE;
      String message = getMessage(msgID, String.valueOf(e));
      err.println(wrapText(message, MAX_LINE_WIDTH));
      try
      {
@@ -378,7 +613,7 @@
        writer.close();
      } catch (Exception e2) {}
      System.exit(1);
      return 1;
    }
@@ -388,19 +623,24 @@
    int resultCode = extendedResponse.getResultCode();
    if (resultCode != LDAPResultCode.SUCCESS)
    {
      System.err.println("ERROR:  Password modify failed with result code " +
                         resultCode);
      int    msgID   = MSGID_LDAPPWMOD_FAILED;
      String message = getMessage(msgID, resultCode);
      err.println(wrapText(message, MAX_LINE_WIDTH));
      String errorMessage = extendedResponse.getErrorMessage();
      if ((errorMessage != null) && (errorMessage.length() > 0))
      {
        System.err.println("Error Message:  " + errorMessage);
        msgID   = MSGID_LDAPPWMOD_FAILURE_ERROR_MESSAGE;
        message = getMessage(msgID, errorMessage);
        err.println(wrapText(message, MAX_LINE_WIDTH));
      }
      DN matchedDN = extendedResponse.getMatchedDN();
      if (matchedDN != null)
      {
        System.err.println("Matched DN:  " + matchedDN.toString());
        msgID   = MSGID_LDAPPWMOD_FAILURE_MATCHED_DN;
        message = getMessage(msgID, matchedDN.toString());
        err.println(wrapText(message, MAX_LINE_WIDTH));
      }
      try
@@ -417,11 +657,22 @@
        writer.close();
      } catch (Exception e) {}
      System.exit(resultCode);
      return resultCode;
    }
    else
    {
      int    msgID   = MSGID_LDAPPWMOD_SUCCESSFUL;
      String message = getMessage(msgID);
      out.println(wrapText(message, MAX_LINE_WIDTH));
    System.out.println("The user's password was successfully modified.");
      String additionalInfo = extendedResponse.getErrorMessage();
      if ((additionalInfo != null) && (additionalInfo.length() > 0))
      {
        msgID   = MSGID_LDAPPWMOD_ADDITIONAL_INFO;
        message = getMessage(msgID, additionalInfo);
        out.println(wrapText(message, MAX_LINE_WIDTH));
      }
    }
    // See if the response included a generated password.
@@ -436,22 +687,24 @@
        {
          if (e.getType() == TYPE_PASSWORD_MODIFY_GENERATED_PASSWORD)
          {
            String generatedPassword = e.decodeAsOctetString().stringValue();
            System.out.println("The generated password was:  " +
                               generatedPassword);
            int    msgID   = MSGID_LDAPPWMOD_GENERATED_PASSWORD;
            String message = getMessage(msgID,
                                        e.decodeAsOctetString().stringValue());
            out.println(wrapText(message, MAX_LINE_WIDTH));
          }
          else
          {
            throw new Exception("ERROR:  Unrecognized response value type " +
                                byteToHex(e.getType()));
            int    msgID   = MSGID_LDAPPWMOD_UNRECOGNIZED_VALUE_TYPE;
            String message = getMessage(msgID, byteToHex(e.getType()));
            err.println(wrapText(message, MAX_LINE_WIDTH));
          }
        }
      }
      catch (Exception e)
      {
        System.err.println("ERROR:  Could not decode response value to " +
                           "determine the generated password:");
        e.printStackTrace();
        int    msgID   = MSGID_LDAPPWMOD_COULD_NOT_DECODE_RESPONSE_VALUE;
        String message = getMessage(msgID, String.valueOf(e));
        err.println(wrapText(message, MAX_LINE_WIDTH));
        try
        {
@@ -467,7 +720,7 @@
          writer.close();
        } catch (Exception e2) {}
        System.exit(1);
        return 1;
      }
    }
@@ -486,27 +739,8 @@
      reader.close();
      writer.close();
    } catch (Exception e) {}
  }
  /**
   * Displays usage information for this program.
   */
  public static void displayUsage()
  {
    System.err.println("USAGE:  java LDAPPasswordModify {options}");
    System.err.println("        where {options} include:");
    System.err.println("-h {ldapHost}  -- The Directory Server address");
    System.err.println("-p {ldapPort}  -- The Directory Server port");
    System.err.println("-D {bindDN}    -- The bind DN");
    System.err.println("-w {bindPW}    -- The bind password");
    System.err.println("-a {authzID}   -- The authorization ID");
    System.err.println("-A             -- Use bind DN as authorization ID");
    System.err.println("-o {oldPWD}    -- The old password");
    System.err.println("-O             -- Use bind password as old password");
    System.err.println("-n {newPWD}    -- The new password");
    System.err.println("-H             -- Display this usage information");
    return 0;
  }
}