Author: markt
Date: Tue Jan 12 13:48:06 2016
New Revision: 1724234

URL: http://svn.apache.org/viewvc?rev=1724234&view=rev
Log:
Refactor

1. More clearly differentiate between:
- implemented protocols/ciphers
- configured protocols/ciphers
- enabled protocols/ciphers
and use common terminology throughout.

2. Remove the ensbledCiphers hack for JSSE+OpenSSL and replace with full 
implementation so the manager app now correctly reports the enabled ciphers.

3. Simplify. SSLContextWrapper has been removed.

4. Standardise treatment of unknown protocol. JSSE silently swallowed it. 
OpenSSL refused to start. Both now log a warning and continue.

Modified:
    tomcat/trunk/java/org/apache/catalina/manager/ManagerServlet.java
    tomcat/trunk/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties
    tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java
    tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java
    tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtil.java
    tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java
    tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java
    tomcat/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties
    tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java
    tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java
    tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java

Modified: tomcat/trunk/java/org/apache/catalina/manager/ManagerServlet.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/manager/ManagerServlet.java?rev=1724234&r1=1724233&r2=1724234&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/manager/ManagerServlet.java (original)
+++ tomcat/trunk/java/org/apache/catalina/manager/ManagerServlet.java Tue Jan 
12 13:48:06 2016
@@ -62,7 +62,6 @@ import org.apache.tomcat.util.Diagnostic
 import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.modeler.Registry;
 import org.apache.tomcat.util.net.SSLHostConfig;
-import org.apache.tomcat.util.net.SSLHostConfigCertificate;
 import org.apache.tomcat.util.res.StringManager;
 
 
