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

kenneth_suter
07.38.2007 8babcca309a6903ae192dae0e13268b0567c9d33
opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/LDAPManagementContextFactory.java
@@ -27,24 +27,8 @@
package org.opends.server.tools.dsconfig;
import static org.opends.messages.DSConfigMessages.*;
import static org.opends.messages.ToolMessages.*;
import java.io.File;
import java.io.FileInputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.util.LinkedHashSet;
import javax.naming.NamingException;
import javax.naming.ldap.InitialLdapContext;
import javax.net.ssl.KeyManager;
import javax.net.ssl.TrustManager;
import org.opends.admin.ads.util.ApplicationKeyManager;
import org.opends.admin.ads.util.ApplicationTrustManager;
import org.opends.admin.ads.util.ConnectionUtils;
import static org.opends.messages.DSConfigMessages.*;
import org.opends.messages.Message;
import org.opends.messages.MessageBuilder;
import org.opends.server.admin.client.AuthenticationException;
@@ -58,17 +42,17 @@
import org.opends.server.admin.client.ldap.LDAPManagementContext;
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.tools.ClientException;
import org.opends.server.util.SelectableCertificateKeyManager;
import org.opends.server.util.args.Argument;
import org.opends.server.util.args.ArgumentException;
import org.opends.server.util.args.SubCommandArgumentParser;
import org.opends.server.util.cli.CLIException;
import org.opends.server.util.cli.LDAPConnectionConsoleInteraction;
import org.opends.server.util.cli.ConsoleApplication;
import org.opends.server.util.cli.Menu;
import org.opends.server.util.cli.MenuBuilder;
import org.opends.server.util.cli.MenuResult;
import org.opends.server.util.cli.ValidationCallback;
import javax.naming.NamingException;
import javax.naming.ldap.InitialLdapContext;
import javax.net.ssl.KeyManager;
import javax.net.ssl.TrustManager;
import java.util.LinkedHashSet;
/**
@@ -83,60 +67,6 @@
  // The management context.
  private ManagementContext context = null;
  // Indicate if we need to display the heading
  private boolean isHeadingDisplayed = false;
  // the Console application
  private ConsoleApplication app;
  /**
   * Enumeration description protocols for interactive CLI choices.
   */
  private enum Protocols
  {
    LDAP(1, INFO_DSCFG_PROMPT_SECURITY_LDAP.get()), SSL(2,
        INFO_DSCFG_PROMPT_SECURITY_USE_SSL.get()), START_TSL(3,
        INFO_DSCFG_PROMPT_SECURITY_USE_START_TSL.get());
    private Integer choice;
    private Message msg;
    /**
     * Private constructor.
     *
     * @param i
     *          the menu return value.
     * @param s
     *          the message message.
     */
    private Protocols(int i, Message msg)
    {
      choice = new Integer(i);
      this.msg = msg;
    }
    /**
     * Returns the choice number.
     *
     * @return the attribute name.
     */
    public Integer getChoice()
    {
      return choice;
    }
    /**
     * Return the menu message.
     *
     * @return the menu message.
     */
    public Message getMenuMessage()
    {
      return msg;
    }
  };
  /**
   * Creates a new LDAP management context factory.
   */
