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

Jean-Noel Rouvignac
23.19.2013 e97c9f71197fcea5cddc0f7c36f16df1714fb0bb
OPENDJ-917 (CR-1731) HTTP Connection Handler - Fix HTTPS support



HTTPS was wrongly configured: code was configuring an SSLEngine that was then never used.
Changed the code to configure an SSLEngineConfigurator that is passed down to Grizzly HTTP server.



(Un)surprisingly I hit a bug on my Linux Mint:
https://bugs.launchpad.net/ubuntu/+source/openjdk-6/+bug/1006776
I had to modify /etc/java-6-openjdk/security/java.security so it uses the sun Elliptic Curve implementation by changing the line
security.provider.9=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/nss.cfg
to
security.provider.9=sun.security.ec.SunEC
#security.provider.10=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/nss.cfg



HTTPConnectionHandler.java:
Replaced instance members sslContext and sslEngine with sslEngineConfigurator.
Renamed createSSLEngine() into createSSLEngineConfigurator().
In createSSLContext(), removed the try / catch block duplicated with the one in createSSLEngineConfigurator().
As a consequence, the following methods changed: configureSSL(), getEnabledSSLCipherSuites(), getEnabledSSLProtocols(), getSSLEngine(), isConfigurationAcceptable(), startHttpServer().
1 files modified
146 ■■■■■ changed files
opends/src/server/org/opends/server/protocols/http/HTTPConnectionHandler.java 146 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/protocols/http/HTTPConnectionHandler.java
@@ -188,15 +188,8 @@
  /** The friendly name of this connection handler. */
  private String friendlyName;
  /**
   * SSL context.
   *
   * @see HTTPConnectionHandler#sslEngine
   */
  private SSLContext sslContext;
  /** The SSL engine is used for obtaining default SSL parameters. */
  private SSLEngine sslEngine;
  /** The SSL engine configurator is used for obtaining default SSL parameters. */
  private SSLEngineConfigurator sslEngineConfigurator;
  /**
   * Default constructor. It is invoked by reflection to create this
@@ -341,13 +334,11 @@
    protocol = config.isUseSSL() ? "HTTPS" : "HTTP";
    if (config.isUseSSL())
    {
      sslContext = createSSLContext(config);
      sslEngine = createSSLEngine(config, sslContext);
      sslEngineConfigurator = createSSLEngineConfigurator(config);
    }
    else
    {
      sslContext = null;
      sslEngine = null;
      sslEngineConfigurator = null;
    }
  }
@@ -426,10 +417,10 @@
  @Override
  public Collection<String> getEnabledSSLCipherSuites()
  {
    final SSLEngine engine = sslEngine;
    if (engine != null)
    final SSLEngineConfigurator configurator = sslEngineConfigurator;
    if (configurator != null)
    {
      return Arrays.asList(engine.getEnabledCipherSuites());
      return Arrays.asList(configurator.getEnabledCipherSuites());
    }
    return super.getEnabledSSLCipherSuites();
  }
@@ -438,10 +429,10 @@
  @Override
  public Collection<String> getEnabledSSLProtocols()
  {
    final SSLEngine engine = sslEngine;
    if (engine != null)
    final SSLEngineConfigurator configurator = sslEngineConfigurator;
    if (configurator != null)
    {
      return Arrays.asList(engine.getEnabledProtocols());
      return Arrays.asList(configurator.getEnabledProtocols());
    }
    return super.getEnabledSSLProtocols();
  }
@@ -478,7 +469,7 @@
   */
  SSLEngine getSSLEngine()
  {
    return sslEngine;
    return sslEngineConfigurator.createSSLEngine();
  }
  /** {@inheritDoc} */
