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

lutoff
18.47.2007 2fcf1d613593b70af7613af3e31165b9519ca60a
Add the following global options in dsservice to handle client keystore
Also modify ads.util package for this purpose.

-K, --keyStorePath {keyStorePath}
Certificate keystore path
--keyStorePassword {keyStorePassword}
Certificate keystore PIN
-u, --keyStorePasswordFile {path}
Certificate keystore PIN file
6 files modified
261 ■■■■ changed files
opendj-sdk/opends/src/ads/org/opends/admin/ads/util/ConnectionUtils.java 16 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/ads/org/opends/admin/ads/util/ServerLoader.java 2 ●●● patch | view | raw | blame | history
opendj-sdk/opends/src/ads/org/opends/admin/ads/util/TrustedSocketFactory.java 116 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java 2 ●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/DsServiceCliMain.java 2 ●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/DsServiceCliParser.java 123 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/ads/org/opends/admin/ads/util/ConnectionUtils.java
@@ -44,6 +44,7 @@
import javax.naming.ldap.StartTlsRequest;
import javax.naming.ldap.StartTlsResponse;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManager;
import javax.net.ssl.TrustManager;
/**
@@ -150,7 +151,8 @@
   * @param env           null or additional environment properties.
   * @param trustManager  null or the trust manager to be invoked during SSL
   * negociation.
   *
   * @param keyManager    null or the key manager to be invoked during SSL
   * negociation.
   * @return the established connection with the given parameters.
   *
   * @throws NamingException the exception thrown when instantiating
@@ -162,7 +164,7 @@
   */
  public static InitialLdapContext createLdapsContext(String ldapsURL,
      String dn, String pwd, int timeout, Hashtable<String, String> env,
      TrustManager trustManager) throws NamingException {
      TrustManager trustManager, KeyManager keyManager) throws NamingException {
    if (env != null)
    { // We clone 'env' so that we can modify it freely
      env = new Hashtable<String, String>(env);
@@ -195,11 +197,13 @@
    final Object[] pair = new Object[] {null, null};
    final Hashtable fEnv = env;
    final TrustManager fTrustManager = trustManager;
    final KeyManager   fKeyManage    = keyManager;
    Thread t = new Thread(new Runnable() {
      public void run() {
        try {
          TrustedSocketFactory.setCurrentThreadTrustManager(fTrustManager);
          TrustedSocketFactory.setCurrentThreadTrustManager(fTrustManager,
              fKeyManage);
          pair[0] = new InitialLdapContext(fEnv, null);
        } catch (NamingException ne) {
@@ -292,7 +296,7 @@
          tls.setHostnameVerifier(fVerifier);
          try
          {
            tls.negotiate(new TrustedSocketFactory(fTrustManager));
            tls.negotiate(new TrustedSocketFactory(fTrustManager,null));
          }
          catch(IOException x) {
            NamingException xx;
@@ -367,7 +371,9 @@
      throw new IllegalStateException("Unexpected throwable.", t);
    }
    return canConnectAsAdministrativeUser;
  }/**
  }
  /**
   * This is just a commodity method used to try to get an InitialLdapContext.
   * @param t the Thread to be used to create the InitialLdapContext.
   * @param pair an Object[] array that contains the InitialLdapContext and the
opendj-sdk/opends/src/ads/org/opends/admin/ads/util/ServerLoader.java
@@ -256,7 +256,7 @@
    else
    {
      ctx = ConnectionUtils.createLdapsContext(lastLdapUrl, dn, pwd,
          ConnectionUtils.getDefaultLDAPTimeout(), null, trustManager);
          ConnectionUtils.getDefaultLDAPTimeout(), null, trustManager, null);
    }
    return ctx;
opendj-sdk/opends/src/ads/org/opends/admin/ads/util/TrustedSocketFactory.java
@@ -38,6 +38,7 @@
import java.security.GeneralSecurityException;
import javax.net.SocketFactory;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.SSLKeyException;
@@ -52,29 +53,43 @@
    Logger.getLogger(TrustedSocketFactory.class.getName());
  private static Map<Thread, TrustManager> hmTrustManager =
    new HashMap<Thread, TrustManager>();
  private static Map<TrustManager, SocketFactory> hmDefaultFactory =
  private static Map<Thread, KeyManager> hmKeyManager =
    new HashMap<Thread, KeyManager>();
  private static Map<TrustManager, SocketFactory> hmDefaultFactoryTm =
    new HashMap<TrustManager, SocketFactory>();
  private static Map<KeyManager, SocketFactory> hmDefaultFactoryKm =
    new HashMap<KeyManager, SocketFactory>();
  private SSLSocketFactory innerFactory;
  private TrustManager trustManager;
  private KeyManager   keyManager;
  /**
   * Constructor of the TrustedSocketFactory.
   * @param trustManager the trust manager to use.
   * @param keyManager   the key manager to use.
   */
  public TrustedSocketFactory(TrustManager trustManager)
  public TrustedSocketFactory(TrustManager trustManager, KeyManager keyManager)
  {
    this.trustManager = trustManager;
    this.keyManager   = keyManager;
  }
  /**
   * Sets the provided trust manager for the operations in the current thread.
   * @param trustManager the trust manager to use.
   * Sets the provided trust and key manager for the operations in the
   * current thread.
   *
   * @param trustManager
   *          the trust manager to use.
   * @param keyManager
   *          the key manager to use.
   */
  public static synchronized void setCurrentThreadTrustManager(
      TrustManager trustManager)
      TrustManager trustManager, KeyManager keyManager)
  {
    setThreadTrustManager(trustManager, Thread.currentThread());
    setThreadKeyManager  (keyManager, Thread.currentThread());
  }
  /**
@@ -87,7 +102,7 @@
  {
    TrustManager currentTrustManager = hmTrustManager.get(thread);
    if (currentTrustManager != null) {
      hmDefaultFactory.remove(currentTrustManager);
      hmDefaultFactoryTm.remove(currentTrustManager);
      hmTrustManager.remove(thread);
    }
    if (trustManager != null) {
@@ -95,6 +110,24 @@
    }
  }
  /**
   * Sets the provided key manager for the operations in the provided thread.
   * @param keyManager the key manager to use.
   * @param thread the thread where we want to use the provided key manager.
   */
  public static synchronized void setThreadKeyManager(
      KeyManager keyManager, Thread thread)
  {
    KeyManager currentKeyManager = hmKeyManager.get(thread);
    if (currentKeyManager != null) {
      hmDefaultFactoryKm.remove(currentKeyManager);
      hmKeyManager.remove(thread);
    }
    if (keyManager != null) {
      hmKeyManager.put(thread, keyManager);
    }
  }
  //
  // SocketFactory implementation
  //
@@ -112,21 +145,63 @@
  {
    Thread currentThread = Thread.currentThread();
    TrustManager trustManager = hmTrustManager.get(currentThread);
    KeyManager   keyManager   = hmKeyManager.get(currentThread);
    SocketFactory result;
    if (trustManager == null)
    {
      LOG.log(Level.SEVERE, "Can't find a trust manager associated to thread " +
          currentThread);
      result = new TrustedSocketFactory(null);
      if (keyManager == null)
      {
        LOG.log(Level.SEVERE, "Can't find a key manager associated to thread " +
            currentThread);
        result = new TrustedSocketFactory(null,null);
      }
      else
      {
        result = hmDefaultFactoryKm.get(keyManager);
        if (result == null)
        {
          result = new TrustedSocketFactory(null,keyManager);
          hmDefaultFactoryKm.put(keyManager, result);
        }
      }
    }
    else
    {
      result = hmDefaultFactory.get(trustManager);
      if (result == null)
      if (keyManager == null)
      {
        result = new TrustedSocketFactory(trustManager);
        hmDefaultFactory.put(trustManager, result);
        LOG.log(Level.SEVERE,
            "Can't find a key manager associated to thread " + currentThread);
        result = hmDefaultFactoryTm.get(trustManager);
        if (result == null)
        {
          result = new TrustedSocketFactory(trustManager, null);
          hmDefaultFactoryTm.put(trustManager, result);
        }
      }
      else
      {
        SocketFactory tmsf = hmDefaultFactoryTm.get(trustManager);
        SocketFactory kmsf = hmDefaultFactoryKm.get(keyManager);
        if ( tmsf == null || kmsf == null)
        {
          result = new TrustedSocketFactory(trustManager, keyManager);
          hmDefaultFactoryTm.put(trustManager, result);
          hmDefaultFactoryKm.put(keyManager, result);
        }
        else
        if ( !tmsf.equals(kmsf) )
        {
          result = new TrustedSocketFactory(trustManager, keyManager);
          hmDefaultFactoryTm.put(trustManager, result);
          hmDefaultFactoryKm.put(keyManager, result);
        }
        else
        {
          result = tmsf ;
        }
      }
    }
@@ -216,18 +291,28 @@
    {
      String algorithm = "TLSv1";
      SSLKeyException xx;
      KeyManager[] km = null;
      TrustManager[] tm = null;
      try {
        SSLContext sslCtx = SSLContext.getInstance(algorithm);
        if (trustManager == null)
        {
          LOG.log(Level.SEVERE, "Warning : no trust for this factory");
          sslCtx.init(null, null, null); // No certif -> no SSL connection
        }
        else {
          sslCtx.init(null, new TrustManager[] { trustManager }, null
          );
        else
        {
          tm = new TrustManager[] { trustManager };
        }
        if (keyManager == null)
        {
          LOG.log(Level.SEVERE, "Warning : no key for this factory");
        }
        else
        {
          km = new KeyManager[] { keyManager };
        }
        sslCtx.init(km, tm, new java.security.SecureRandom() );
        innerFactory = sslCtx.getSocketFactory();
      }
      catch(GeneralSecurityException x) {
@@ -237,7 +322,6 @@
        throw xx;
      }
    }
    return innerFactory;
  }
}
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
@@ -902,7 +902,7 @@
      String dn, String pwd, int timeout, Hashtable<String, String> env,
      TrustManager trustManager) throws NamingException {
    return ConnectionUtils.createLdapsContext(ldapsURL, dn, pwd, timeout, env,
        trustManager);
        trustManager, null);
  }
  /**
opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/DsServiceCliMain.java
@@ -232,7 +232,7 @@
      {
        ctx = ConnectionUtils.createLdapsContext(ldapsUrl,
            dn, pwd, ConnectionUtils.getDefaultLDAPTimeout(), null,
             argParser.getTrustManager());
             argParser.getTrustManager(), argParser.getKeyManager());
      }
      catch (NamingException e)
      {
opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/DsServiceCliParser.java
@@ -47,6 +47,7 @@
import org.opends.admin.ads.ADSContext;
import org.opends.admin.ads.ADSContextException;
import org.opends.admin.ads.util.ApplicationKeyManager;
import org.opends.admin.ads.util.ApplicationTrustManager;
import org.opends.server.admin.client.cli.DsServiceCliReturnCode.ReturnCode;
import org.opends.server.loggers.debug.DebugTracer;
@@ -127,6 +128,21 @@
  private FileBasedArgument trustStorePasswordFileArg = null;
  /**
   * The 'keyStore' global argument.
   */
  private StringArgument keyStorePathArg = null;
  /**
   * The 'keyStorePassword' global argument.
   */
  private StringArgument keyStorePasswordArg = null;
  /**
   * The 'keyStorePasswordFile' global argument.
   */
  private FileBasedArgument keyStorePasswordFileArg = null;
  /**
   * The Logger.
   */
  static private final Logger LOG =
@@ -255,6 +271,24 @@
        MSGID_DESCRIPTION_TRUSTSTOREPASSWORD_FILE);
    addGlobalArgument(trustStorePasswordFileArg);
    keyStorePathArg = new StringArgument("keyStorePath",
        OPTION_SHORT_KEYSTOREPATH, OPTION_LONG_KEYSTOREPATH, false, false,
        true, OPTION_VALUE_KEYSTOREPATH, null, null,
        MSGID_DESCRIPTION_KEYSTOREPATH);
    addGlobalArgument(keyStorePathArg);
    keyStorePasswordArg = new StringArgument("keyStorePassword", null,
        OPTION_LONG_KEYSTORE_PWD, false, false, true,
        OPTION_VALUE_KEYSTORE_PWD, null, null,
        MSGID_DESCRIPTION_KEYSTOREPASSWORD);
    addGlobalArgument(keyStorePasswordArg);
    keyStorePasswordFileArg = new FileBasedArgument("keystorepasswordfile",
        OPTION_SHORT_KEYSTORE_PWD_FILE, OPTION_LONG_KEYSTORE_PWD_FILE, false,
        false, OPTION_VALUE_KEYSTORE_PWD_FILE, null, null,
        MSGID_DESCRIPTION_KEYSTOREPASSWORD_FILE);
    addGlobalArgument(keyStorePasswordFileArg);
    verboseArg = new BooleanArgument("verbose", 'v', "verbose",
        MSGID_DESCRIPTION_VERBOSE);
    addGlobalArgument(verboseArg);
@@ -457,8 +491,8 @@
   */
  public ApplicationTrustManager getTrustManager()
  {
    ApplicationTrustManager trustStore = null ;
    KeyStore keyStore = null ;
    ApplicationTrustManager truststoreManager = null ;
    KeyStore truststore = null ;
    if (trustStorePathArg.isPresent())
    {
      try
@@ -473,55 +507,120 @@
        {
          trustStorePasswordValue = trustStorePasswordFileArg.getValue();
        }
        keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(fos, trustStorePasswordValue.toCharArray());
        truststore = KeyStore.getInstance(KeyStore.getDefaultType());
        truststore.load(fos, trustStorePasswordValue.toCharArray());
      }
      catch (KeyStoreException e)
      {
        // Nothing to do: if this occurs we will systematically refuse the
        // certificates.  Maybe we should avoid this and be strict, but we are
        // in a best effor mode.
        LOG.log(Level.WARNING, "Error with the keystore", e);
        LOG.log(Level.WARNING, "Error with the truststore", e);
      }
      catch (NoSuchAlgorithmException e)
      {
        // Nothing to do: if this occurs we will systematically refuse the
        // certificates.  Maybe we should avoid this and be strict, but we are
        // in a best effor mode.
        LOG.log(Level.WARNING, "Error with the keystore", e);
        LOG.log(Level.WARNING, "Error with the truststore", e);
      }
      catch (CertificateException e)
      {
        // Nothing to do: if this occurs we will systematically refuse the
        // certificates.  Maybe we should avoid this and be strict, but we are
        // in a best effor mode.
        LOG.log(Level.WARNING, "Error with the keystore", e);
        LOG.log(Level.WARNING, "Error with the truststore", e);
      }
      catch (IOException e)
      {
        // Nothing to do: if this occurs we will systematically refuse the
        // certificates.  Maybe we should avoid this and be strict, but we are
        // in a best effor mode.
        LOG.log(Level.WARNING, "Error with the truststore", e);
      }
    }
    truststoreManager = new ApplicationTrustManager(truststore);
    truststoreManager.setHost(getHostName());
    return truststoreManager;
  }
  /**
   * Handle KeyStore.
   *
   * @return The keyStore manager to be used for the command.
   */
  public ApplicationKeyManager getKeyManager()
  {
    KeyStore keyStore = null;
    String keyStorePasswordValue = null;
    if (keyStorePathArg.isPresent())
    {
      try
      {
        FileInputStream fos = new FileInputStream(keyStorePathArg.getValue());
        if (keyStorePasswordArg.isPresent())
        {
          keyStorePasswordValue = keyStorePasswordArg.getValue();
        }
        else if (keyStorePasswordFileArg.isPresent())
        {
          keyStorePasswordValue = keyStorePasswordFileArg.getValue();
        }
        keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(fos, keyStorePasswordValue.toCharArray());
      }
      catch (KeyStoreException e)
      {
        // Nothing to do: if this occurs we will systematically refuse
        // the
        // certificates. Maybe we should avoid this and be strict, but
        // we are
        // in a best effor mode.
        LOG.log(Level.WARNING, "Error with the keystore", e);
      }
      catch (NoSuchAlgorithmException e)
      {
        // Nothing to do: if this occurs we will systematically refuse
        // the
        // certificates. Maybe we should avoid this and be strict, but
        // we are
        // in a best effor mode.
        LOG.log(Level.WARNING, "Error with the keystore", e);
      }
      catch (CertificateException e)
      {
        // Nothing to do: if this occurs we will systematically refuse
        // the
        // certificates. Maybe we should avoid this and be strict, but
        // we are
        // in a best effor mode.
        LOG.log(Level.WARNING, "Error with the keystore", e);
      }
      catch (IOException e)
      {
        // Nothing to do: if this occurs we will systematically refuse
        // the
        // certificates. Maybe we should avoid this and be strict, but
        // we are
        // in a best effor mode.
        LOG.log(Level.WARNING, "Error with the keystore", e);
      }
    }
    trustStore = new ApplicationTrustManager(keyStore);
    trustStore.setHost(getHostName());
    return trustStore ;
    return new ApplicationKeyManager(keyStore, keyStorePasswordValue
        .toCharArray());
  }
  /**
   * Indication if provided global options are validate.
   *
   * @param err the stream to be used to print error message.
   *
   * @return return code.
   */
  public int validateGlobalOption(PrintStream err)
  {
    ReturnCode returnCode = ReturnCode.SUCCESSFUL_NOP;
    // Couldn't have at the same time bindPassword and bibdPasswordFile
    // Couldn't have at the same time bindPassword and bindPasswordFile
    if(bindPasswordArg.isPresent() && bindPasswordFileArg.isPresent())
    {
      int    msgID   = MSGID_TOOL_CONFLICTING_ARGS;