From 0d31b80cec97ff9e6d9135a219ffa4e993eb5242 Mon Sep 17 00:00:00 2001
From: Chris Ridd <chris.ridd@forgerock.com>
Date: Wed, 07 Sep 2016 12:49:11 +0000
Subject: [PATCH] OPENDJ-3221 Set better default TLS protocols which can also be overridden

---
 opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java    |   54 ++++++++++++++++++++++++---
 opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ConnectionWrapper.java |   11 ++++-
 2 files changed, 57 insertions(+), 8 deletions(-)

diff --git a/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java b/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java
index 0d05cf9..d5987df 100644
--- a/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java
+++ b/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java
@@ -21,10 +21,7 @@
 import static com.forgerock.opendj.cli.CliMessages.*;
 import static com.forgerock.opendj.cli.Utils.getHostNameForLdapUrl;
 import static com.forgerock.opendj.cli.Utils.throwIfArgumentsConflict;
-import static org.forgerock.opendj.ldap.LDAPConnectionFactory.AUTHN_BIND_REQUEST;
-import static org.forgerock.opendj.ldap.LDAPConnectionFactory.CONNECT_TIMEOUT;
-import static org.forgerock.opendj.ldap.LDAPConnectionFactory.SSL_CONTEXT;
-import static org.forgerock.opendj.ldap.LDAPConnectionFactory.SSL_USE_STARTTLS;
+import static org.forgerock.opendj.ldap.LDAPConnectionFactory.*;
 import static org.forgerock.util.time.Duration.*;
 
 import static com.forgerock.opendj.cli.CommonArguments.*;
@@ -38,6 +35,9 @@
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 import java.util.concurrent.TimeUnit;
 
 import javax.net.ssl.SSLContext;
@@ -345,6 +345,43 @@
     }
 
     /**
+     * Return a list of the available TLS protocols to use.
+     *
+     * <p>
+     * All protocols starting with "SSL" are removed. In particular the SSLv2Hello pseudo protocol is removed which will
+     * prevent connections to a server that doesn't have this configured.
+     * </p>
+     * <p>
+     * To override the defaults, set the <em>org.opends.ldaps.protocols</em> system property to a comma-separated list
+     * of desired protocols.
+     * </p>
+     *
+     * @return A list of valid protocol strings.
+     * @throws NoSuchAlgorithmException
+     *         If an SSL context could not be created.
+     */
+    public static List<String> getDefaultProtocols() throws NoSuchAlgorithmException {
+        List<String> enabled = Arrays.asList(SSLContext.getDefault().createSSLEngine().getEnabledProtocols());
+        final String property = System.getProperty("org.opends.ldaps.protocols");
+        final List<String> defaults = new ArrayList<>();
+        if (property != null && property.length() != 0) {
+            for (String protocol : property.split(",")) {
+                if (enabled.contains(protocol)) {
+                    defaults.add(protocol);
+                }
+            }
+            return defaults;
+        }
+        // exclude SSLv2Hello and SSLv3
+        for (String protocol : enabled) {
+            if (!protocol.startsWith("SSL")) {
+                defaults.add(protocol);
+            }
+        }
+        return defaults;
+    }
+
+    /**
      * Constructs a connection factory for pre-authenticated connections. Checks if any conflicting arguments are
      * present, build the connection with selected arguments and returns the connection factory. If the application is
      * interactive, it will prompt the user for missing parameters.
@@ -427,8 +464,13 @@
 
             Options options = Options.defaultOptions();
             if (sslContext != null) {
-                options.set(SSL_CONTEXT, sslContext)
-                    .set(SSL_USE_STARTTLS, useStartTLSArg.isPresent());
+                try {
+                    options.set(SSL_CONTEXT, sslContext)
+                            .set(SSL_USE_STARTTLS, useStartTLSArg.isPresent())
+                            .set(SSL_ENABLED_PROTOCOLS, getDefaultProtocols());
+                } catch (NoSuchAlgorithmException e) {
+                    throw new ArgumentException(ERR_LDAP_CONN_CANNOT_INITIALIZE_SSL.get(e.toString()), e);
+                }
             }
             options.set(CONNECT_TIMEOUT, duration(getConnectTimeout(), TimeUnit.MILLISECONDS));
             if (usePreAuthentication) {
diff --git a/opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ConnectionWrapper.java b/opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ConnectionWrapper.java
index ce9447c..12a1de1 100644
--- a/opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ConnectionWrapper.java
+++ b/opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ConnectionWrapper.java
@@ -25,12 +25,14 @@
 
 import java.io.Closeable;
 import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
 import java.util.concurrent.TimeUnit;
 
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.TrustManager;
 
+import com.forgerock.opendj.cli.ConnectionFactoryProvider;
 import org.forgerock.opendj.config.LDAPProfile;
 import org.forgerock.opendj.ldap.Connection;
 import org.forgerock.opendj.ldap.DN;
@@ -149,8 +151,13 @@
         .set(CONNECT_TIMEOUT, duration(connectTimeout, TimeUnit.MILLISECONDS));
     if (isLdaps || isStartTls)
     {
-      options.set(SSL_CONTEXT, getSSLContext(trustManager, keyManager))
-             .set(SSL_USE_STARTTLS, isStartTls);
+      try {
+        options.set(SSL_CONTEXT, getSSLContext(trustManager, keyManager))
+                .set(SSL_USE_STARTTLS, isStartTls)
+                .set(SSL_ENABLED_PROTOCOLS, ConnectionFactoryProvider.getDefaultProtocols());
+      } catch (NoSuchAlgorithmException e) {
+          throw newLdapException(CLIENT_SIDE_PARAM_ERROR, "Unable to perform SSL initialization:" + e.getMessage());
+      }
     }
     SimpleBindRequest request = bindDn != null && bindPwd != null
         ? newSimpleBindRequest(bindDn.toString(), bindPwd.toCharArray())

--
Gitblit v1.10.0