@@ -587,8 +578,7 @@
      {
        try
        {
          SSLContext sslContext = createSSLContext(config);
          createSSLEngine(config, sslContext);
          createSSLEngineConfigurator(config);
        }
        catch (DirectoryException e)
        {
@@ -843,10 +833,10 @@
      transport.setSelectorRunnersCount(numRequestHandlers);
      transport.setServerConnectionBackLog(currentConfig.getAcceptBacklog());
      if (sslContext != null)
      if (sslEngineConfigurator != null)
      {
        listener.setSecure(true);
        listener.setSSLEngineConfig(new SSLEngineConfigurator(sslContext));
        listener.setSSLEngineConfig(sslEngineConfigurator);
      }
    }
@@ -988,51 +978,58 @@
    buffer.append(handlerName);
  }
  private SSLEngine createSSLEngine(HTTPConnectionHandlerCfg config,
      SSLContext sslContext) throws DirectoryException
  private SSLEngineConfigurator createSSLEngineConfigurator(
      HTTPConnectionHandlerCfg config) throws DirectoryException
  {
    if (sslContext == null)
    if (!config.isUseSSL())
    {
      return null;
    }
    try
    {
      SSLEngine sslEngine = sslContext.createSSLEngine();
      sslEngine.setUseClientMode(false);
      SSLContext sslContext = createSSLContext(config);
      SSLEngineConfigurator configurator =
          new SSLEngineConfigurator(sslContext);
      configurator.setClientMode(false);
      // configure with defaults from the JVM
      final SSLEngine defaults = sslContext.createSSLEngine();
      configurator.setEnabledProtocols(defaults.getEnabledProtocols());
      configurator.setEnabledCipherSuites(defaults.getEnabledCipherSuites());
      final Set<String> protocols = config.getSSLProtocol();
      if (!protocols.isEmpty())
      {
        String[] array = protocols.toArray(new String[protocols.size()]);
        sslEngine.setEnabledProtocols(array);
        configurator.setEnabledProtocols(array);
      }
      final Set<String> ciphers = config.getSSLCipherSuite();
      if (!ciphers.isEmpty())
      {
        String[] array = ciphers.toArray(new String[ciphers.size()]);
        sslEngine.setEnabledCipherSuites(array);
        configurator.setEnabledCipherSuites(array);
      }
      switch (config.getSSLClientAuthPolicy())
      {
      case DISABLED:
        sslEngine.setNeedClientAuth(false);
        sslEngine.setWantClientAuth(false);
        configurator.setNeedClientAuth(false);
        configurator.setWantClientAuth(false);
        break;
      case REQUIRED:
        sslEngine.setWantClientAuth(true);
        sslEngine.setNeedClientAuth(true);
        configurator.setNeedClientAuth(true);
        configurator.setWantClientAuth(true);
        break;
      case OPTIONAL:
      default:
        sslEngine.setNeedClientAuth(false);
        sslEngine.setWantClientAuth(true);
        configurator.setNeedClientAuth(false);
        configurator.setWantClientAuth(true);
        break;
      }
      return sslEngine;
      return configurator;
    }
    catch (Exception e)
    {
@@ -1048,60 +1045,45 @@
  }
  private SSLContext createSSLContext(HTTPConnectionHandlerCfg config)
      throws DirectoryException
      throws Exception
  {
    if (!config.isUseSSL())
    {
      return null;
    }
    try
    DN keyMgrDN = config.getKeyManagerProviderDN();
    KeyManagerProvider<?> keyManagerProvider =
        DirectoryServer.getKeyManagerProvider(keyMgrDN);
    if (keyManagerProvider == null)
    {
      DN keyMgrDN = config.getKeyManagerProviderDN();
      KeyManagerProvider<?> keyManagerProvider =
          DirectoryServer.getKeyManagerProvider(keyMgrDN);
      if (keyManagerProvider == null)
      {
        keyManagerProvider = new NullKeyManagerProvider();
      }
      String alias = config.getSSLCertNickname();
      KeyManager[] keyManagers;
      if (alias == null)
      {
        keyManagers = keyManagerProvider.getKeyManagers();
      }
      else
      {
        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;
      keyManagerProvider = new NullKeyManagerProvider();
    }
    catch (Exception e)
    String alias = config.getSSLCertNickname();
    KeyManager[] keyManagers;
    if (alias == null)
    {
      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);
      keyManagers = keyManagerProvider.getKeyManagers();
    }
    else
    {
      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;
  }
}