Author: markt
Date: Thu Oct 23 10:17:26 2014
New Revision: 1633788

URL: http://svn.apache.org/r1633788
Log:
Better handling for https://issues.apache.org/bugzilla/show_bug.cgi?id=56780
Now it is only necessary for the connector to be configured with 
sslProtocol="TLSv1.2" when using an IBM JRE in strict SP800-131a mode.

Modified:
    tomcat/tc7.0.x/trunk/   (props changed)
    
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
    
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/jsse/res/LocalStrings.properties

Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
  Merged /tomcat/trunk:r1633785

Modified: 
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java?rev=1633788&r1=1633787&r2=1633788&view=diff
==============================================================================
--- 
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
 (original)
+++ 
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
 Thu Oct 23 10:17:26 2014
@@ -87,11 +87,6 @@ public class JSSESocketFactory implement
     private static final StringManager sm =
         StringManager.getManager("org.apache.tomcat.util.net.jsse.res");
 
-    private static final boolean RFC_5746_SUPPORTED;
-
-    private static final String[] DEFAULT_SERVER_PROTOCOLS;
-    private static final String[] DEFAULT_SERVER_CIPHER_SUITES;
-
     // Defaults - made public where re-used
     private static final String defaultProtocol = "TLS";
     private static final String defaultKeystoreType = "JKS";
@@ -102,64 +97,12 @@ public class JSSESocketFactory implement
     private static final String ALLOW_ALL_SUPPORTED_CIPHERS = "ALL";
     public static final String DEFAULT_KEY_PASS = "changeit";
 
-    static {
-        boolean result = false;
-        SSLContext context;
-        String[] ciphers = null;
-        String[] protocols = null;
-        try {
-            // BZ 56780 IBM JRE can throw IllegalArgumentException here
-            context = SSLContext.getInstance("TLS");
-            context.init(null, null, null);
-            SSLServerSocketFactory ssf = context.getServerSocketFactory();
-            String supportedCiphers[] = ssf.getSupportedCipherSuites();
-            for (String cipher : supportedCiphers) {
-                if ("TLS_EMPTY_RENEGOTIATION_INFO_SCSV".equals(cipher)) {
-                    result = true;
-                    break;
-                }
-            }
-
-            // There is no API to obtain the default server protocols and 
cipher
-            // suites. Having inspected the OpenJDK code there the same results
-            // can be achieved via the standard API but there is no guarantee
-            // that every JVM implementation determines the defaults the same
-            // way. Therefore the defaults are determined by creating a server
-            // socket and requested the configured values.
-
-            SSLServerSocket socket = (SSLServerSocket) 
ssf.createServerSocket();
-            ciphers = socket.getEnabledCipherSuites();
-            // Filter out all the SSL protocols (SSLv2 and SSLv3) from the
-            // default protocols since they are no longer considered secure
-            List<String> filteredProtocols = new ArrayList<String>();
-            for (String protocol : socket.getEnabledProtocols()) {
-                if (protocol.contains("SSL")) {
-                    log.debug(sm.getString("jsse.excludeDefaultProtocol", 
protocol));
-                    continue;
-                }
-                filteredProtocols.add(protocol);
-            }
-            protocols = filteredProtocols.toArray(new 
String[filteredProtocols.size()]);
-        } catch (NoSuchAlgorithmException e ) {
-            // Assume no RFC 5746 support if an SSLContext could not be created
-            // Unable to determine default ciphers/protocols so use none
-        } catch (KeyManagementException e) {
-            // Assume no RFC 5746 support if an SSLContext could not be created
-            // Unable to determine default ciphers/protocols so use none
-        } catch (IOException e) {
-            // Unable to determine default ciphers/protocols so use none
-        } catch (IllegalArgumentException e) {
-            // Assume no RFC 5746 support if an SSLContext could not be created
-            // Unable to determine default ciphers/protocols so use none
-        }
-        RFC_5746_SUPPORTED = result;
-        DEFAULT_SERVER_CIPHER_SUITES = ciphers;
-        DEFAULT_SERVER_PROTOCOLS = protocols;
-    }
-
-
     private AbstractEndpoint<?> endpoint;
 
+    private final boolean rfc5746Supported;
+    private final String[] defaultServerProtocols;
+    private final String[] defaultServerCipherSuites;
+
     protected SSLServerSocketFactory sslProxy = null;
     protected String[] enabledCiphers;
     protected String[] enabledProtocols;