@@ -153,347 +83,23 @@
    // Lazily create the LDAP management context.
    if (context == null)
    {
      this.app = app;
      isHeadingDisplayed = false;
      boolean secureConnection =
        (
            secureArgsList.useSSLArg.isPresent()
            ||
            secureArgsList.useStartTLSArg.isPresent()
            ||
            secureArgsList.trustAllArg.isPresent()
            ||
            secureArgsList.trustStorePathArg.isPresent()
            ||
            secureArgsList.trustStorePasswordArg.isPresent()
            ||
            secureArgsList.trustStorePasswordFileArg.isPresent()
            ||
            secureArgsList.keyStorePathArg.isPresent()
            ||
            secureArgsList.keyStorePasswordArg.isPresent()
            ||
            secureArgsList.keyStorePasswordFileArg.isPresent()
        );
      // Get the LDAP host.
      String hostName = secureArgsList.hostNameArg.getValue();
      final String tmpHostName = hostName;
      if (app.isInteractive() && !secureArgsList.hostNameArg.isPresent())
      {
        if (!isHeadingDisplayed)
        {
          app.println();
          app.println();
          app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get());
          isHeadingDisplayed = true;
        }
        ValidationCallback<String> callback = new ValidationCallback<String>()
        {
          public String validate(ConsoleApplication app, String input)
              throws CLIException
          {
            String ninput = input.trim();
            if (ninput.length() == 0)
            {
              return tmpHostName;
            }
            else
            {
              try
              {
                InetAddress.getByName(ninput);
                return ninput;
              }
              catch (UnknownHostException e)
              {
                // Try again...
                app.println();
                app.println(ERR_DSCFG_BAD_HOST_NAME.get(ninput));
                app.println();
                return null;
              }
            }
          }
        };
        try
        {
          app.println();
          hostName = app.readValidatedInput(INFO_DSCFG_PROMPT_HOST_NAME
              .get(hostName), callback);
        }
        catch (CLIException e)
        {
          throw ArgumentExceptionFactory.unableToReadConnectionParameters(e);
        }
      }
      boolean useSSL = secureArgsList.useSSL();
      boolean useStartTLS = secureArgsList.useStartTLS();
      KeyManager keyManager = null;
      TrustManager trustManager = null;
      boolean connectionTypeIsSet =
        (
          secureArgsList.useSSLArg.isPresent()
          ||
          secureArgsList.useStartTLSArg.isPresent()
        );
      if (app.isInteractive() && !connectionTypeIsSet)
      {
        if (!isHeadingDisplayed)
        {
          app.println();
          app.println();
          app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get());
          isHeadingDisplayed = true;
        }
        MenuBuilder<Integer> builder = new MenuBuilder<Integer>(app);
        builder.setPrompt(INFO_DSCFG_PROMPT_SECURITY_USE_SECURE_CTX.get());
        Protocols defaultProtocol ;
        if (secureConnection)
        {
          defaultProtocol = Protocols.SSL;
        }
        else
        {
          defaultProtocol = Protocols.LDAP;
        }
        for (Protocols p : Protocols.values())
        {
          if (secureConnection && p.equals(Protocols.LDAP))
          {
            continue ;
          }
          int i = builder.addNumberedOption(p.getMenuMessage(), MenuResult
              .success(p.getChoice()));
          if (p.equals(defaultProtocol))
          {
            builder.setDefault(
                INFO_DSCFG_PROMPT_SECURITY_PROTOCOL_DEFAULT_CHOICE
                    .get(new Integer(i)), MenuResult.success(p.getChoice()));
          }
        }
        Menu<Integer> menu = builder.toMenu();
        try
        {
          MenuResult<Integer> result = menu.run();
          if (result.isSuccess())
          {
            if (result.getValue().equals(Protocols.SSL.getChoice()))
            {
              useSSL = true;
            }
            else if (result.getValue()
                .equals(Protocols.START_TSL.getChoice()))
            {
              useStartTLS = true;
            }
          }
          else
          {
            // Should never happen.
            throw new RuntimeException();
          }
        }
        catch (CLIException e)
        {
          throw new RuntimeException(e);
        }
      }
      if (useSSL || useStartTLS)
      {
        // Get truststore info
        trustManager = getTrustManager();
        // Check if we need client side authentication
        keyManager = getKeyManager();
      }
      // Get the LDAP port.
      int portNumber;
      if (!useSSL)
      {
        portNumber = secureArgsList.portArg.getIntValue();
      }
      else
      {
        if (secureArgsList.portArg.isPresent())
        {
          portNumber = secureArgsList.portArg.getIntValue();
        }
        else
        {
          portNumber = 636;
        }
      }
      final int tmpPortNumber = portNumber;
      if (app.isInteractive() && !secureArgsList.portArg.isPresent())
      {
        if (!isHeadingDisplayed)
        {
          app.println();
          app.println();
          app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get());
          isHeadingDisplayed = true;
        }
        ValidationCallback<Integer> callback = new ValidationCallback<Integer>()
        {
          public Integer validate(ConsoleApplication app, String input)
              throws CLIException
          {
            String ninput = input.trim();
            if (ninput.length() == 0)
            {
              return tmpPortNumber;
            }
            else
            {
              try
              {
                int i = Integer.parseInt(ninput);
                if (i < 1 || i > 65535)
                {
                  throw new NumberFormatException();
                }
                return i;
              }
              catch (NumberFormatException e)
              {
                // Try again...
                app.println();
                app.println(ERR_DSCFG_BAD_PORT_NUMBER.get(ninput));
                app.println();
                return null;
              }
            }
          }
        };
        try
        {
          app.println();
          portNumber = app.readValidatedInput(INFO_DSCFG_PROMPT_PORT_NUMBER
              .get(portNumber), callback);
        }
        catch (CLIException e)
        {
          throw ArgumentExceptionFactory.unableToReadConnectionParameters(e);
        }
      }
      // Get the LDAP bind credentials.
      String bindDN = secureArgsList.bindDnArg.getValue();
      final String tmpBindDN = bindDN;
      if (keyManager == null)
      {
        if (app.isInteractive() && !secureArgsList.bindDnArg.isPresent())
        {
          if (!isHeadingDisplayed)
          {
            app.println();
            app.println();
            app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get());
            isHeadingDisplayed = true;
          }
          ValidationCallback<String> callback = new ValidationCallback<String>()
          {
            public String validate(ConsoleApplication app, String input)
                throws CLIException
            {
              String ninput = input.trim();
              if (ninput.length() == 0)
              {
                return tmpBindDN;
              }
              else
              {
                return ninput;
              }
            }
          };
          try
          {
            app.println();
            bindDN = app.readValidatedInput(INFO_DSCFG_PROMPT_BIND_DN
                .get(bindDN), callback);
          }
          catch (CLIException e)
          {
            throw ArgumentExceptionFactory
                .unableToReadConnectionParameters(e);
          }
        }
      }
      else
      {
        bindDN = null ;
      }
      String bindPassword = secureArgsList.bindPasswordArg.getValue();
      if (keyManager == null)
      {
        if (secureArgsList.bindPasswordFileArg.isPresent())
        {
          // Read from file if it exists.
          bindPassword = secureArgsList.bindPasswordFileArg.getValue();
          if (bindPassword == null)
          {
            throw ArgumentExceptionFactory.missingBindPassword(bindDN);
          }
        }
        else if (bindPassword == null || bindPassword.equals("-"))
        {
          // Read the password from the stdin.
          if (!app.isInteractive())
          {
            throw ArgumentExceptionFactory
                .unableToReadBindPasswordInteractively();
          }
          if (!isHeadingDisplayed)
          {
            app.println();
            app.println();
            app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get());
            isHeadingDisplayed = true;
          }
          try
          {
            app.println();
            Message prompt = INFO_LDAPAUTH_PASSWORD_PROMPT.get(bindDN);
            bindPassword = app.readPassword(prompt);
          }
          catch (Exception e)
          {
            throw ArgumentExceptionFactory
                .unableToReadConnectionParameters(e);
          }
        }
      }
      // Interact with the user though the console to get
      // LDAP connection information
      LDAPConnectionConsoleInteraction ci =
              new LDAPConnectionConsoleInteraction(app, secureArgsList);
      ci.run();
      String hostName = ci.getHostName();
      Integer portNumber = ci.getPortNumber();
      String bindDN = ci.getBindDN();
      String bindPassword = ci.getBindPassword();
      TrustManager trustManager = ci.getTrustManager();
      KeyManager keyManager = ci.getKeyManager();
      // Do we have a secure connection ?
      LDAPConnection conn ;
      if (useSSL)
      if (ci.useSSL())
      {
        InitialLdapContext ctx = null;
        InitialLdapContext ctx;
        String ldapsUrl = "ldaps://" + hostName + ":" + portNumber;
        try
        {
@@ -510,9 +116,9 @@
              message) ;
        }
      }
      else if (useStartTLS)
      else if (ci.useStartTLS())
      {
        InitialLdapContext ctx = null;
        InitialLdapContext ctx;
        String ldapUrl = "ldap://" + hostName + ":" + portNumber;
        try
        {
@@ -600,342 +206,4 @@
    }
  }
  /**
   * Get the trust manager.
   *
   * @return The trust manager based on CLI args on interactive prompt.
   * @throws ArgumentException If an error occurs when getting args values.
   */
  private ApplicationTrustManager getTrustManager()
  throws ArgumentException
  {
    boolean trustAll = secureArgsList.trustAllArg.isPresent();
    if (app.isInteractive() && !secureArgsList.trustAllArg.isPresent())
    {
      if (!isHeadingDisplayed)
      {
        app.println();
        app.println();
        app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get());
        isHeadingDisplayed = true;
      }
      try
      {
        app.println();
        trustAll = app.confirmAction(INFO_DSCFG_PROMPT_SECURITY_USE_TRUST_ALL
            .get(), false);
      }
      catch (CLIException e)
      {
        // Should never happen.
        throw new RuntimeException(e);
      }
    }
    // Trust everything, so no trust manager
    if (trustAll)
    {
      return null;
    }
    // If we not trust all server certificates, we have to get info
    // about truststore. First get the truststore path.
    String truststorePath = secureArgsList.trustStorePathArg.getValue();
    if (app.isInteractive() && !secureArgsList.trustStorePathArg.isPresent())
    {
      if (!isHeadingDisplayed)
      {
        app.println();
        app.println();
        app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get());
        isHeadingDisplayed = true;
      }
      ValidationCallback<String> callback = new ValidationCallback<String>()
      {
        public String validate(ConsoleApplication app, String input)
            throws CLIException
        {
          String ninput = input.trim();
          if (ninput.length() == 0)
          {
            app.println();
            app.println(ERR_DSCFG_PROMPT_SECURITY_INVALID_FILE_PATH
                .get());
            app.println();
            return null;
          }
          File f = new File(ninput);
          if (f.exists() && f.canRead() && !f.isDirectory())
          {
            return ninput;
          }
          else
          {
            app.println();
            app.println(ERR_DSCFG_PROMPT_SECURITY_INVALID_FILE_PATH
                .get());
            app.println();
            return null;
          }
        }
      };
      try
      {
        app.println();
        truststorePath = app.readValidatedInput(
            INFO_DSCFG_PROMPT_SECURITY_TRUSTSTORE_PATH.get(), callback);
      }
      catch (CLIException e)
      {
        throw ArgumentExceptionFactory.unableToReadConnectionParameters(e);
      }
    }
    // Then the truststore password.
    //  As the most common case is to have no password for truststore,
    // we don't ask it in the interactive mode.
    String truststorePassword = secureArgsList.trustStorePasswordArg
        .getValue();
    if (secureArgsList.trustStorePasswordFileArg.isPresent())
    {
      // Read from file if it exists.
      truststorePassword = secureArgsList.trustStorePasswordFileArg
          .getValue();
    }
    if ((truststorePassword !=  null) && (truststorePassword.equals("-")))
    {
      // Read the password from the stdin.
      if (!app.isInteractive())
      {
        truststorePassword = null;
      }
      else
      {
        if (!isHeadingDisplayed)
        {
          app.println();
          app.println();
          app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get());
          isHeadingDisplayed = true;
        }
        try
        {
          app.println();
          Message prompt = INFO_DSCFG_PROMPT_SECURITY_TRUSTSTORE_PASSWORD
              .get(truststorePath);
          truststorePassword = app.readPassword(prompt);
        }
        catch (Exception e)
        {
          throw ArgumentExceptionFactory.unableToReadConnectionParameters(e);
        }
      }
    }
    // We'we got all the information to get the truststore manager
    try
    {
      FileInputStream fos = new FileInputStream(truststorePath);
      KeyStore truststore = KeyStore.getInstance(KeyStore.getDefaultType());
      if (truststorePassword != null)
      {
        truststore.load(fos, truststorePassword.toCharArray());
      }
      else
      {
        truststore.load(fos, null);
      }
      fos.close();
      return new ApplicationTrustManager(truststore);
    }
    catch (Exception e)
    {
      throw ArgumentExceptionFactory.unableToReadConnectionParameters(e);
    }
  }
  /**
   * Get the key manager.
   *
   * @return The key manager based on CLI args on interactive prompt.
   * @throws ArgumentException If an error occurs when getting args values.
   */
  private KeyManager getKeyManager()
  throws ArgumentException
  {
    // Do we need client side authentication ?
    // If one of the client side authentication args is set, we assume
    // that we
    // need client side authentication.
    boolean weDontKnowIfWeNeedKeystore = !(secureArgsList.keyStorePathArg
        .isPresent()
        || secureArgsList.keyStorePasswordArg.isPresent()
        || secureArgsList.keyStorePasswordFileArg.isPresent()
        || secureArgsList.certNicknameArg
        .isPresent());
    // We don't have specific key manager parameter.
    // We assume that no client side authentication is required
    // Client side authentication is not the common use case. As a
    // consequence, interactive mode doesn't add an extra question
    // which will be in most cases useless.
    if (weDontKnowIfWeNeedKeystore)
    {
      return null;
    }
    // Get info about keystore. First get the keystore path.
    String keystorePath = secureArgsList.keyStorePathArg.getValue();
    if (app.isInteractive() && !secureArgsList.keyStorePathArg.isPresent())
    {
      if (!isHeadingDisplayed)
      {
        app.println();
        app.println();
        app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get());
        isHeadingDisplayed = true;
      }
      ValidationCallback<String> callback = new ValidationCallback<String>()
      {
        public String validate(ConsoleApplication app, String input)
            throws CLIException
        {
          String ninput = input.trim();
          if (ninput.length() == 0)
          {
            return ninput;
          }
          File f = new File(ninput);
          if (f.exists() && f.canRead() && !f.isDirectory())
          {
            return ninput;
          }
          else
          {
            app.println();
            app.println(ERR_DSCFG_PROMPT_SECURITY_INVALID_FILE_PATH
                .get());
            app.println();
            return null;
          }
        }
      };
      try
      {
        app.println();
        keystorePath = app.readValidatedInput(
            INFO_DSCFG_PROMPT_SECURITY_KEYSTORE_PATH.get(), callback);
      }
      catch (CLIException e)
      {
        throw ArgumentExceptionFactory.unableToReadConnectionParameters(e);
      }
    }
    // Then the keystore password.
    String keystorePassword = secureArgsList.keyStorePasswordArg.getValue();
    if (secureArgsList.keyStorePasswordFileArg.isPresent())
    {
      // Read from file if it exists.
      keystorePassword = secureArgsList.keyStorePasswordFileArg.getValue();
      if (keystorePassword == null)
      {
        throw ArgumentExceptionFactory.missingBindPassword(keystorePassword);
      }
    }
    else if (keystorePassword == null || keystorePassword.equals("-"))
    {
      // Read the password from the stdin.
      if (!app.isInteractive())
      {
        throw ArgumentExceptionFactory
            .unableToReadBindPasswordInteractively();
      }
      if (!isHeadingDisplayed)
      {
        app.println();
        app.println();
        app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get());
        isHeadingDisplayed = true;
      }
      try
      {
        app.println();
        Message prompt = INFO_DSCFG_PROMPT_SECURITY_KEYSTORE_PASSWORD
            .get(keystorePath);
        keystorePassword = app.readPassword(prompt);
      }
      catch (Exception e)
      {
        throw ArgumentExceptionFactory.unableToReadConnectionParameters(e);
      }
    }
    // finally the certificate name, if needed.
    String certifNickname = secureArgsList.certNicknameArg.getValue();
    if (app.isInteractive() && !secureArgsList.certNicknameArg.isPresent())
    {
      if (!isHeadingDisplayed)
      {
        app.println();
        app.println();
        app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get());
        isHeadingDisplayed = true;
      }
      ValidationCallback<String> callback = new ValidationCallback<String>()
      {
        public String validate(ConsoleApplication app, String input)
            throws CLIException
        {
          return input.trim();
        }
      };
      try
      {
        app.println();
        certifNickname = app.readValidatedInput(
            INFO_DSCFG_PROMPT_SECURITY_CERTIFICATE_NAME.get(), callback);
      }
      catch (CLIException e)
      {
        throw ArgumentExceptionFactory.unableToReadConnectionParameters(e);
      }
    }
    // We'we got all the information to get the keystore manager
    try
    {
      FileInputStream fos = new FileInputStream(keystorePath);
      KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
      keystore.load(fos, keystorePassword.toCharArray());
      fos.close();
      ApplicationKeyManager akm = new ApplicationKeyManager(keystore,
          keystorePassword.toCharArray());
      if (certifNickname.length() != 0)
      {
        return new SelectableCertificateKeyManager(akm, certifNickname);
      }
      else
      {
        return akm ;
      }
    }
    catch (Exception e)
    {
      throw ArgumentExceptionFactory.unableToReadConnectionParameters(e);
    }
  }
}