[Pki-devel] [PATCH] Bug 871171 - Provide Tomcat support for TLS v1.1 and TLS v1.2 (Tomcatjss)

Christina Fu cfu at redhat.com
Mon Sep 29 18:32:26 UTC 2014


This tomcatjss patch is for the following bug:
*Bug 871171* <https://bugzilla.redhat.com/show_bug.cgi?id=871171> 
-Provide Tomcat support for TLS v1.1 and TLS v1.2 (Tomcatjss)

It provides the minimum code to support setting the ssl version range 
from tomcatjss server.
The tlsv1.1 and 1.2 ciphers are made available as well.

This patch works in conjunction with the JSS patch that was sent out for 
review.

Three are three new variables introduced in the server.xml :
sslVersionRangeStream - for stream protocol type.  it takes a format of 
"min:max" where min/max values can be "ssl3, tls1_0, tls1_1, or tls1_2"
sslVersionRangeDatagram - for datagram protocol type. it takes a format 
of "min:max" where min/max values can be "tls1_1, or tls1_2"
sslRangeCiphers - a complete list of ciphers you wish to support 
(provided supported by NSS) in such ssl version range.

When the new *range* parameters are set, the old sslOptions parameter is 
ignored, as it is obsolete.  However, if the *range* parameters are not 
specified, the sslOptions will be supported as before.

thanks,
Christina


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/pki-devel/attachments/20140929/58624dff/attachment.htm>
-------------- next part --------------
Index: src/org/apache/tomcat/util/net/jss/JSSSocketFactory.java
===================================================================
--- src/org/apache/tomcat/util/net/jss/JSSSocketFactory.java	(revision 278)
+++ src/org/apache/tomcat/util/net/jss/JSSSocketFactory.java	(working copy)
@@ -138,6 +138,23 @@
         cipherMap.put("TLS_ECDH_anon_WITH_AES_128_CBC_SHA",      SSLSocket.TLS_ECDH_anon_WITH_AES_128_CBC_SHA);
         cipherMap.put("TLS_ECDH_anon_WITH_AES_256_CBC_SHA",      SSLSocket.TLS_ECDH_anon_WITH_AES_256_CBC_SHA);
 
+        //TLSv1_2
+        cipherMap.put("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",     SSLSocket.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256);
+        cipherMap.put("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",     SSLSocket.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256);
+        cipherMap.put("TLS_RSA_WITH_NULL_SHA256",                SSLSocket.TLS_RSA_WITH_NULL_SHA256);
+        cipherMap.put("TLS_RSA_WITH_AES_128_CBC_SHA256",         SSLSocket.TLS_RSA_WITH_AES_128_CBC_SHA256);
+        cipherMap.put("TLS_RSA_WITH_AES_256_CBC_SHA256",         SSLSocket.TLS_RSA_WITH_AES_256_CBC_SHA256);
+        cipherMap.put("TLS_RSA_WITH_SEED_CBC_SHA",               SSLSocket.TLS_RSA_WITH_SEED_CBC_SHA);
+        cipherMap.put("TLS_RSA_WITH_AES_128_GCM_SHA256",         SSLSocket.TLS_RSA_WITH_AES_128_GCM_SHA256);
+        cipherMap.put("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",     SSLSocket.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256);
+        cipherMap.put("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",     SSLSocket.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256);
+        cipherMap.put("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256);
+        cipherMap.put("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",   SSLSocket.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256);
+        cipherMap.put("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256);
+        cipherMap.put("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",  SSLSocket.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256);
+        cipherMap.put("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",   SSLSocket.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256);
+        cipherMap.put("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",    SSLSocket.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256);
+
     }
 
     private static HashMap eccCipherMap = new HashMap();
@@ -197,9 +214,13 @@
         }
     }
 
-    public void setSSLCiphers(String attr) throws SocketException
+    public void setSSLCiphers(String attr) throws SocketException, IOException
     {
       String ciphers = (String)endpoint.getAttribute(attr);
+      if (ciphers == null || ciphers.equals("")) {
+          debugWrite("JSSSocketFactory setSSLCiphers: "+ attr +" not found");
+          return;
+      }
       StringTokenizer st = new StringTokenizer(ciphers, ",");
       while (st.hasMoreTokens()) {
         String cipherstr = st.nextToken();
@@ -257,7 +278,14 @@
       }
     }
 