@@ -178,8 +121,77 @@ public class JSSESocketFactory implement
 
     public JSSESocketFactory (AbstractEndpoint<?> endpoint) {
         this.endpoint = endpoint;
+
+        String sslProtocol = endpoint.getSslProtocol();
+        if (sslProtocol == null) {
+            sslProtocol = defaultProtocol;
+        }
+
+        SSLContext context;
+        try {
+             context = SSLContext.getInstance(sslProtocol);
+             context.init(null,  null,  null);
+        } catch (NoSuchAlgorithmException e) {
+            // This is fatal for the connector so throw an exception to prevent
+            // it from starting
+            throw new IllegalArgumentException(e);
+        } catch (KeyManagementException e) {
+            // This is fatal for the connector so throw an exception to prevent
+            // it from starting
+            throw new IllegalArgumentException(e);
+        }
+
+        // Supported cipher suites aren't accessible directly from the
+        // SSLContext so use the SSL server socket factory
+        SSLServerSocketFactory ssf = context.getServerSocketFactory();
+        String supportedCiphers[] = ssf.getSupportedCipherSuites();
+        boolean found = false;
+        for (String cipher : supportedCiphers) {
+            if ("TLS_EMPTY_RENEGOTIATION_INFO_SCSV".equals(cipher)) {
+                found = true;
+                break;
+            }
+        }
+        rfc5746Supported = found;
+
+        // There is no standard way to determine the default protocols and
+        // cipher suites so create a server socket to see what the defaults are
+        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.
+            defaultServerCipherSuites = new String[0];
+            defaultServerProtocols = new String[0];
+            log.warn(sm.getString("jsse.noDefaultCiphers", 
endpoint.getName()));
+            log.warn(sm.getString("jsse.noDefaultProtocols", 
endpoint.getName()));
+            return;
+        }
+
+        defaultServerCipherSuites = socket.getEnabledCipherSuites();
+        if (defaultServerCipherSuites.length == 0) {
+            log.warn(sm.getString("jsse.noDefaultCiphers", 
endpoint.getName()));
+        }
+
+        // Filter out all the SSL protocols (SSLv2 and SSLv3) from the defaults
+        // since they are no longer considered secure
+        List<String> filteredProtocols = new ArrayList<String>();
+        for (String protocol : socket.getEnabledProtocols()) {
+            if (protocol.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", 
endpoint.getName()));
+        }
     }
 
+
     @Override
     public ServerSocket createSocket (int port)
         throws IOException
@@ -232,7 +244,7 @@ public class JSSESocketFactory implement
         if (session.getCipherSuite().equals("SSL_NULL_WITH_NULL_NULL"))
             throw new IOException("SSL handshake failed. Ciper suite in SSL 
Session is SSL_NULL_WITH_NULL_NULL");
 
-        if (!allowUnsafeLegacyRenegotiation && !RFC_5746_SUPPORTED) {
+        if (!allowUnsafeLegacyRenegotiation && !rfc5746Supported) {
             // Prevent further handshakes by removing all cipher suites
             ((SSLSocket) sock).setEnabledCipherSuites(new String[0]);
         }
@@ -247,7 +259,7 @@ public class JSSESocketFactory implement
         }
         if ((requestedCiphersStr == null)
                 || (requestedCiphersStr.trim().length() == 0)) {
-            return DEFAULT_SERVER_CIPHER_SUITES;
+            return defaultServerCipherSuites;
         }
 
         List<String> requestedCiphers = new ArrayList<String>();
@@ -258,7 +270,7 @@ public class JSSESocketFactory implement
             }
         }
         if (requestedCiphers.isEmpty()) {
-            return DEFAULT_SERVER_CIPHER_SUITES;
+            return defaultServerCipherSuites;
         }
         List<String> ciphers = new ArrayList<String>(requestedCiphers);
         ciphers.retainAll(Arrays.asList(context.getSupportedSSLParameters()
@@ -713,7 +725,7 @@ public class JSSESocketFactory implement
     public String[] getEnableableProtocols(SSLContext context) {
         String[] requestedProtocols = endpoint.getSslEnabledProtocolsArray();
         if ((requestedProtocols == null) || (requestedProtocols.length == 0)) {
-            return DEFAULT_SERVER_PROTOCOLS;
+            return defaultServerProtocols;
         }
 
         List<String> protocols = new ArrayList<String>(

Modified: 
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/jsse/res/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/jsse/res/LocalStrings.properties?rev=1633788&r1=1633787&r2=1633788&view=diff
==============================================================================
--- 
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/jsse/res/LocalStrings.properties
 (original)
+++ 
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/jsse/res/LocalStrings.properties
 Thu Oct 23 10:17:26 2014
@@ -25,6 +25,8 @@ jsse.requested_protocols_not_supported=N
 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.
 jsseSupport.clientCertError=Error trying to obtain a certificate from the 
client
 jseeSupport.certTranslationError=Error translating certificate [{0}]
 jsseSupport.noCertWant=No client certificate sent for want



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to