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

Matthew Swift
22.24.2012 45690fbc42773415ef034419ed3f27d2974b78e1
Fix OPENDJ-649: Add supportedTLSCiphers and supportedTLSProtocols to RootDSE and system monitor
13 files modified
1142 ■■■■■ changed files
opends/resource/schema/02-config.ldif 10 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/AdministrationConnector.java 81 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/api/ConnectionHandler.java 33 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/backends/RootDSEBackend.java 352 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/ConnectionHandlerConfigManager.java 33 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/DirectoryServer.java 43 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/TLSByteChannel.java 88 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/monitors/SystemInfoMonitorProvider.java 46 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java 9 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java 278 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/util/ServerConstants.java 36 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SASLOverTLSTestCase.java 128 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/ldap/TestLDAPConnectionHandler.java 5 ●●●●● patch | view | raw | blame | history
opends/resource/schema/02-config.ldif
@@ -3338,6 +3338,16 @@
  EQUALITY caseExactMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.63
  NAME 'supportedTLSProtocols'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  USAGE dSAOperation
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.64
  NAME 'supportedTLSCiphers'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  USAGE dSAOperation
  X-ORIGIN 'OpenDJ Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
  NAME 'ds-cfg-access-control-handler'
  SUP top
opends/src/server/org/opends/server/admin/AdministrationConnector.java
@@ -30,13 +30,10 @@
import static org.opends.server.loggers.ErrorLogger.logError;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.messages.AdminMessages.*;
import java.io.IOException;
import java.security.KeyStoreException;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.security.cert.CertificateEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedSet;
@@ -172,16 +169,12 @@
      AdministrationConnectorCfg configuration) throws ConfigException,
      InitializationException
  {
    this.config = configuration;
    // Create a fake LDAP connection handler configuration
    LDAPConnectionHandlerCfg ldapConnectionHandlerCfg =
      new FakeLDAPConnectionHandlerCfg(config);
    createSelfSignedCertifIfNeeded();
    // Administration Connector uses the LDAP connection handler
    // implementation
    adminConnectionHandler = new LDAPConnectionHandler(
@@ -604,20 +597,26 @@
  /**
   * Creates a self-signed JKS certificate if needed.
   *
   * @throws InitializationException
   *           If an unexpected error occurred whilst trying to create the
   *           certificate.
   */
  private void createSelfSignedCertifIfNeeded() throws InitializationException
  public static void createSelfSignedCertificateIfNeeded()
      throws InitializationException
  {
    try
    {
      RootCfg root = ServerManagementContext.getInstance()
          .getRootConfiguration();
      AdministrationConnectorCfg config = root.getAdministrationConnector();
      // Check if certificate generation is needed
      String certAlias = config.getSSLCertNickname();
      KeyManagerProviderCfg keyMgrConfig =
        getAdminConnectorKeyManagerConfig(config.getKeyManagerProvider());
      TrustManagerProviderCfg trustMgrConfig =
        getAdminConnectorTrustManagerConfig(config.getTrustManagerProvider());
      KeyManagerProviderCfg keyMgrConfig = root.getKeyManagerProvider(config
          .getKeyManagerProvider());
      TrustManagerProviderCfg trustMgrConfig = root
          .getTrustManagerProvider(config.getTrustManagerProvider());
      if (!(keyMgrConfig instanceof FileBasedKeyManagerProviderCfg)
          || !(trustMgrConfig instanceof FileBasedTrustManagerProviderCfg))
@@ -747,54 +746,20 @@
      File f = new File(tempCertPath);
      f.delete();
    }
    catch (ConfigException e)
    catch (InitializationException e)
    {
      handleCertifExceptions(e);
      throw e;
    }
    catch (KeyStoreException e)
    catch (Exception e)
    {
      handleCertifExceptions(e);
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      Message message = ERR_ADMIN_CERTIFICATE_GENERATION.get(e.getMessage());
      logError(message);
      throw new InitializationException(message);
    }
    catch (IOException e)
    {
      handleCertifExceptions(e);
    }
    catch (CertificateEncodingException e)
    {
      handleCertifExceptions(e);
    }
  }
  private void handleCertifExceptions(Exception e)
      throws InitializationException
  {
    if (debugEnabled())
    {
      TRACER.debugCaught(DebugLogLevel.ERROR, e);
    }
    Message message = ERR_ADMIN_CERTIFICATE_GENERATION.get(e.getMessage());
    logError(message);
    throw new InitializationException(message);
  }
  private KeyManagerProviderCfg getAdminConnectorKeyManagerConfig(String name)
      throws ConfigException
  {
    RootCfg root = ServerManagementContext.getInstance().getRootConfiguration();
    return root.getKeyManagerProvider(name);
  }
  private TrustManagerProviderCfg getAdminConnectorTrustManagerConfig(
      String name) throws ConfigException
  {
    RootCfg root = ServerManagementContext.getInstance().getRootConfiguration();
    return root.getTrustManagerProvider(name);
  }
opends/src/server/org/opends/server/api/ConnectionHandler.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions copyright 2012 ForgeRock AS.
 */
package org.opends.server.api;
import org.opends.messages.Message;
@@ -30,6 +31,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.opends.server.admin.std.server.*;
@@ -108,6 +110,37 @@
  public abstract String getConnectionHandlerName();
  /**
   * Retrieves an unmodifiable set of enabled SSL cipher suites configured for
   * this connection handler, if applicable. Implementations must return an
   * empty set if use of SSL/TLS is not possible.
   *
   * @return The set of enabled SSL cipher suites configured for this connection
   *         handler.
   */
  public Collection<String> getEnabledSSLCipherSuites()
  {
    return Collections.emptyList();
  }
  /**
   * Retrieves the set of enabled SSL protocols configured for this connection
   * handler. Implementations must return an empty set if use of SSL/TLS is not
   * possible.
   *
   * @return The set of enabled SSL protocols configured for this connection
   *         handler.
   */
  public Collection<String> getEnabledSSLProtocols()
  {
    return Collections.emptyList();
  }
   /**
   * Retrieves the DN of the configuration entry with which this alert
   * generator is associated.
opends/src/server/org/opends/server/backends/RootDSEBackend.java
@@ -30,20 +30,27 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import org.opends.messages.Message;
import org.opends.server.admin.Configuration;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.std.server.RootDSEBackendCfg;
import org.opends.server.api.Backend;
import org.opends.server.api.ClientConnection;
import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
import org.opends.server.core.AddOperation;
@@ -53,7 +60,6 @@
import org.opends.server.core.ModifyDNOperation;
import org.opends.server.core.SearchOperation;
import org.opends.server.core.WorkflowTopologyNode;
import org.opends.server.core.networkgroups.NetworkGroup;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.types.*;
import org.opends.server.util.LDIFWriter;
@@ -511,10 +517,25 @@
  /**
   * Retrieves the root DSE entry for the Directory Server.
   *
   * @return  The root DSE entry for the Directory Server.
   * @return The root DSE entry for the Directory Server.
   */
  public Entry getRootDSE()
  {
    return getRootDSE(null);
  }
  /**
   * Retrieves the root DSE entry for the Directory Server.
   *
   * @param connection
   *          The client connection, or {@code null} if there is no associated
   *          client connection.
   * @return The root DSE entry for the Directory Server.
   */
  public Entry getRootDSE(ClientConnection connection)
  {
    HashMap<AttributeType,List<Attribute>> dseUserAttrs =
         new HashMap<AttributeType,List<Attribute>>();
@@ -523,119 +544,143 @@
    // Add the "namingContexts" attribute.
    Attribute publicNamingContextAttr =
         createDNAttribute(ATTR_NAMING_CONTEXTS, ATTR_NAMING_CONTEXTS_LC,
                           DirectoryServer.getPublicNamingContexts().keySet());
    ArrayList<Attribute> publicNamingContextAttrs = new ArrayList<Attribute>(1);
    publicNamingContextAttrs.add(publicNamingContextAttr);
    if (showAllAttributes ||
        (! publicNamingContextAttr.getAttributeType().isOperational()))
    final Collection<DN> namingContexts;
    if (connection == null)
    {
      dseUserAttrs.put(publicNamingContextAttr.getAttributeType(),
                       publicNamingContextAttrs);
      namingContexts = DirectoryServer.getPublicNamingContexts().keySet();
    }
    else
    {
      dseOperationalAttrs.put(publicNamingContextAttr.getAttributeType(),
                              publicNamingContextAttrs);
      namingContexts = new LinkedList<DN>();
      for (WorkflowTopologyNode node : connection.getNetworkGroup()
          .getNamingContexts().getPublicNamingContexts())
      {
        namingContexts.add(node.getBaseDN());
      }
    }
    Attribute publicNamingContextAttr = createDNAttribute(ATTR_NAMING_CONTEXTS,
        ATTR_NAMING_CONTEXTS_LC, namingContexts);
    if (!publicNamingContextAttr.isEmpty())
    {
      List<Attribute> publicNamingContextAttrs = new ArrayList<Attribute>(1);
      publicNamingContextAttrs.add(publicNamingContextAttr);
      if (showAllAttributes
          || (!publicNamingContextAttr.getAttributeType().isOperational()))
      {
        dseUserAttrs.put(publicNamingContextAttr.getAttributeType(),
            publicNamingContextAttrs);
      }
      else
      {
        dseOperationalAttrs.put(publicNamingContextAttr.getAttributeType(),
            publicNamingContextAttrs);
      }
    }
    // Add the "ds-private-naming-contexts" attribute.
    Attribute privateNamingContextAttr =
         createDNAttribute(ATTR_PRIVATE_NAMING_CONTEXTS,
                           ATTR_PRIVATE_NAMING_CONTEXTS,
                           DirectoryServer.getPrivateNamingContexts().keySet());
    ArrayList<Attribute> privateNamingContextAttrs =
         new ArrayList<Attribute>(1);
    privateNamingContextAttrs.add(privateNamingContextAttr);
    if (showAllAttributes ||
        (! privateNamingContextAttr.getAttributeType().isOperational()))
    Attribute privateNamingContextAttr = createDNAttribute(
        ATTR_PRIVATE_NAMING_CONTEXTS, ATTR_PRIVATE_NAMING_CONTEXTS,
        DirectoryServer.getPrivateNamingContexts().keySet());
    if (!privateNamingContextAttr.isEmpty())
    {
      dseUserAttrs.put(privateNamingContextAttr.getAttributeType(),
                       privateNamingContextAttrs);
      List<Attribute> privateNamingContextAttrs = new ArrayList<Attribute>(1);
      privateNamingContextAttrs.add(privateNamingContextAttr);
      if (showAllAttributes
          || (!privateNamingContextAttr.getAttributeType().isOperational()))
      {
        dseUserAttrs.put(privateNamingContextAttr.getAttributeType(),
            privateNamingContextAttrs);
      }
      else
      {
        dseOperationalAttrs.put(privateNamingContextAttr.getAttributeType(),
            privateNamingContextAttrs);
      }
    }
    else
    {
      dseOperationalAttrs.put(privateNamingContextAttr.getAttributeType(),
                              privateNamingContextAttrs);
    }
    // Add the "supportedControl" attribute.
    Attribute supportedControlAttr =
         createAttribute(ATTR_SUPPORTED_CONTROL, ATTR_SUPPORTED_CONTROL_LC,
                         DirectoryServer.getSupportedControls());
    ArrayList<Attribute> supportedControlAttrs = new ArrayList<Attribute>(1);
    supportedControlAttrs.add(supportedControlAttr);
    if (showAllAttributes ||
        (! supportedControlAttr.getAttributeType().isOperational()))
    Attribute supportedControlAttr = createAttribute(ATTR_SUPPORTED_CONTROL,
        ATTR_SUPPORTED_CONTROL_LC, DirectoryServer.getSupportedControls());
    if (!supportedControlAttr.isEmpty())
    {
      dseUserAttrs.put(supportedControlAttr.getAttributeType(),
                       supportedControlAttrs);
      List<Attribute> supportedControlAttrs = new ArrayList<Attribute>(1);
      supportedControlAttrs.add(supportedControlAttr);
      if (showAllAttributes
          || (!supportedControlAttr.getAttributeType().isOperational()))
      {
        dseUserAttrs.put(supportedControlAttr.getAttributeType(),
            supportedControlAttrs);
      }
      else
      {
        dseOperationalAttrs.put(supportedControlAttr.getAttributeType(),
            supportedControlAttrs);
      }
    }
    else
    {
      dseOperationalAttrs.put(supportedControlAttr.getAttributeType(),
                              supportedControlAttrs);
    }
    // Add the "supportedExtension" attribute.
    Attribute supportedExtensionAttr =
         createAttribute(ATTR_SUPPORTED_EXTENSION, ATTR_SUPPORTED_EXTENSION_LC,
                         DirectoryServer.getSupportedExtensions().keySet());
    ArrayList<Attribute> supportedExtensionAttrs = new ArrayList<Attribute>(1);
    supportedExtensionAttrs.add(supportedExtensionAttr);
    if (showAllAttributes ||
        (! supportedExtensionAttr.getAttributeType().isOperational()))
    Attribute supportedExtensionAttr = createAttribute(
        ATTR_SUPPORTED_EXTENSION, ATTR_SUPPORTED_EXTENSION_LC, DirectoryServer
            .getSupportedExtensions().keySet());
    if (!supportedExtensionAttr.isEmpty())
    {
      dseUserAttrs.put(supportedExtensionAttr.getAttributeType(),
                       supportedExtensionAttrs);
      List<Attribute> supportedExtensionAttrs = new ArrayList<Attribute>(1);
      supportedExtensionAttrs.add(supportedExtensionAttr);
      if (showAllAttributes
          || (!supportedExtensionAttr.getAttributeType().isOperational()))
      {
        dseUserAttrs.put(supportedExtensionAttr.getAttributeType(),
            supportedExtensionAttrs);
      }
      else
      {
        dseOperationalAttrs.put(supportedExtensionAttr.getAttributeType(),
            supportedExtensionAttrs);
      }
    }
    else
    {
      dseOperationalAttrs.put(supportedExtensionAttr.getAttributeType(),
                              supportedExtensionAttrs);
    }
    // Add the "supportedFeature" attribute.
    Attribute supportedFeatureAttr =
         createAttribute(ATTR_SUPPORTED_FEATURE, ATTR_SUPPORTED_FEATURE_LC,
                         DirectoryServer.getSupportedFeatures());
    ArrayList<Attribute> supportedFeatureAttrs = new ArrayList<Attribute>(1);
    supportedFeatureAttrs.add(supportedFeatureAttr);
    if (showAllAttributes ||
        (! supportedFeatureAttr.getAttributeType().isOperational()))
    Attribute supportedFeatureAttr = createAttribute(ATTR_SUPPORTED_FEATURE,
        ATTR_SUPPORTED_FEATURE_LC, DirectoryServer.getSupportedFeatures());
    if (!supportedFeatureAttr.isEmpty())
    {
      dseUserAttrs.put(supportedFeatureAttr.getAttributeType(),
                       supportedFeatureAttrs);
    }
    else
    {
      dseOperationalAttrs.put(supportedFeatureAttr.getAttributeType(),
                              supportedFeatureAttrs);
      List<Attribute> supportedFeatureAttrs = new ArrayList<Attribute>(1);
      supportedFeatureAttrs.add(supportedFeatureAttr);
      if (showAllAttributes
          || (!supportedFeatureAttr.getAttributeType().isOperational()))
      {
        dseUserAttrs.put(supportedFeatureAttr.getAttributeType(),
            supportedFeatureAttrs);
      }
      else
      {
        dseOperationalAttrs.put(supportedFeatureAttr.getAttributeType(),
            supportedFeatureAttrs);
      }
    }
    // Add the "supportedSASLMechanisms" attribute.
    Attribute supportedSASLMechAttr =
         createAttribute(ATTR_SUPPORTED_SASL_MECHANISMS,
                         ATTR_SUPPORTED_SASL_MECHANISMS_LC,
                         DirectoryServer.getSupportedSASLMechanisms().keySet());
    ArrayList<Attribute> supportedSASLMechAttrs = new ArrayList<Attribute>(1);
    supportedSASLMechAttrs.add(supportedSASLMechAttr);
    if (showAllAttributes ||
        (! supportedSASLMechAttr.getAttributeType().isOperational()))
    Attribute supportedSASLMechAttr = createAttribute(
        ATTR_SUPPORTED_SASL_MECHANISMS, ATTR_SUPPORTED_SASL_MECHANISMS_LC,
        DirectoryServer.getSupportedSASLMechanisms().keySet());
    if (!supportedSASLMechAttr.isEmpty())
    {
      dseUserAttrs.put(supportedSASLMechAttr.getAttributeType(),
                       supportedSASLMechAttrs);
    }
    else
    {
      dseOperationalAttrs.put(supportedSASLMechAttr.getAttributeType(),
                              supportedSASLMechAttrs);
      List<Attribute> supportedSASLMechAttrs = new ArrayList<Attribute>(1);
      supportedSASLMechAttrs.add(supportedSASLMechAttr);
      if (showAllAttributes
          || (!supportedSASLMechAttr.getAttributeType().isOperational()))
      {
        dseUserAttrs.put(supportedSASLMechAttr.getAttributeType(),
            supportedSASLMechAttrs);
      }
      else
      {
        dseOperationalAttrs.put(supportedSASLMechAttr.getAttributeType(),
            supportedSASLMechAttrs);
      }
    }
@@ -649,26 +694,28 @@
         createAttribute(ATTR_SUPPORTED_LDAP_VERSION,
                         ATTR_SUPPORTED_LDAP_VERSION_LC,
                         versionStrings);
    ArrayList<Attribute> supportedLDAPVersionAttrs =
         new ArrayList<Attribute>(1);
    supportedLDAPVersionAttrs.add(supportedLDAPVersionAttr);
    if (showAllAttributes ||
        (! supportedLDAPVersionAttr.getAttributeType().isOperational()))
    if (!supportedLDAPVersionAttr.isEmpty())
    {
      dseUserAttrs.put(supportedLDAPVersionAttr.getAttributeType(),
                       supportedLDAPVersionAttrs);
    }
    else
    {
      dseOperationalAttrs.put(supportedLDAPVersionAttr.getAttributeType(),
                              supportedLDAPVersionAttrs);
      List<Attribute> supportedLDAPVersionAttrs = new ArrayList<Attribute>(1);
      supportedLDAPVersionAttrs.add(supportedLDAPVersionAttr);
      if (showAllAttributes
          || (!supportedLDAPVersionAttr.getAttributeType().isOperational()))
      {
        dseUserAttrs.put(supportedLDAPVersionAttr.getAttributeType(),
            supportedLDAPVersionAttrs);
      }
      else
      {
        dseOperationalAttrs.put(supportedLDAPVersionAttr.getAttributeType(),
            supportedLDAPVersionAttrs);
      }
    }
    // Add the "supportedAuthPasswordSchemes" attribute.
    Set<String> authPWSchemes =
         DirectoryServer.getAuthPasswordStorageSchemes().keySet();
    if (! authPWSchemes.isEmpty())
    if (!authPWSchemes.isEmpty())
    {
      Attribute supportedAuthPWSchemesAttr =
           createAttribute(ATTR_SUPPORTED_AUTH_PW_SCHEMES,
@@ -690,6 +737,77 @@
    }
    // Obtain TLS protocol and cipher support.
    Collection<String> supportedTlsProtocols;
    Collection<String> supportedTlsCiphers;
    if (connection != null)
    {
      // Only return the list of enabled protocols / ciphers for the connection
      // handler to which the client is connected.
      supportedTlsProtocols = connection.getConnectionHandler()
          .getEnabledSSLProtocols();
      supportedTlsCiphers = connection.getConnectionHandler()
          .getEnabledSSLCipherSuites();
    }
    else
    {
      try
      {
        final SSLContext context = SSLContext.getDefault();
        final SSLParameters parameters = context.getSupportedSSLParameters();
        supportedTlsProtocols = Arrays.asList(parameters.getProtocols());
        supportedTlsCiphers = Arrays.asList(parameters.getCipherSuites());
      }
      catch (Exception e)
      {
        // A default SSL context should always be available.
        supportedTlsProtocols = Collections.emptyList();
        supportedTlsCiphers = Collections.emptyList();
      }
    }
    // Add the "supportedTLSProtocols" attribute.
    Attribute supportedTLSProtocolsAttr = createAttribute(
        ATTR_SUPPORTED_TLS_PROTOCOLS, ATTR_SUPPORTED_TLS_PROTOCOLS_LC,
        supportedTlsProtocols);
    if (!supportedTLSProtocolsAttr.isEmpty())
    {
      List<Attribute> supportedTLSProtocolsAttrs = new ArrayList<Attribute>(1);
      supportedTLSProtocolsAttrs.add(supportedTLSProtocolsAttr);
      if (showAllAttributes
          || (!supportedTLSProtocolsAttr.getAttributeType().isOperational()))
      {
        dseUserAttrs.put(supportedTLSProtocolsAttr.getAttributeType(),
            supportedTLSProtocolsAttrs);
      }
      else
      {
        dseOperationalAttrs.put(supportedTLSProtocolsAttr.getAttributeType(),
            supportedTLSProtocolsAttrs);
      }
    }
    // Add the "supportedTLSCiphers" attribute.
    Attribute supportedTLSCiphersAttr = createAttribute(
        ATTR_SUPPORTED_TLS_CIPHERS, ATTR_SUPPORTED_TLS_CIPHERS_LC,
        supportedTlsCiphers);
    if (!supportedTLSCiphersAttr.isEmpty())
    {
      List<Attribute> supportedTLSCiphersAttrs = new ArrayList<Attribute>(1);
      supportedTLSCiphersAttrs.add(supportedTLSCiphersAttr);
      if (showAllAttributes
          || (!supportedTLSCiphersAttr.getAttributeType().isOperational()))
      {
        dseUserAttrs.put(supportedTLSCiphersAttr.getAttributeType(),
            supportedTLSCiphersAttrs);
      }
      else
      {
        dseOperationalAttrs.put(supportedTLSCiphersAttr.getAttributeType(),
            supportedTLSCiphersAttrs);
      }
    }
    // Add all the standard "static" attributes.
    for (Attribute a : staticDSEAttributes)
    {
@@ -772,33 +890,6 @@
  /**
   * Retrieves the root DSE entry for the given network group.
   *
   * @param   ng  The network group for which we want the root DSE entry
   * @return  The root DSE entry for the given network group.
   */
  public Entry getRootDSE(NetworkGroup ng)
  {
    Entry e = getRootDSE();
    // Simply replace the list of naming contexts with those known by
    // the provided network group.
    TreeSet<DN> dn = new TreeSet<DN>();
    for (WorkflowTopologyNode node :
        ng.getNamingContexts().getPublicNamingContexts()) {
      dn.add(node.getBaseDN());
    }
    Attribute publicNamingContextAttr =
         createDNAttribute(ATTR_NAMING_CONTEXTS, ATTR_NAMING_CONTEXTS_LC, dn);
    e.replaceAttribute(publicNamingContextAttr);
    return e;
  }
  /**
   * Determines the workflow nodes which handle subordinate naming contexts.
   * A workflow node is handling a subordinate naming context if the workflow
   * base DN is in the list of the RootDSE subordinate naming contexts.
@@ -1041,8 +1132,7 @@
    switch (searchOperation.getScope())
    {
      case BASE_OBJECT:
        Entry dseEntry = getRootDSE(
            searchOperation.getClientConnection().getNetworkGroup());
        Entry dseEntry = getRootDSE(searchOperation.getClientConnection());
        if (filter.matchesEntry(dseEntry))
        {
          searchOperation.returnEntry(dseEntry, null);
opends/src/server/org/opends/server/core/ConnectionHandlerConfigManager.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions copyright 2012 ForgeRock AS.
 */
package org.opends.server.core;
import org.opends.messages.Message;
@@ -39,6 +40,7 @@
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.opends.server.admin.AdministrationConnector;
@@ -80,8 +82,8 @@
  // The mapping between configuration entry DNs and their
  // corresponding connection handler implementations.
  private ConcurrentHashMap<DN, ConnectionHandler> connectionHandlers =
        new ConcurrentHashMap<DN, ConnectionHandler>();
  private final Map<DN, ConnectionHandler<?>> connectionHandlers =
        new ConcurrentHashMap<DN, ConnectionHandler<?>>();
@@ -251,7 +253,7 @@
    // deregister and stop it. We'll try to leave any established
    // connections alone if possible.
    DN dn = configuration.dn();
    ConnectionHandler connectionHandler = connectionHandlers.get(dn);
    ConnectionHandler<?> connectionHandler = connectionHandlers.get(dn);
    if (connectionHandler != null) {
      DirectoryServer.deregisterConnectionHandler(connectionHandler);
      connectionHandlers.remove(dn);
@@ -280,7 +282,11 @@
   */
  public void initializeConnectionHandlerConfig()
      throws ConfigException, InitializationException {
    connectionHandlers = new ConcurrentHashMap<DN, ConnectionHandler>();
    // Clear the set of connection handlers in case of in-core restart.
    connectionHandlers.clear();
    // Initialize the admin connector.
    initializeAdministrationConnectorConfig();
    // Get the root configuration which acts as the parent of all
    // connection handlers.
@@ -325,20 +331,7 @@
  /**
   * Initializes the configuration associated with the Directory
   * Server administration connector. This should only be called at
   * Directory Server startup.
   *
   * @throws ConfigException
   *           If a critical configuration problem prevents the
   *           administration connector initialization from succeeding.
   * @throws InitializationException
   *           If a problem occurs while initializing the administration
   *           connector that is not related to the server
   *           configuration.
   */
  public void initializeAdministrationConnectorConfig()
  private void initializeAdministrationConnectorConfig()
    throws ConfigException, InitializationException {
    RootCfg root =
@@ -417,6 +410,7 @@
        .getJavaClassPropertyDefinition();
    // Load the class and cast it to a connection handler.
    @SuppressWarnings("rawtypes")
    Class<? extends ConnectionHandler> theClass;
    ConnectionHandler<?> connectionHandler;
@@ -475,7 +469,8 @@
        .getJavaClassPropertyDefinition();
    // Load the class and cast it to a connection handler.
    ConnectionHandler connectionHandler = null;
    ConnectionHandler<?> connectionHandler = null;
    @SuppressWarnings("rawtypes")
    Class<? extends ConnectionHandler> theClass;
    try {
      connectionHandler = connectionHandlers.get(config.dn());
opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -57,6 +57,7 @@
import org.opends.messages.Message;
import org.opends.messages.MessageDescriptor;
import org.opends.server.admin.AdministrationConnector;
import org.opends.server.admin.AdministrationDataSync;
import org.opends.server.admin.ClassLoaderProvider;
import org.opends.server.admin.server.ServerManagementContext;
@@ -1252,28 +1253,23 @@
      entryCacheConfigManager = new EntryCacheConfigManager();
      entryCacheConfigManager.initializeDefaultEntryCache();
      // Initialize the administration connector.
      // Initialize the administration connector self signed certificate if
      // needed and do this before initializing the key managers so that it is
      // picked up.
      if (startConnectionHandlers)
      {
        initializeAdministrationConnector();
        AdministrationConnector.createSelfSignedCertificateIfNeeded();
      }
        // Initialize the key manager provider.
      // Initialize the key manager provider.
      keyManagerProviderConfigManager = new KeyManagerProviderConfigManager();
      keyManagerProviderConfigManager.initializeKeyManagerProviders();
      // Initialize the extension.
      extensionConfigManager = new ExtensionConfigManager();
      extensionConfigManager.initializeExtensions();
      // Initialize the trust manager provider.
      trustManagerProviderConfigManager =
           new TrustManagerProviderConfigManager();
      trustManagerProviderConfigManager.initializeTrustManagerProviders();
      // Initialize the certificate mapper.
      certificateMapperConfigManager = new CertificateMapperConfigManager();
      certificateMapperConfigManager.initializeCertificateMappers();
@@ -1360,6 +1356,12 @@
      // Load and initialize the user plugins.
      pluginConfigManager.initializeUserPlugins(null);
      // Initialize the extensions.
      extensionConfigManager = new ExtensionConfigManager();
      extensionConfigManager.initializeExtensions();
      // Initialize any synchronization providers that may be defined.
      if (!environmentConfig.disableSynchronization())
      {
@@ -2738,27 +2740,6 @@
  /**
   * Initializes the administration connector for the Directory Server.
   *
   * @throws  ConfigException  If a configuration problem is identified while
   *                           initializing the administration connector.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   the administration connector that is not
   *                                   related to the server configuration.
   */
  public void initializeAdministrationConnector()
         throws ConfigException, InitializationException
  {
    if (connectionHandlerConfigManager == null) {
      connectionHandlerConfigManager = new ConnectionHandlerConfigManager();
    }
    connectionHandlerConfigManager.initializeAdministrationConnectorConfig();
  }
  /**
   * Initializes the subentry manager for the Directory Server.
   * Note that the subentry manager initialization should be
   * done before any dependent components initialization and
opends/src/server/org/opends/server/extensions/TLSByteChannel.java
@@ -39,13 +39,10 @@
import java.security.cert.Certificate;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.net.ssl.*;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import org.opends.server.admin.std.server.LDAPConnectionHandlerCfg;
import org.opends.server.api.ClientConnection;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.types.DebugLogLevel;
@@ -443,32 +440,6 @@
  private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0);
  private static final DebugTracer TRACER = getTracer();
  /**
   * Create an TLS byte channel instance using the specified LDAP connection
   * configuration, client connection, SSL context and socket channel
   * parameters.
   *
   * @param config
   *          The LDAP connection configuration.
   * @param c
   *          The client connection.
   * @param sslContext
   *          The SSL context.
   * @param socketChannel
   *          The socket channel.
   * @return A TLS capable byte channel.
   */
  public static TLSByteChannel getTLSByteChannel(
      final LDAPConnectionHandlerCfg config, final ClientConnection c,
      final SSLContext sslContext, final ByteChannel socketChannel)
  {
    return new TLSByteChannel(config, c, socketChannel, sslContext);
  }
  private final ByteChannelImpl pimpl = new ByteChannelImpl();
  private final ByteChannel channel;
  private final SSLEngine sslEngine;
@@ -485,55 +456,20 @@
  private TLSByteChannel(final LDAPConnectionHandlerCfg config,
      final ClientConnection c, final ByteChannel channel,
      final SSLContext sslContext)
  /**
   * Creates an TLS byte channel instance using the specified LDAP connection
   * configuration, client connection, SSL context and socket channel
   * parameters.
   *
   * @param channel
   *          The underlying channel.
   * @param sslEngine
   *          The SSL engine to use.
   */
  public TLSByteChannel(final ByteChannel channel, final SSLEngine sslEngine)
  {
    this.channel = channel;
    // getHostName could potentially be very expensive and could block
    // the connection handler for several minutes. (See issue 4229)
    // Accepting new connections should be done in a seperate thread to
    // avoid blocking new connections. Just remove for now to prevent
    // potential DoS attacks. SSL sessions will not be reused and some
    // cipher suites (such as Kerberos) will not work.
    // String hostName = socketChannel.socket().getInetAddress().getHostName();
    // int port = socketChannel.socket().getPort();
    // sslEngine = sslContext.createSSLEngine(hostName, port);
    sslEngine = sslContext.createSSLEngine();
    sslEngine.setUseClientMode(false);
    final Set<String> protocols = config.getSSLProtocol();
    if (!protocols.isEmpty())
    {
      sslEngine.setEnabledProtocols(protocols.toArray(new String[0]));
    }
    final Set<String> ciphers = config.getSSLCipherSuite();
    if (!ciphers.isEmpty())
    {
      sslEngine.setEnabledCipherSuites(ciphers.toArray(new String[0]));
    }
    switch (config.getSSLClientAuthPolicy())
    {
    case DISABLED:
      sslEngine.setNeedClientAuth(false);
      sslEngine.setWantClientAuth(false);
      break;
    case REQUIRED:
      sslEngine.setWantClientAuth(true);
      sslEngine.setNeedClientAuth(true);
      break;
    case OPTIONAL:
    default:
      sslEngine.setNeedClientAuth(false);
      sslEngine.setWantClientAuth(true);
      break;
    }
    this.sslEngine = sslEngine;
    // Allocate read/write buffers.
    final SSLSession session = sslEngine.getSession();
opends/src/server/org/opends/server/monitors/SystemInfoMonitorProvider.java
@@ -23,19 +23,27 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions copyright 2012 ForgeRock AS.
 */
package org.opends.server.monitors;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.util.ServerConstants.*;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import org.opends.server.admin.std.server.SystemInfoMonitorProviderCfg;
import org.opends.server.api.MonitorProvider;
import org.opends.server.config.ConfigException;
@@ -184,6 +192,44 @@
      attrs.add(createAttribute("jvmArguments", argList.toString()));
    }
    // Get the list of supported SSL protocols and ciphers.
    Collection<String> supportedTlsProtocols;
    Collection<String> supportedTlsCiphers;
    try
    {
      final SSLContext context = SSLContext.getDefault();
      final SSLParameters parameters = context.getSupportedSSLParameters();
      supportedTlsProtocols = Arrays.asList(parameters.getProtocols());
      supportedTlsCiphers = Arrays.asList(parameters.getCipherSuites());
    }
    catch (Exception e)
    {
      // A default SSL context should always be available.
      supportedTlsProtocols = Collections.emptyList();
      supportedTlsCiphers = Collections.emptyList();
    }
    // Add the "supportedTLSProtocols" attribute.
    AttributeType supportedTLSProtocolsAttrType = DirectoryServer
        .getDefaultAttributeType(ATTR_SUPPORTED_TLS_PROTOCOLS);
    AttributeBuilder builder = new AttributeBuilder(
        supportedTLSProtocolsAttrType);
    for (String value : supportedTlsProtocols)
    {
      builder.add(value);
    }
    attrs.add(builder.toAttribute());
    // Add the "supportedTLSCiphers" attribute.
    AttributeType supportedTLSCiphersAttrType = DirectoryServer
        .getDefaultAttributeType(ATTR_SUPPORTED_TLS_CIPHERS);
    builder = new AttributeBuilder(supportedTLSCiphersAttrType);
    for (String value : supportedTlsCiphers)
    {
      builder.add(value);
    }
    attrs.add(builder.toAttribute());
    return attrs;
  }
opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -55,6 +55,8 @@
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.net.ssl.SSLException;
import org.opends.messages.Message;
import org.opends.messages.MessageBuilder;
import org.opends.server.api.ClientConnection;
@@ -496,8 +498,7 @@
    if (connectionHandler.useSSL())
    {
      enableSSL(connectionHandler.getTLSByteChannel(this,
          timeoutClientChannel));
      enableSSL(connectionHandler.getTLSByteChannel(timeoutClientChannel));
    }
    connectionID = DirectoryServer.newConnectionAccepted(this);
@@ -1615,7 +1616,7 @@
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      if (asn1Reader.hasRemainingData())
      if (asn1Reader.hasRemainingData() || (e instanceof SSLException))
      {
        // The connection failed, but there was an unread partial message so
        // interpret this as an IO error.
@@ -2536,7 +2537,7 @@
    try
    {
      TLSByteChannel tlsByteChannel =
          connectionHandler.getTLSByteChannel(this, timeoutClientChannel);
          connectionHandler.getTLSByteChannel(timeoutClientChannel);
      setTLSPendingProvider(tlsByteChannel);
    }
    catch (DirectoryException de)
opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
@@ -40,14 +40,14 @@
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.nio.channels.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import org.opends.messages.Message;
import org.opends.server.admin.server.ConfigurationChangeListener;
@@ -175,12 +175,6 @@
  // server.
  private AddressMask[] deniedClients;
  // The set of SSL cipher suites that should be allowed.
  private String[] enabledSSLCipherSuites;
  // The set of SSL protocols that should be allowed.
  private String[] enabledSSLProtocols;
  // The index to the request handler that will be used for the next
  // connection accepted by the server.
  private int requestHandlerIndex;
@@ -223,9 +217,10 @@
  // SSL instance name used in context creation.
  private static final String SSL_CONTEXT_INSTANCE_NAME = "TLS";
  // SSL context.
  // SSL context and engine - the engine is used for obtaining default SSL
  // parameters.
  private SSLContext sslContext;
  private boolean sslConfig = false;
  private SSLEngine sslEngine;
  /**
   * Connection finalizer thread.
@@ -340,10 +335,25 @@
    allowedClients = config.getAllowedClient().toArray(new AddressMask[0]);
    deniedClients = config.getDeniedClient().toArray(new AddressMask[0]);
    // Reconfigure SSL context if needed.
    // Reconfigure SSL if needed.
    protocol = config.isUseSSL() ? "LDAPS" : "LDAP";
    if (config.isUseSSL() || config.isAllowStartTLS())
    {
      sslConfig = true;
      try
      {
        sslContext = createSSLContext(config);
        sslEngine = createSSLEngine(config, sslContext);
      }
      catch (DirectoryException e)
      {
        if (debugEnabled())
        {
          TRACER.debugCaught(DebugLogLevel.ERROR, e);
        }
        messages.add(e.getMessageObject());
        return new ConfigChangeResult(e.getResultCode(), adminActionRequired,
            messages);
      }
    }
    if (config.isAllowLDAPV2())
@@ -501,29 +511,37 @@
  /**
   * Retrieves the set of enabled SSL cipher suites configured for this
   * connection handler.
   *
   * @return The set of enabled SSL cipher suites configured for this connection
   *         handler.
   * {@inheritDoc}
   */
  public String[] getEnabledSSLCipherSuites()
  public Collection<String> getEnabledSSLCipherSuites()
  {
    return enabledSSLCipherSuites;
    if (currentConfig.isUseSSL() || currentConfig.isAllowStartTLS())
    {
      final SSLEngine engine = sslEngine;
      if (engine != null)
      {
        return Arrays.asList(engine.getEnabledCipherSuites());
      }
    }
    return super.getEnabledSSLCipherSuites();
  }
  /**
   * Retrieves the set of enabled SSL protocols configured for this connection
   * handler.
   *
   * @return The set of enabled SSL protocols configured for this connection
   *         handler.
   * {@inheritDoc}
   */
  public String[] getEnabledSSLProtocols()
  public Collection<String> getEnabledSSLProtocols()
  {
    return enabledSSLProtocols;
    if (currentConfig.isUseSSL() || currentConfig.isAllowStartTLS())
    {
      final SSLEngine engine = sslEngine;
      if (engine != null)
      {
        return Arrays.asList(engine.getEnabledProtocols());
      }
    }
    return super.getEnabledSSLProtocols();
  }
@@ -669,8 +687,6 @@
      throw new InitializationException(message, e);
    }
    protocol = "LDAP";
    // Save this configuration for future reference.
    currentConfig = config;
    enabled = config.isEnabled();
@@ -678,8 +694,24 @@
    allowedClients = config.getAllowedClient().toArray(new AddressMask[0]);
    deniedClients = config.getDeniedClient().toArray(new AddressMask[0]);
    // Setup SSL context if needed.
    if (config.isUseSSL() || config.isAllowStartTLS()) sslConfig = true;
    // Configure SSL if needed.
    protocol = config.isUseSSL() ? "LDAPS" : "LDAP";
    if (config.isUseSSL() || config.isAllowStartTLS())
    {
      try
      {
        sslContext = createSSLContext(config);
        sslEngine = createSSLEngine(config, sslContext);
      }
      catch (DirectoryException e)
      {
        if (debugEnabled())
        {
          TRACER.debugCaught(DebugLogLevel.ERROR, e);
        }
        throw new InitializationException(e.getMessageObject());
      }
    }
    // Save properties that cannot be dynamically modified.
    allowReuseAddress = config.isAllowTCPReuseAddress();
@@ -786,11 +818,11 @@
  {
    LDAPConnectionHandlerCfg config = (LDAPConnectionHandlerCfg) configuration;
    // Attempt to bind to the listen port on all configured addresses to
    // verify whether the connection handler will be able to start.
    if ((currentConfig == null)
        || (!currentConfig.isEnabled() && config.isEnabled()))
    {
      // Attempt to bind to the listen port on all configured addresses to
      // verify whether the connection handler will be able to start.
      for (InetAddress a : config.getListenAddress())
      {
        try
@@ -817,7 +849,31 @@
        }
      }
    }
    return isConfigurationChangeAcceptable(config, unacceptableReasons);
    if (config.isEnabled())
    {
      // Check that the SSL configuration is valid.
      if (config.isUseSSL() || config.isAllowStartTLS())
      {
        try
        {
          SSLContext sslContext = createSSLContext(config);
          createSSLEngine(config, sslContext);
        }
        catch (DirectoryException e)
        {
          if (debugEnabled())
          {
            TRACER.debugCaught(DebugLogLevel.ERROR, e);
          }
          unacceptableReasons.add(e.getMessageObject());
          return false;
        }
      }
    }
    return true;
  }
@@ -828,8 +884,7 @@
  public boolean isConfigurationChangeAcceptable(
      LDAPConnectionHandlerCfg config, List<Message> unacceptableReasons)
  {
    // All validation is performed by the admin framework.
    return true;
    return isConfigurationAcceptable(config, unacceptableReasons);
  }
@@ -1153,8 +1208,8 @@
    // Check to see if the core server rejected the
    // connection (e.g., already too many connections
    // established).
    LDAPClientConnection clientConnection =
        createClientConnection(clientChannel);
    LDAPClientConnection clientConnection = new LDAPClientConnection(this,
        clientChannel, getProtocol());
    if (clientConnection.getConnectionID() < 0)
    {
      // The connection will have already been closed.
@@ -1326,97 +1381,126 @@
  private LDAPClientConnection createClientConnection(
      SocketChannel socketChannel) throws DirectoryException
  {
    if (sslConfig)
    {
      configSSL(currentConfig);
      sslConfig = false;
    }
    LDAPClientConnection c = new LDAPClientConnection(this, socketChannel,
        getProtocol());
    return c;
  }
  /**
   * Creates a TLS Byte Channel instance using the specified LDAP client
   * connection and socket channel.
   * Creates a TLS Byte Channel instance using the specified socket channel.
   *
   * @param c
   *          The client connection to use in the creation.
   * @param socketChannel
   * @param channel
   *          The socket channel to use in the creation.
   * @return A TLS Byte Channel instance.
   * @throws DirectoryException
   *           If the channel cannot be created.
   */
  public TLSByteChannel getTLSByteChannel(LDAPClientConnection c,
      ByteChannel socketChannel) throws DirectoryException
  public TLSByteChannel getTLSByteChannel(ByteChannel channel)
      throws DirectoryException
  {
    return (TLSByteChannel.getTLSByteChannel(currentConfig, c, sslContext,
        socketChannel));
    SSLEngine sslEngine = createSSLEngine(currentConfig, sslContext);
    return new TLSByteChannel(channel, sslEngine);
  }
  private void configSSL(LDAPConnectionHandlerCfg config)
      throws DirectoryException
  private SSLEngine createSSLEngine(LDAPConnectionHandlerCfg config,
      SSLContext sslContext) throws DirectoryException
  {
    ResultCode resCode = DirectoryServer.getServerErrorResultCode();
    try
    {
      String alias = config.getSSLCertNickname();
      if (config.isUseSSL())
      SSLEngine sslEngine = sslContext.createSSLEngine();
      sslEngine.setUseClientMode(false);
      final Set<String> protocols = config.getSSLProtocol();
      if (!protocols.isEmpty())
      {
        protocol = "LDAPS";
        sslEngine.setEnabledProtocols(protocols.toArray(new String[0]));
      }
      final Set<String> ciphers = config.getSSLCipherSuite();
      if (!ciphers.isEmpty())
      {
        sslEngine.setEnabledCipherSuites(ciphers.toArray(new String[0]));
      }
      switch (config.getSSLClientAuthPolicy())
      {
      case DISABLED:
        sslEngine.setNeedClientAuth(false);
        sslEngine.setWantClientAuth(false);
        break;
      case REQUIRED:
        sslEngine.setWantClientAuth(true);
        sslEngine.setNeedClientAuth(true);
        break;
      case OPTIONAL:
      default:
        sslEngine.setNeedClientAuth(false);
        sslEngine.setWantClientAuth(true);
        break;
      }
      return sslEngine;
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      ResultCode resCode = DirectoryServer.getServerErrorResultCode();
      Message message = ERR_CONNHANDLER_SSL_CANNOT_INITIALIZE
          .get(getExceptionMessage(e));
      throw new DirectoryException(resCode, message, e);
    }
  }
  private SSLContext createSSLContext(LDAPConnectionHandlerCfg config)
      throws DirectoryException
  {
    try
    {
      DN keyMgrDN = config.getKeyManagerProviderDN();
      DN trustMgrDN = config.getTrustManagerProviderDN();
      KeyManagerProvider<?> keyManagerProvider = DirectoryServer
          .getKeyManagerProvider(keyMgrDN);
      if (keyManagerProvider == null)
      {
        keyManagerProvider = new NullKeyManagerProvider();
      TrustManagerProvider<?> trustManagerProvider = DirectoryServer
          .getTrustManagerProvider(trustMgrDN);
      if (trustManagerProvider == null)
        trustManagerProvider = new NullTrustManagerProvider();
      sslContext = SSLContext.getInstance(SSL_CONTEXT_INSTANCE_NAME);
      }
      String alias = config.getSSLCertNickname();
      KeyManager[] keyManagers;
      if (alias == null)
      {
        sslContext.init(keyManagerProvider.getKeyManagers(),
            trustManagerProvider.getTrustManagers(), null);
        keyManagers = keyManagerProvider.getKeyManagers();
      }
      else
      {
        sslContext.init(
            SelectableCertificateKeyManager.wrap(
                keyManagerProvider.getKeyManagers(), alias),
            trustManagerProvider.getTrustManagers(), null);
        keyManagers = SelectableCertificateKeyManager.wrap(
            keyManagerProvider.getKeyManagers(), alias);
      }
      DN trustMgrDN = config.getTrustManagerProviderDN();
      TrustManagerProvider<?> trustManagerProvider = DirectoryServer
          .getTrustManagerProvider(trustMgrDN);
      if (trustManagerProvider == null)
      {
        trustManagerProvider = new NullTrustManagerProvider();
      }
      SSLContext sslContext = SSLContext.getInstance(SSL_CONTEXT_INSTANCE_NAME);
      sslContext.init(keyManagers, trustManagerProvider.getTrustManagers(),
          null);
      return sslContext;
    }
    catch (NoSuchAlgorithmException nsae)
    catch (Exception e)
    {
      if (debugEnabled()) TRACER.debugCaught(DebugLogLevel.ERROR, nsae);
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      ResultCode resCode = DirectoryServer.getServerErrorResultCode();
      Message message = ERR_CONNHANDLER_SSL_CANNOT_INITIALIZE
          .get(getExceptionMessage(nsae));
      throw new DirectoryException(resCode, message, nsae);
    }
    catch (KeyManagementException kme)
    {
      if (debugEnabled()) TRACER.debugCaught(DebugLogLevel.ERROR, kme);
      Message message = ERR_CONNHANDLER_SSL_CANNOT_INITIALIZE
          .get(getExceptionMessage(kme));
      throw new DirectoryException(resCode, message, kme);
    }
    catch (DirectoryException de)
    {
      if (debugEnabled()) TRACER.debugCaught(DebugLogLevel.ERROR, de);
      Message message = ERR_CONNHANDLER_SSL_CANNOT_INITIALIZE
          .get(getExceptionMessage(de));
      throw new DirectoryException(resCode, message, de);
          .get(getExceptionMessage(e));
      throw new DirectoryException(resCode, message, e);
    }
  }
opends/src/server/org/opends/server/util/ServerConstants.java
@@ -573,6 +573,42 @@
  /**
   * The name of the standard attribute that is used to specify the versions of
   * the TLS protocol supported by the server, formatted in camel case.
   */
  public static final String ATTR_SUPPORTED_TLS_PROTOCOLS =
      "supportedTLSProtocols";
  /**
   * The name of the standard attribute that is used to specify the versions of
   * the TLS protocol supported by the server, formatted in lower case.
   */
  public static final String ATTR_SUPPORTED_TLS_PROTOCOLS_LC =
      "supportedtlsprotocols";
  /**
   * The name of the standard attribute that is used to specify the the TLS
   * ciphers supported by the server, formatted in camel case.
   */
  public static final String ATTR_SUPPORTED_TLS_CIPHERS =
      "supportedTLSCiphers";
  /**
   * The name of the standard attribute that is used to specify the the TLS
   * ciphers supported by the server, formatted in lower case.
   */
  public static final String ATTR_SUPPORTED_TLS_CIPHERS_LC =
      "supportedtlsciphers";
  /**
   * The name of the attribute that is used to specify the time that the
   * Directory Server started, formatted in camel case.
   */
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SASLOverTLSTestCase.java
@@ -28,24 +28,41 @@
package org.opends.server.extensions;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Random;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.*;
import javax.naming.ldap.*;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.StartTlsRequest;
import javax.naming.ldap.StartTlsResponse;
import javax.net.SocketFactory;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import org.opends.admin.ads.util.BlindTrustManager;
import org.opends.server.TestCaseUtils;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
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.DirectoryServer;
import org.testng.Assert;
/**
 * This class tests SASL confidentiality/integrity over TLS (SSL). It
@@ -54,6 +71,78 @@
 *
 */
public class SASLOverTLSTestCase extends ExtensionsTestCase {
  /**
   * Client SSL socket factory which blindly trusts server certificates.
   */
  public static final class TestSSLSocketFactory extends SSLSocketFactory
  {
    public static synchronized SocketFactory getDefault()
    {
      return INSTANCE;
    }
    private static final TestSSLSocketFactory INSTANCE = new TestSSLSocketFactory();
    private final SSLSocketFactory factory;
    private TestSSLSocketFactory()
    {
      try
      {
        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(null, new TrustManager[] { new BlindTrustManager() }, null);
        factory = ctx.getSocketFactory();
      }
      catch (Exception e)
      {
        throw new RuntimeException(e);
      }
    }
    public Socket createSocket() throws IOException
    {
      return factory.createSocket();
    }
    public Socket createSocket(String host, int port) throws IOException,
        UnknownHostException
    {
      return factory.createSocket(host, port);
    }
    public String[] getDefaultCipherSuites()
    {
      return factory.getDefaultCipherSuites();
    }
    public String[] getSupportedCipherSuites()
    {
      return factory.getSupportedCipherSuites();
    }
    public Socket createSocket(Socket s, String host, int port,
        boolean autoClose) throws IOException
    {
      return factory.createSocket(s, host, port, autoClose);
    }
    public Socket createSocket(String host, int port, InetAddress localHost,
        int localPort) throws IOException, UnknownHostException
    {
      return factory.createSocket(host, port, localHost, localPort);
    }
    public Socket createSocket(InetAddress host, int port) throws IOException
    {
      return factory.createSocket(host, port);
    }
    public Socket createSocket(InetAddress address, int port,
        InetAddress localAddress, int localPort) throws IOException
    {
      return factory.createSocket(address, port, localAddress, localPort);
    }
  }
  private static int KB = 1024;
  private static final String factory = "com.sun.jndi.ldap.LdapCtxFactory";
@@ -63,14 +152,6 @@
  private static final String pwdPolicyDN =
                     "cn=" + pwdPolicy + ",cn=Password Policies,cn=config";
  //Keystore/truststore paths
  private String keyStorePath =
         DirectoryServer.getInstanceRoot() + File.separator + "config" +
         File.separator + "client.keystore";
  private String trustStorePath =
          DirectoryServer.getInstanceRoot() + File.separator +  "config" +
          File.separator + "client.truststore";
  //DNS
  private static String testUserDN = "cn=test.User, o=test";
  private static final String digestDN = "dn:"+ testUserDN;
@@ -111,14 +192,6 @@
            "--handler-name", "DIGEST-MD5",
            "--set", "quality-of-protection:" + "confidentiality",
            "--set", "server-fqdn:localhost");
    keyStorePath = DirectoryServer.getInstanceRoot() + File.separator +
                          "config" + File.separator + "client.keystore";
    trustStorePath = DirectoryServer.getInstanceRoot() + File.separator +
                            "config" + File.separator + "client.truststore";
    System.setProperty("javax.net.ssl.keyStore",keyStorePath);
    System.setProperty("javax.net.ssl.keyStorePassword", "password");
    System.setProperty("javax.net.ssl.trustStore", trustStorePath);
    System.setProperty("javax.net.ssl.trustStorePassword", "password");
    addTestEntry();
  }
@@ -142,7 +215,7 @@
   * @throws NamingException If there was an JNDi naming error.
   * @throws IOException If there was an IO error occurs.
   */
  @Test(dataProvider = "kiloBytes")
  @Test(enabled = false, dataProvider = "kiloBytes")
  public void sslIntegrity(int size)throws NamingException, IOException {
    TestCaseUtils.dsconfig(
        "set-sasl-mechanism-handler-prop",
@@ -157,7 +230,7 @@
   * @throws NamingException If there was an JNDi naming error.
   * @throws IOException If there was an IO error occurs.
   */
  @Test(dataProvider = "kiloBytes")
  @Test(enabled = false, dataProvider = "kiloBytes")
  public void sslConfidentiality(int size)throws NamingException, IOException {
    TestCaseUtils.dsconfig(
        "set-sasl-mechanism-handler-prop",
@@ -189,6 +262,7 @@
      env.put(Context.SECURITY_CREDENTIALS, "password");
      env.put("java.naming.ldap.attributes.binary", "jpegPhoto");
      env.put("javax.security.sasl.qop", qop);
      env.put("java.naming.ldap.factory.socket", TestSSLSocketFactory.class.getName());
      ctx = new InitialLdapContext(env, null);
      byte[] jpegBytes = getRandomBytes(size);
      ModificationItem[] mods = new ModificationItem[1];
@@ -213,8 +287,8 @@
   * @throws NamingException If there was an JNDi naming error.
   * @throws IOException If there was an IO error.
   */
  @Test(dataProvider = "kiloBytes")
  public void StartTLS(int size) throws NamingException, IOException {
  @Test(enabled = false, dataProvider = "kiloBytes")
  public void startTLS(int size) throws NamingException, IOException {
    LdapContext ctx = null;
    try {
      Hashtable<String, String> env = new Hashtable<String, String>();
@@ -276,6 +350,7 @@
      env.put(Context.SECURITY_PRINCIPAL, dirMgr);
      env.put(Context.SECURITY_CREDENTIALS, "password");
      env.put(Context.SECURITY_AUTHENTICATION, simple);
      env.put("java.naming.ldap.factory.socket", TestSSLSocketFactory.class.getName());
      ctx = new InitialDirContext(env);
      ctx.bind(testUserDN, null, entryAttrs);
      ModificationItem[] mods = new ModificationItem[1];
@@ -318,6 +393,7 @@
      env.put(Context.SECURITY_PRINCIPAL, dirMgr);
      env.put(Context.SECURITY_CREDENTIALS, "password");
      env.put(Context.SECURITY_AUTHENTICATION, "simple");
      env.put("java.naming.ldap.factory.socket", TestSSLSocketFactory.class.getName());
      ctx = new InitialDirContext(env);
      ctx.destroySubcontext(testUserDN);
    } finally {
opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/ldap/TestLDAPConnectionHandler.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions copyright 2012 ForgeRock AS.
 */
package org.opends.server.protocols.ldap;
@@ -110,8 +111,8 @@
    LinkedHashMap<String,String> alerts = LDAPConnHandler.getAlerts();
    String c=LDAPConnHandler.getClassName();
    DN dn = LDAPConnHandler.getComponentEntryDN();
    String[] cips = LDAPConnHandler.getEnabledSSLCipherSuites();
    String[] protos = LDAPConnHandler.getEnabledSSLProtocols();
    Collection<String> cips = LDAPConnHandler.getEnabledSSLCipherSuites();
    Collection<String> protos = LDAPConnHandler.getEnabledSSLProtocols();
    int maxReqSize = LDAPConnHandler.getMaxRequestSize();
    String shutListName=LDAPConnHandler.getShutdownListenerName();
    SSLClientAuthPolicy policy = LDAPConnHandler.getSSLClientAuthPolicy();