@@ -1707,16 +1706,13 @@ public class ManagerServlet extends Http
             if (Boolean.TRUE.equals(connector.getProperty("SSLEnabled"))) {
                 SSLHostConfig[] sslHostConfigs = 
connector.getProtocolHandler().findSslHostConfigs();
                 for (SSLHostConfig sslHostConfig : sslHostConfigs) {
-                    for (SSLHostConfigCertificate cert : 
sslHostConfig.getCertificates()) {
-                        String name = connector.toString() + "-" + 
sslHostConfig.getHostName() +
-                                "-" + cert.getType();
-                        Set<String> cipherList = new HashSet<>();
-                        String[] cipherNames = cert.getEnabledCiphers();
-                        for (String cipherName : cipherNames) {
-                            cipherList.add(cipherName);
-                        }
-                        result.put(name, cipherList);
+                    String name = connector.toString() + "-" + 
sslHostConfig.getHostName();
+                    Set<String> cipherList = new HashSet<>();
+                    String[] cipherNames = sslHostConfig.getEnabledCiphers();
+                    for (String cipherName : cipherNames) {
+                        cipherList.add(cipherName);
                     }
+                result.put(name, cipherList);
                 }
             } else {
                 Set<String> cipherList = new HashSet<>();

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java?rev=1724234&r1=1724233&r2=1724234&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java Tue 
Jan 12 13:48:06 2016
@@ -77,8 +77,14 @@ public abstract class AbstractJsseEndpoi
             sslImplementation = 
SSLImplementation.getInstance(getSslImplementationName());
 
             for (SSLHostConfig sslHostConfig : sslHostConfigs.values()) {
+                boolean firstCertificate = true;
                 for (SSLHostConfigCertificate certificate : 
sslHostConfig.getCertificates(true)) {
                     SSLUtil sslUtil = 
sslImplementation.getSSLUtil(certificate);
+                    if (firstCertificate) {
+                        firstCertificate = false;
+                        
sslHostConfig.setEnabledProtocols(sslUtil.getEnabledProtocols());
+                        
sslHostConfig.setEnabledCiphers(sslUtil.getEnabledCiphers());
+                    }
 
                     SSLContext sslContext = 
sslUtil.createSSLContext(negotiableProtocols);
                     sslContext.init(sslUtil.getKeyManagers(), 
sslUtil.getTrustManagers(), null);
@@ -87,8 +93,7 @@ public abstract class AbstractJsseEndpoi
                     if (sessionContext != null) {
                         sslUtil.configureSessionContext(sessionContext);
                     }
-                    SSLContextWrapper sslContextWrapper = new 
SSLContextWrapper(sslContext, sslUtil);
-                    certificate.setSslContextWrapper(sslContextWrapper);
+                    certificate.setSslContext(sslContext);
                 }
             }
 
@@ -100,8 +105,8 @@ public abstract class AbstractJsseEndpoi
         if (isSSLEnabled()) {
             for (SSLHostConfig sslHostConfig : sslHostConfigs.values()) {
                 for (SSLHostConfigCertificate certificate : 
sslHostConfig.getCertificates(true)) {
-                    if (certificate.getSslContextWrapper() != null) {
-                        SSLContext sslContext = 
certificate.getSslContextWrapper().getSSLContext();
+                    if (certificate.getSslContext() != null) {
+                        SSLContext sslContext = certificate.getSslContext();
                         if (sslContext != null) {
                             sslContext.destroy();
                         }
@@ -116,13 +121,13 @@ public abstract class AbstractJsseEndpoi
 
         SSLHostConfigCertificate certificate = 
selectCertificate(sslHostConfig, clientRequestedCiphers);
 
-        SSLContextWrapper sslContextWrapper = 
certificate.getSslContextWrapper();
-        if (sslContextWrapper == null) {
+        SSLContext sslContext = certificate.getSslContext();
+        if (sslContext == null) {
             throw new IllegalStateException(
                     sm.getString("endpoint.jsse.noSslContext", sniHostName));
         }
 
-        SSLEngine engine = sslContextWrapper.getSSLContext().createSSLEngine();
+        SSLEngine engine = sslContext.createSSLEngine();
         switch (sslHostConfig.getCertificateVerification()) {
         case NONE:
             engine.setNeedClientAuth(false);
@@ -137,8 +142,8 @@ public abstract class AbstractJsseEndpoi
             break;
         }
         engine.setUseClientMode(false);
-        engine.setEnabledCipherSuites(sslContextWrapper.getEnabledCiphers());
-        engine.setEnabledProtocols(sslContextWrapper.getEnabledProtocols());
+        engine.setEnabledCipherSuites(sslHostConfig.getEnabledCiphers());
+        engine.setEnabledProtocols(sslHostConfig.getEnabledProtocols());
 
         SSLParameters sslParameters = engine.getSSLParameters();
         
sslParameters.setUseCipherSuitesOrder(sslHostConfig.getHonorCipherOrder());
@@ -188,27 +193,8 @@ public abstract class AbstractJsseEndpoi
     public void unbind() throws Exception {
         for (SSLHostConfig sslHostConfig : sslHostConfigs.values()) {
             for (SSLHostConfigCertificate certificate : 
sslHostConfig.getCertificates(true)) {
-                certificate.setSslContextWrapper(null);
+                certificate.setSslContext(null);
             }
         }
     }
-
-
-    static class SSLContextWrapper {
-
-        private final SSLContext sslContext;
-        private final String[] enabledCiphers;
-        private final String[] enabledProtocols;
-
-        public SSLContextWrapper(SSLContext sslContext, SSLUtil sslUtil) {
-            this.sslContext = sslContext;
-            // Determine which cipher suites and protocols to enable
-            enabledCiphers = sslUtil.getEnableableCiphers(sslContext);
-            enabledProtocols = sslUtil.getEnableableProtocols(sslContext);
-        }
-
-        public SSLContext getSSLContext() { return sslContext;}
-        public String[] getEnabledCiphers() { return enabledCiphers; }
-        public String[] getEnabledProtocols() { return enabledProtocols; }
-    }
 }

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java?rev=1724234&r1=1724233&r2=1724234&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Tue Jan 12 
13:48:06 2016
@@ -363,7 +363,7 @@ public class AprEndpoint extends Abstrac
                     // Native fallback used if protocols=""
                     value = SSL.SSL_PROTOCOL_ALL;
                 } else {
-                    for (String protocol : sslHostConfig.getProtocols()) {
+                    for (String protocol : 
sslHostConfig.getEnabledProtocols()) {
                         if 
(Constants.SSL_PROTO_SSLv2Hello.equalsIgnoreCase(protocol)) {
                             // NO-OP. OpenSSL always supports SSLv2Hello
                         } else if 
(Constants.SSL_PROTO_SSLv2.equalsIgnoreCase(protocol)) {
@@ -377,9 +377,8 @@ public class AprEndpoint extends Abstrac
                         } else if 
(Constants.SSL_PROTO_TLSv1_2.equalsIgnoreCase(protocol)) {
                             value |= SSL.SSL_PROTOCOL_TLSV1_2;
                         } else {
-                            // Protocol not recognized, fail to start as it is 
safer than
-                            // continuing with the default which might enable 
more than the
-                            // is required
+                            // Should not happen since filtering to build
+                            // enabled protocols removes invalid values.
                             throw new Exception(sm.getString(
                                     "endpoint.apr.invalidSslProtocol", 
protocol));
                         }

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties?rev=1724234&r1=1724233&r2=1724234&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/LocalStrings.properties Tue 
Jan 12 13:48:06 2016
@@ -123,3 +123,7 @@ sslHostConfig.mismatch=The property [{0}
 sslHostConfig.prefix_missing=The protocol [{0}] was added to the list of 
protocols on the SSLHostConfig named [{1}]. Check if a +/- prefix is missing.
 
 sslImplementation.cnfe= Unable to create SSLImplementation for class [{0}]
+
+slUtilBase.noneSupported=None of the [{0}] specified are supported by the SSL 
engine : [{1}]
+sslUtilBase.active=The [{0}] that are active are : [{1}]
+sslUtilBase.skipped=Some of the specified [{0}] are not supported by the SSL 
engine and have been skipped: [{1}]

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java?rev=1724234&r1=1724233&r2=1724234&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java Tue Jan 12 
13:48:06 2016
@@ -70,10 +70,12 @@ public class SSLHostConfig {
 
     // Configuration properties
 
+    // Internal
+    private String[] enabledCiphers;
+    private String[] enabledProtocols;
     // Nested
     private SSLHostConfigCertificate defaultCertificate = null;
     private Set<SSLHostConfigCertificate> certificates = new HashSet<>(4);
-
     // Common
     private String certificateRevocationListFile;
     private CertificateVerification certificateVerification = 
CertificateVerification.NONE;
@@ -160,6 +162,38 @@ public class SSLHostConfig {
     }
 
 
+    // ----------------------------------------------------- Internal 
properties
+
+    /**
+     * @see SSLUtil#getEnabledProtocols()
+     *
+     * @return The protocols enabled for this TLS virtual host
+     */
+    public String[] getEnabledProtocols() {
+        return enabledProtocols;
+    }
+
+
+    void setEnabledProtocols(String[] enabledProtocols) {
+        this.enabledProtocols = enabledProtocols;
+    }
+
+
+    /**
+     * @see SSLUtil#getEnabledCiphers()
+     *
+     * @return The ciphers enabled for this TLS virtual host
+     */
+    public String[] getEnabledCiphers() {
+        return enabledCiphers;
+    }
+
+
+    void setEnabledCiphers(String[] enabledCiphers) {
+        this.enabledCiphers = enabledCiphers;
+    }
+
+
     // ------------------------------------------- Nested configuration 
elements
 
     private void registerDefaultCertificate() {

Modified: 
tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java?rev=1724234&r1=1724233&r2=1724234&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java 
Tue Jan 12 13:48:06 2016
@@ -18,9 +18,7 @@ package org.apache.tomcat.util.net;
 
 import java.util.HashSet;
 import java.util.Set;
-import java.util.stream.Collectors;
 
-import org.apache.tomcat.util.net.AbstractJsseEndpoint.SSLContextWrapper;
 import org.apache.tomcat.util.net.openssl.ciphers.Authentication;
 
 
@@ -36,7 +34,7 @@ public class SSLHostConfigCertificate {
     // OpenSSL can handle multiple certs in a single config so the reference to
     // the context is at the virtual host level. JSSE can't so the reference is
     // held here on the certificate.
-    private SSLContextWrapper sslContextWrapper;
+    private SSLContext sslContext;
 
     // Common
     private final SSLHostConfig sslHostConfig;
@@ -66,23 +64,23 @@ public class SSLHostConfigCertificate {
     }
 
 
-    public SSLContextWrapper getSslContextWrapper() {
-        return sslContextWrapper;
+    public SSLContext getSslContext() {
+        return sslContext;
     }
 
 
-    public void setSslContextWrapper(SSLContextWrapper sslContextWrapper) {
-        this.sslContextWrapper = sslContextWrapper;
+    public void setSslContext(SSLContext sslContext) {
+        this.sslContext = sslContext;
     }
 
 
-    // Common
-
     public SSLHostConfig getSSLHostConfig() {
         return sslHostConfig;
     }
 
 
+    // Common
+
     public Type getType() {
         return type;
     }
@@ -198,17 +196,6 @@ public class SSLHostConfigCertificate {
     }
 
 
-    public String[] getEnabledCiphers() {
-        SSLContextWrapper wrapper = getSslContextWrapper();
-        if (wrapper != null) {
-            return wrapper.getEnabledCiphers();
-        }
-
-        return sslHostConfig.getCipherList().stream().map(c -> c.toString()).
-                collect(Collectors.toList()).toArray(new String[0]);
-    }
-
-
     // Nested types
 
     public static enum Type {

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtil.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtil.java?rev=1724234&r1=1724233&r2=1724234&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtil.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtil.java Tue Jan 12 
13:48:06 2016
@@ -38,32 +38,34 @@ public interface SSLUtil {
     public void configureSessionContext(SSLSessionContext sslSessionContext);
 
     /**
-     * Determines the SSL cipher suites that can be enabled, based on the
-     * configuration of the endpoint and the ciphers supported by the SSL
-     * implementation.
+     * The set of enabled protocols is the intersection of the implemented
+     * protocols and the configured protocols. If no protocols are explicitly
+     * configured, then all of the implemented protocols will be included in 
the
+     * returned array.
      *
-     * @param context An initialized context to obtain the supported ciphers 
from.
+     * @return The protocols currently enabled and available for clients to
+     *         select from for the associated connection
      *
-     * @return Array of SSL cipher suites that may be enabled (which may be
-     *         empty if none of the specified ciphers are supported), or
-     *         the defaults for the underlying SSL implementation if
-     *         the endpoint configuration does not specify any ciphers.
+     * @throws IllegalArgumentException  If there is no intersection between 
the
+     *         implemented and configured protocols
      */
-    public String[] getEnableableCiphers(SSLContext context);
+    public String[] getEnabledProtocols() throws IllegalArgumentException;
 
     /**
-     * Determines the SSL protocol variants that can be enabled, based on the
-     * configuration of the endpoint and the ciphers supported by the SSL
-     * implementation.
+     * The set of enabled ciphers is the intersection of the implemented 
ciphers
+     * and the configured ciphers. If no ciphers are explicitly configured, 
then
+     * the default ciphers will be included in the returned array.
+     * <p>
+     * The ciphers used during the TLS handshake may be further restricted by
+     * the {@link #getEnabledProtocols()} and the certificates.
      *
-     * @param context An initialized context to obtain the supported protocols 
from.
+     * @return The ciphers currently enabled and available for clients to 
select
+     *         from for the associated connection
      *
-     * @return Array of SSL protocol variants that may be enabled (which may be
-     *         empty if none of the specified protocols are supported), or
-     *         the defaults for the underlying SSL implementation if
-     *         the endpoint configuration does not specify any protocols.
+     * @throws IllegalArgumentException  If there is no intersection between 
the
+     *         implemented and configured ciphers
      */
-    public String[] getEnableableProtocols(SSLContext context);
+    public String[] getEnabledCiphers() throws IllegalArgumentException;
 
     /**
      * Optional interface that can be implemented by

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java?rev=1724234&r1=1724233&r2=1724234&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java Tue Jan 12 
13:48:06 2016
@@ -16,15 +16,102 @@
  */
 package org.apache.tomcat.util.net;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.juli.logging.Log;
+import org.apache.tomcat.util.res.StringManager;
+
 /**
  * Common base class for {@link SSLUtil} implementations.
  */
 public abstract class SSLUtilBase implements SSLUtil {
 
+    private static final StringManager sm = 
StringManager.getManager(SSLUtilBase.class);
+
     protected final SSLHostConfigCertificate certificate;
 
+    private final String[] enabledProtocols;
+    private final String[] enabledCiphers;
+
 
     protected SSLUtilBase(SSLHostConfigCertificate certificate) {
         this.certificate = certificate;
+        SSLHostConfig sslHostConfig = certificate.getSSLHostConfig();
+
+        // Calculate the enabled protocols
+        Set<String> configuredProtocols = sslHostConfig.getProtocols();
+        Set<String> implementedProtocols = getImplementedProtocols();
+        List<String> enabledProtocols =
+                getEnabled("protocols", true, configuredProtocols, 
implementedProtocols);
+        this.enabledProtocols = enabledProtocols.toArray(new 
String[enabledProtocols.size()]);
+
+        // Calculate the enabled ciphers
+        List<String> configuredCiphers = sslHostConfig.getJsseCipherNames();
+        Set<String> implementedCiphers = getImplementedCiphers();
+        List<String> enabledCiphers =
+                getEnabled("ciphers", false, configuredCiphers, 
implementedCiphers);
+        this.enabledCiphers = enabledCiphers.toArray(new 
String[enabledCiphers.size()]);
+    }
+
+
+    private <T> List<T> getEnabled(String name, boolean warnOnSkip, 
Collection<T> configured,
+            Collection<T> implemented) {
+
+        List<T> enabled = new ArrayList<>();
+
+        if (implemented.size() == 0) {
+            // Unable to determine the list of available protocols. This will
+            // have been logged previously.
+            // Use the configuredProtocols and hope they work. If not, an error
+            // will be generated when the list is used. Not ideal but no more
+            // can be done at this point.
+            enabled.addAll(configured);
+        } else {
+            enabled.addAll(implemented);
+            enabled.retainAll(configured);
+
+            if (enabled.isEmpty()) {
+                // Don't use the defaults in this case. They may be less secure
+                // than the configuration the user intended.
+                // Force the failure of the connector
+                throw new IllegalArgumentException(
+                        sm.getString("sslUtilBase.noneSupported", name, 
configured));
+            }
+            if (getLog().isDebugEnabled()) {
+                getLog().debug(sm.getString("sslUtilBase.active", name, 
enabled));
+            }
+            if (getLog().isDebugEnabled() || warnOnSkip) {
+                if (enabled.size() != configured.size()) {
+                    List<T> skipped = new ArrayList<>();
+                    skipped.addAll(configured);
+                    skipped.removeAll(enabled);
+                    String msg = sm.getString("sslUtilBase.skipped", name, 
skipped);
+                    if (warnOnSkip) {
+                        getLog().warn(msg);
+                    } else {
+                        getLog().debug(msg);
+                    }
+                }
+            }
+        }
+
+        return enabled;
     }
+
+    @Override
+    public String[] getEnabledProtocols() {
+        return enabledProtocols;
+    }
+
+    @Override
+    public String[] getEnabledCiphers() {
+        return enabledCiphers;
+    }
+
+    protected abstract Set<String> getImplementedProtocols();
+    protected abstract Set<String> getImplementedCiphers();
+    protected abstract Log getLog();
 }

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java?rev=1724234&r1=1724233&r2=1724234&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java Tue Jan 12 
13:48:06 2016
@@ -33,11 +33,12 @@ import java.security.cert.CertificateFac
 import java.security.cert.CollectionCertStoreParameters;
 import java.security.cert.PKIXBuilderParameters;
 import java.security.cert.X509CertSelector;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
+import java.util.Set;
 
 import javax.net.ssl.CertPathTrustManagerParameters;
 import javax.net.ssl.KeyManager;
@@ -54,6 +55,7 @@ import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.compat.JreVendor;
 import org.apache.tomcat.util.file.ConfigFileLoader;
+import org.apache.tomcat.util.net.Constants;
 import org.apache.tomcat.util.net.SSLContext;
 import org.apache.tomcat.util.net.SSLHostConfig;
 import org.apache.tomcat.util.net.SSLHostConfigCertificate;
@@ -74,18 +76,13 @@ public class JSSEUtil extends SSLUtilBas
     private static final Log log = LogFactory.getLog(JSSEUtil.class);
     private static final StringManager sm = 
StringManager.getManager(JSSEUtil.class);
 
-    private final SSLHostConfig sslHostConfig;
-
-    private final String[] defaultServerProtocols;
-
-
-    public JSSEUtil (SSLHostConfigCertificate certificate) {
-        super(certificate);
-        this.sslHostConfig = certificate.getSSLHostConfig();
+    private static final Set<String> implementedProtocols;
+    private static final Set<String> implementedCiphers;
 
+    static {
         SSLContext context;
         try {
-            context = createSSLContext(null);
+            context = new JSSESSLContext(Constants.SSL_PROTO_TLS);
             context.init(null,  null,  null);
         } catch (NoSuchAlgorithmException | KeyManagementException e) {
             // This is fatal for the connector so throw an exception to prevent
@@ -96,83 +93,55 @@ public class JSSEUtil extends SSLUtilBas
         // There is no standard way to determine the default protocols and
         // cipher suites so create a server socket to see what the defaults are
         SSLServerSocketFactory ssf = context.getServerSocketFactory();
-        SSLServerSocket socket;
-        try {
-            socket = (SSLServerSocket) ssf.createServerSocket();
-        } catch (IOException e) {
-            // This is very likely to be fatal but there is a slim chance that
-            // the JSSE implementation just doesn't like creating unbound
-            // sockets so allow the code to proceed.
-            defaultServerProtocols = new String[0];
-            log.warn(sm.getString("jsse.noDefaultProtocols", 
sslHostConfig.getHostName()));
-            return;
-        }
-
-        try {
+        implementedProtocols = new HashSet<>();
+        try (SSLServerSocket socket = (SSLServerSocket) 
ssf.createServerSocket()) {
             // Filter out all the SSL protocols (SSLv2 and SSLv3) from the
             // defaults
             // since they are no longer considered secure
-            List<String> filteredProtocols = new ArrayList<>();
             for (String protocol : socket.getEnabledProtocols()) {
                 if (protocol.toUpperCase(Locale.ENGLISH).contains("SSL")) {
                     log.debug(sm.getString("jsse.excludeDefaultProtocol", 
protocol));
                     continue;
                 }
-                filteredProtocols.add(protocol);
-            }
-            defaultServerProtocols =
-                    filteredProtocols.toArray(new 
String[filteredProtocols.size()]);
-            if (defaultServerProtocols.length == 0) {
-                log.warn(sm.getString("jsse.noDefaultProtocols", 
sslHostConfig.getHostName()));
+                implementedProtocols.add(protocol);
             }
-        } finally {
-            try {
-                socket.close();
-            } catch (IOException e) {
-                log.warn(sm.getString("jsse.exceptionOnClose"), e);
-            }
-        }
-    }
+        } catch (IOException e) {
+            // This is very likely to be fatal but there is a slim chance that
+            // the JSSE implementation just doesn't like creating unbound
+            // sockets so allow the code to proceed.
 
+        }
 
-    @Override
-    public String[] getEnableableCiphers(SSLContext context) {
-        List<String> requestedCiphers = sslHostConfig.getJsseCipherNames();
+        if (implementedProtocols.size() == 0) {
+            log.warn(sm.getString("jsse.noDefaultProtocols"));
+        }
 
-        List<String> ciphers = new ArrayList<>(requestedCiphers);
-        String[] supportedCipherSuiteArray = 
context.getSupportedSSLParameters().getCipherSuites();
+        String[] implementedCipherSuiteArray = 
context.getSupportedSSLParameters().getCipherSuites();
         // The IBM JRE will accept cipher suites names SSL_xxx or TLS_xxx but
         // only returns the SSL_xxx form for supported cipher suites. Therefore
         // need to filter the requested cipher suites using both forms with an
         // IBM JRE.
-        List<String> supportedCipherSuiteList;
         if (JreVendor.IS_IBM_JVM) {
-            supportedCipherSuiteList = new 
ArrayList<>(supportedCipherSuiteArray.length * 2);
-            for (String name : supportedCipherSuiteArray) {
-                supportedCipherSuiteList.add(name);
+            implementedCiphers = new 
HashSet<>(implementedCipherSuiteArray.length * 2);
+            for (String name : implementedCipherSuiteArray) {
+                implementedCiphers.add(name);
                 if (name.startsWith("SSL")) {
-                    supportedCipherSuiteList.add("TLS" + name.substring(3));
+                    implementedCiphers.add("TLS" + name.substring(3));
                 }
             }
         } else {
-            supportedCipherSuiteList = 
Arrays.asList(supportedCipherSuiteArray);
+            implementedCiphers = new 
HashSet<>(implementedCipherSuiteArray.length);
+            
implementedCiphers.addAll(Arrays.asList(implementedCipherSuiteArray));
         }
-        ciphers.retainAll(supportedCipherSuiteList);
+    }
+
+
+    private final SSLHostConfig sslHostConfig;
 
-        if (ciphers.isEmpty()) {
-            log.warn(sm.getString("jsse.requested_ciphers_not_supported",
-                    sslHostConfig.getCiphers()));
-        }
-        if (log.isDebugEnabled()) {
-            log.debug(sm.getString("jsse.enableable_ciphers", ciphers));
-            if (ciphers.size() != requestedCiphers.size()) {
-                List<String> skipped = new ArrayList<>(requestedCiphers);
-                skipped.removeAll(ciphers);
-                log.debug(sm.getString("jsse.unsupported_ciphers", skipped));
-            }
-        }
 
-        return ciphers.toArray(new String[ciphers.size()]);
+    public JSSEUtil (SSLHostConfigCertificate certificate) {
+        super(certificate);
+        this.sslHostConfig = certificate.getSSLHostConfig();
     }
 
 
@@ -263,6 +232,24 @@ public class JSSEUtil extends SSLUtilBas
 
 
     @Override
+    protected Log getLog() {
+        return log;
+    }
+
+
+    @Override
+    protected Set<String> getImplementedProtocols() {
+        return implementedProtocols;
+    }
+
+
+    @Override
+    protected Set<String> getImplementedCiphers() {
+        return implementedCiphers;
+    }
+
+
+    @Override
     public SSLContext createSSLContext(List<String> negotiableProtocols) 
throws NoSuchAlgorithmException {
         return new JSSESSLContext(sslHostConfig.getSslProtocol());
     }
@@ -409,32 +396,4 @@ public class JSSEUtil extends SSLUtilBas
         }
         return crls;
     }
-
-    @Override
-    public String[] getEnableableProtocols(SSLContext context) {
-        if (sslHostConfig.getProtocols().size() == 0) {
-            // JSSE fallback used if protocols=""
-            return defaultServerProtocols;
-        }
-
-        List<String> protocols = new ArrayList<>();
-        protocols.addAll(sslHostConfig.getProtocols());
-        protocols.retainAll(Arrays.asList(context.getSupportedSSLParameters()
-                .getProtocols()));
-
-        if (protocols.isEmpty()) {
-            log.warn(sm.getString("jsse.requested_protocols_not_supported",
-                    sslHostConfig.getProtocols()));
-        }
-        if (log.isDebugEnabled()) {
-            log.debug(sm.getString("jsse.enableable_protocols", protocols));
-            if (protocols.size() != sslHostConfig.getProtocols().size()) {
-                List<String> skipped = new ArrayList<>();
-                skipped.addAll(sslHostConfig.getProtocols());
-                skipped.removeAll(protocols);
-                log.debug(sm.getString("jsse.unsupported_protocols", skipped));
-            }
-        }
-        return protocols.toArray(new String[protocols.size()]);
-    }
 }

Modified: 
tomcat/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties?rev=1724234&r1=1724233&r2=1724234&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties 
Tue Jan 12 13:48:06 2016
@@ -21,12 +21,9 @@ jsse.invalidTrustManagerClassName=The tr
 jsse.requested_ciphers_not_supported=None of the ciphers specified are 
supported by the SSL engine : {0}
 jsse.enableable_ciphers=Specified SSL ciphers that are supported and 
enableable are : {0}
 jsse.unsupported_ciphers=Some specified SSL ciphers are not supported by the 
SSL engine : {0}
-jsse.requested_protocols_not_supported=None of the SSL protocols specified are 
supported by the SSL engine : {0}
-jsse.enableable_protocols=Specified SSL protocols that are supported and 
enableable are : {0}
-jsse.unsupported_protocols=Some specified SSL protocols are not supported by 
the SSL engine : {0}
 jsse.excludeDefaultProtocol=The SSL protocol [{0}] which is enabled by default 
in this JRE was excluded from the defaults used by Tomcat
 jsse.noDefaultCiphers=Unable to determine a default for ciphers for [{0}]. Set 
an explicit value to ensure the connector can start.
-jsse.noDefaultProtocols=Unable to determine a default for sslEnabledProtocols 
for [{0}]. Set an explicit value to ensure the connector can start.
+jsse.noDefaultProtocols=Unable to determine a default for sslEnabledProtocols. 
Set an explicit value to ensure the connector can start.
 jsse.exceptionOnClose=Failure to close socket.
 jsseSupport.clientCertError=Error trying to obtain a certificate from the 
client
 jseeSupport.certTranslationError=Error translating certificate [{0}]

Modified: 
tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java?rev=1724234&r1=1724233&r2=1724234&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java 
Tue Jan 12 13:48:06 2016
@@ -120,7 +120,7 @@ public class OpenSSLContext implements o
             if (sslHostConfig.getProtocols().size() == 0) {
                 value = SSL.SSL_PROTOCOL_ALL;
             } else {
-                for (String protocol : sslHostConfig.getProtocols()) {
+                for (String protocol : sslHostConfig.getEnabledProtocols()) {
                     if 
(Constants.SSL_PROTO_SSLv2Hello.equalsIgnoreCase(protocol)) {
                         // NO-OP. OpenSSL always supports SSLv2Hello
                     } else if 
(Constants.SSL_PROTO_SSLv2.equalsIgnoreCase(protocol)) {

Modified: 
tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java?rev=1724234&r1=1724233&r2=1724234&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java Tue 
Jan 12 13:48:06 2016
@@ -68,7 +68,7 @@ public final class OpenSSLEngine extends
     private static final SSLException ENGINE_CLOSED = new 
SSLException(sm.getString("engine.engineClosed"));
     private static final SSLException ENCRYPTED_PACKET_OVERSIZED = new 
SSLException(sm.getString("engine.oversizedPacket"));
 
-    private static final Set<String> AVAILABLE_CIPHER_SUITES;
+    protected static final Set<String> AVAILABLE_CIPHER_SUITES;
 
     static {
         final Set<String> availableCipherSuites = new LinkedHashSet<>(128);
@@ -114,7 +114,7 @@ public final class OpenSSLEngine extends
     // Protocols
     static final int VERIFY_DEPTH = 10;
 
-    private static final String[] SUPPORTED_PROTOCOLS = {
+    private static final String[] IMPLEMENTED_PROTOCOLS = {
         Constants.SSL_PROTO_SSLv2Hello,
         Constants.SSL_PROTO_SSLv2,
         Constants.SSL_PROTO_SSLv3,
@@ -122,8 +122,8 @@ public final class OpenSSLEngine extends
         Constants.SSL_PROTO_TLSv1_1,
         Constants.SSL_PROTO_TLSv1_2
     };
-    private static final Set<String> SUPPORTED_PROTOCOLS_SET =
-            new HashSet<>(Arrays.asList(SUPPORTED_PROTOCOLS));
+    protected static final Set<String> IMPLEMENTED_PROTOCOLS_SET =
+            new HashSet<>(Arrays.asList(IMPLEMENTED_PROTOCOLS));
 
     // Header (5) + Data (2^14) + Compression (1024) + Encryption (1024) + MAC 
(20) + Padding (256)
     static final int MAX_ENCRYPTED_PACKET_LENGTH = MAX_CIPHERTEXT_LENGTH + 5 + 
20 + 256;
@@ -746,7 +746,7 @@ public final class OpenSSLEngine extends
 
     @Override
     public String[] getSupportedProtocols() {
-        return SUPPORTED_PROTOCOLS.clone();
+        return IMPLEMENTED_PROTOCOLS.clone();
     }
 
     @Override
@@ -790,7 +790,7 @@ public final class OpenSSLEngine extends
         boolean tlsv1_1 = false;
         boolean tlsv1_2 = false;
         for (String p : protocols) {
-            if (!SUPPORTED_PROTOCOLS_SET.contains(p)) {
+            if (!IMPLEMENTED_PROTOCOLS_SET.contains(p)) {
                 throw new 
IllegalArgumentException(sm.getString("engine.unsupportedProtocol", p));
             }
             if (p.equals(Constants.SSL_PROTO_SSLv2)) {

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java?rev=1724234&r1=1724233&r2=1724234&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java Tue 
Jan 12 13:48:06 2016
@@ -17,11 +17,14 @@
 package org.apache.tomcat.util.net.openssl;
 
 import java.util.List;
+import java.util.Set;
 
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLSessionContext;
 import javax.net.ssl.TrustManager;
 
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.net.SSLContext;
 import org.apache.tomcat.util.net.SSLHostConfig;
 import org.apache.tomcat.util.net.SSLHostConfigCertificate;
@@ -30,10 +33,9 @@ import org.apache.tomcat.util.net.jsse.J
 
 public class OpenSSLUtil extends SSLUtilBase {
 
-    private final JSSEUtil jsseUtil;
+    private static final Log log = LogFactory.getLog(OpenSSLUtil.class);
 
-    private String[] enabledProtocols = null;
-    private String[] enabledCiphers = null;
+    private final JSSEUtil jsseUtil;
 
     public OpenSSLUtil(SSLHostConfigCertificate certificate) {
         super(certificate);
@@ -47,6 +49,25 @@ public class OpenSSLUtil extends SSLUtil
         }
     }
 
+
+    @Override
+    protected Log getLog() {
+        return log;
+    }
+
+
+    @Override
+    protected Set<String> getImplementedProtocols() {
+        return OpenSSLEngine.IMPLEMENTED_PROTOCOLS_SET;
+    }
+
+
+    @Override
+    protected Set<String> getImplementedCiphers() {
+        return OpenSSLEngine.AVAILABLE_CIPHER_SUITES;
+    }
+
+
     @Override
     public SSLContext createSSLContext(List<String> negotiableProtocols) 
throws Exception {
         return new OpenSSLContext(certificate, negotiableProtocols);
@@ -79,22 +100,4 @@ public class OpenSSLUtil extends SSLUtil
     public void configureSessionContext(SSLSessionContext sslSessionContext) {
         // do nothing. configuration is done in the init phase
     }
-
-    @Override
-    public String[] getEnableableCiphers(SSLContext context) {
-        if (enabledCiphers == null) {
-            List<String> enabledCiphersList = ((OpenSSLContext) 
context).getJsseCipherNames();
-            enabledCiphers = enabledCiphersList.toArray(new 
String[enabledCiphersList.size()]);
-        }
-        return enabledCiphers;
-    }
-
-    @Override
-    public String[] getEnableableProtocols(SSLContext context) {
-        if (enabledProtocols == null) {
-            enabledProtocols = new OpenSSLProtocols(((OpenSSLContext) 
context).getEnabledProtocol()).getProtocols();
-        }
-        return enabledProtocols;
-    }
-
 }




---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to