-    public void setSSLOptions() throws SocketException
+    /*
+     * note: the SSL_OptionSet-based API for controlling the enabled
+     * protocol versions are obsolete and replaced by the
+     * setSSLVersionRange calls.  If the "range" parameters are
+     * present in the attributes then the sslOptions parameter is
+     * ignored.
+     */
+    public void setSSLOptions() throws SocketException, IOException
     {
       String options = (String)endpoint.getAttribute("sslOptions");
       StringTokenizer st = new StringTokenizer(options, ",");
@@ -308,6 +336,59 @@
         }
     }
 
+ 
+    /*
+     * setSSLVersionRangeDefault sets the range of allowed ssl versions.
+     * This replaces the obsolete SSL_Option* API
+     *
+     * @param protoVariant indicates whether this setting is for 
+       type "stream" or "datagram"
+     * @param sslVersionRange_s takes on the form of "min:max" where
+     * min/max values can be "ssl3, tls1_0, tls1_1, or tls1_2"
+     * ssl2 is not supported for tomcatjss via this interface. The format is:
+     *  "sslVersionRangeStream=min:max" or "sslVersionRangeDatagram=min:max"
+     */
+    public void setSSLVersionRangeDefault(
+            org.mozilla.jss.ssl.SSLSocket.SSLProtocolVariant protoVariant,
+            String sslVersionRange_s)
+        throws SocketException, IllegalArgumentException, IOException {
+
+        // process sslVersionRange_s
+        String[] sslVersionRange = sslVersionRange_s.split(":"); 
+        if (sslVersionRange.length != 2) {
+            debugWrite("JSSSocketFactory setSSLversionRangeDefault- SSL Version Range format error: " + sslVersionRange_s +"\n");
+            throw new SocketException("tomcatjss: setSSLversionRangeDefault format error");
+        }
+        String min_s = sslVersionRange[0];
+        String max_s = sslVersionRange[1];
+        int min = getSSLVersionRangeEnum(min_s);
+        int max = getSSLVersionRangeEnum(max_s);
+        if ((min == -1) || (max== -1)) {
+            debugWrite("JSSSocketFactory setSSLversionRangeDefault- SSL Version Range format error: " + sslVersionRange_s +"\n");
+            throw new SocketException("tomcatjss: setSSLversionRangeDefault format error");
+        }
+
+        debugWrite("JSSSocketFactory setSSLversionRangeDefault- SSL Version Range set to min=" + min + " max = " + max +"\n");
+        org.mozilla.jss.ssl.SSLSocket.SSLVersionRange range =
+            new org.mozilla.jss.ssl.SSLSocket.SSLVersionRange(min, max);
+
+        SSLSocket.setSSLVersionRangeDefault(protoVariant, range);
+        debugWrite("JSSSocketFactory setSSLversionRangeDefault- variant set\n");
+    }
+
+    int getSSLVersionRangeEnum (String rangeString) {
+        if (rangeString.equals("ssl3"))
+            return org.mozilla.jss.ssl.SSLSocket.SSLVersionRange.ssl3;
+        else if (rangeString.equals("tls1_0"))
+            return org.mozilla.jss.ssl.SSLSocket.SSLVersionRange.tls1_0;
+        else if (rangeString.equals("tls1_1"))
+            return org.mozilla.jss.ssl.SSLSocket.SSLVersionRange.tls1_1;
+        else if (rangeString.equals("tls1_2"))
+            return org.mozilla.jss.ssl.SSLSocket.SSLVersionRange.tls1_2;
+
+        return -1;
+    }
+
     void init() throws IOException {
         try {
             String deb = (String)endpoint.getAttribute("debug");
@@ -543,14 +624,52 @@
             }
             if (mStrictCiphers == true) {
                 // what ciphers do we have to start with? turn them all off
-                 debugWrite("SSSocketFactory init - before setSSLOptions, strictCiphers is true\n");
+                 debugWrite("SSSocketFactory init - before setSSLCiphers, strictCiphers is true\n");
                  unsetSSLCiphers();
             } else {
-                 debugWrite("SSSocketFactory init - before setSSLOptions, strictCiphers is false\n");
+                 debugWrite("SSSocketFactory init - before setSSLCiphers, strictCiphers is false\n");
             }
 
-            setSSLOptions();
-            debugWrite("SSSocketFactory init - after setSSLOptions\n");
+            String sslVersionRangeStream = (String)endpoint.getAttribute("sslVersionRangeStream");
+            if ((sslVersionRangeStream != null) && !sslVersionRangeStream.equals("")) {
+                debugWrite("SSSocketFactory init - calling setSSLVersionRangeDefault() for type STREAM\n");
+                setSSLVersionRangeDefault(org.mozilla.jss.ssl.SSLSocket.SSLProtocolVariant.STREAM, sslVersionRangeStream);
+                debugWrite("SSSocketFactory init - after setSSLVersionRangeDefault() for type STREAM\n");
+            }
+
+            String sslVersionRangeDatagram = (String)endpoint.getAttribute("sslVersionRangeDatagram");
+            if ((sslVersionRangeDatagram != null) && !sslVersionRangeDatagram.equals("")) {
+                debugWrite("SSSocketFactory init - calling setSSLVersionRangeDefault() for type DATA_GRAM\n");
+                setSSLVersionRangeDefault(org.mozilla.jss.ssl.SSLSocket.SSLProtocolVariant.DATA_GRAM, sslVersionRangeDatagram);
+                debugWrite("SSSocketFactory init - after setSSLVersionRangeDefault() for type DATA_GRAM\n");
+            }
+
+            /*
+             * According to NSS:
+             * the SSL_OptionSet-based API for controlling the enabled
+             * protocol versions are obsolete and replaced by the
+             * setSSLVersionRange calls.
+             * Therefore, if the "range" parameters are
+             * present in the attributes then the sslOptions parameter is
+             * ignored.
+             * Using the new version range API in conjunction with the older
+             * SSL_OptionSet-based API for controlling the enabled protocol
+             * versions may cause unexpected results
+             */
+            if (((sslVersionRangeStream != null)
+                    && !sslVersionRangeStream.equals(""))
+                    || ((sslVersionRangeDatagram != null)
+                    && !sslVersionRangeDatagram.equals(""))) {
+                /* deliberately lose the ssl2 here */
+                debugWrite("SSSocketFactory init - calling setSSLCiphers() honoring only sslRangeCiphers\n");
+                setSSLCiphers("sslRangeCiphers");
+                debugWrite("SSSocketFactory init - after setSSLCiphers() honoring only sslRangeCiphers\n");
+            } else {
+                debugWrite("SSSocketFactory init - calling setSSLOptions()\n");
+                setSSLOptions();
+                debugWrite("SSSocketFactory init - after setSSLOptions()\n");
+            }
+
         } catch (Exception ex) {
             debugWrite("JSSSocketFactory init - exception thrown:"+
                    ex.toString()+"\n");
Index: tomcatjss.spec
===================================================================
--- tomcatjss.spec	(revision 278)
+++ tomcatjss.spec	(working copy)
@@ -1,6 +1,6 @@
 Name:     tomcatjss
 Version:  7.1.0
-Release:  4%{?dist}
+Release:  5%{?dist}
 Summary:  JSSE implementation using JSS for Tomcat
 URL:      http://pki.fedoraproject.org/
 License:  LGPLv2+
@@ -17,12 +17,12 @@
 BuildRequires:    ant
 BuildRequires:    java-devel
 BuildRequires:    jpackage-utils >= 0:1.7.5-15
-BuildRequires:    jss >= 4.2.6-24
+BuildRequires:    jss >= 4.2.6-34
 BuildRequires:    tomcat >= 7.0.40
 
 Requires:         java
 Requires:         jpackage-utils >= 0:1.7.5-15
-Requires:         jss >= 4.2.6-24
+Requires:         jss >= 4.2.6-34
 Requires:         tomcat >= 7.0.40
 
 # The 'tomcatjss' package conflicts with the 'tomcat-native' package
@@ -75,6 +75,9 @@
 %{_javadir}/*
 
 %changelog
+* Wed Sep 10 2014 Christina Fu <cfu at redhat.com> - 7.1.0-5
+- added support for TLS v1.1 and v1.2
+
 * Fri Aug  2 2013 Ville Skyttä <ville.skytta at iki.fi> - 7.1.0-4
 - Simplify installation of docs.
 


More information about the Pki-devel mailing list