Author: remm
Date: Wed Jul 15 09:33:16 2015
New Revision: 1691150

URL: http://svn.apache.org/r1691150
Log:
Add plumbing for ALPN with JSSE (trying to test with HTTP/2 and OpenSSL, but it 
crashes during handshake at the moment if protocols have been configured).
Todo: After handshake, the protocol will be read using a new interface that the 
SSLEngine will have.

Modified:
    tomcat/trunk/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtil.java
    tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
    tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java
    tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java

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=1691150&r1=1691149&r2=1691150&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java Wed 
Jul 15 09:33:16 2015
@@ -81,7 +81,7 @@ public abstract class AbstractJsseEndpoi
                 for (SSLHostConfigCertificate certificate : 
sslHostConfig.getCertificates(true)) {
                     SSLUtil sslUtil = 
sslImplementation.getSSLUtil(sslHostConfig, certificate);
 
-                    SSLContext sslContext = sslUtil.createSSLContext();
+                    SSLContext sslContext = 
sslUtil.createSSLContext(negotiableProtocols);
                     sslContext.init(sslUtil.getKeyManagers(), 
sslUtil.getTrustManagers(), null);
 
                     SSLSessionContext sessionContext = 
sslContext.getServerSessionContext();

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=1691150&r1=1691149&r2=1691150&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtil.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtil.java Wed Jul 15 
09:33:16 2015
@@ -16,13 +16,15 @@
  */
 package org.apache.tomcat.util.net;
 
+import java.util.List;
+
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLSessionContext;
 import javax.net.ssl.TrustManager;
 
 public interface SSLUtil {
 
-    public SSLContext createSSLContext() throws Exception;
+    public SSLContext createSSLContext(List<String> negotiableProtocols) 
throws Exception;
 
     public KeyManager[] getKeyManagers() throws Exception;
 

Modified: 
tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java?rev=1691150&r1=1691149&r2=1691150&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java 
Wed Jul 15 09:33:16 2015
@@ -89,7 +89,7 @@ public class JSSESocketFactory implement
 
         SSLContext context;
         try {
-            context = createSSLContext();
+            context = createSSLContext(null);
             context.init(null,  null,  null);
         } catch (NoSuchAlgorithmException | KeyManagementException e) {
             // This is fatal for the connector so throw an exception to prevent
@@ -251,7 +251,7 @@ public class JSSESocketFactory implement
 
 
     @Override
-    public SSLContext createSSLContext() throws NoSuchAlgorithmException {
+    public SSLContext createSSLContext(List<String> negotiableProtocols) 
throws NoSuchAlgorithmException {
         return new JSSESSLContext(sslHostConfig.getSslProtocol());
     }
 

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=1691150&r1=1691149&r2=1691150&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 
Wed Jul 15 09:33:16 2015
@@ -17,6 +17,7 @@
 package org.apache.tomcat.util.net.openssl;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
@@ -69,10 +70,16 @@ public class OpenSSLContext implements o
 
     private static final String defaultProtocol = "TLS";
 
+    // http/1.1 with preceding length
+    private static final byte[] ALPN_DEFAULT =
+            new byte[] { 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 
};
+
     private final SSLHostConfig sslHostConfig;
     private final SSLHostConfigCertificate certificate;
     private OpenSSLServerSessionContext sessionContext;
 
+    private final List<String> negotiableProtocols;
+
     private List<String> ciphers = new ArrayList<>();
 
     public List<String> getCiphers() {
@@ -107,7 +114,7 @@ public class OpenSSLContext implements o
         }
     }
 
-    public OpenSSLContext(SSLHostConfig sslHostConfig, 
SSLHostConfigCertificate certificate)
+    public OpenSSLContext(SSLHostConfig sslHostConfig, 
SSLHostConfigCertificate certificate, List<String> negotiableProtocols)
             throws SSLException {
         this.sslHostConfig = sslHostConfig;
         this.certificate = certificate;
@@ -159,6 +166,9 @@ public class OpenSSLContext implements o
                 throw new Exception(
                         netSm.getString("endpoint.apr.failSslContextMake"), e);
             }
+
+            this.negotiableProtocols = negotiableProtocols;
+
             success = true;
         } catch(Exception e) {
             throw new SSLException(sm.getString("openssl.errorSSLCtxInit"), e);
@@ -169,6 +179,38 @@ public class OpenSSLContext implements o
         }
     }
 
+    private byte[] buildAlpnConfig(List<String> protocols) {
+        /*
+         * The expected format is zero or more of the following:
+         * - Single byte for size
+         * - Sequence of size bytes for the identifier
+         */
+        byte[][] protocolsBytes = new byte[protocols.size()][];
+        int i = 0;
+        int size = 0;
+        for (String protocol : protocols) {
+            protocolsBytes[i] = protocol.getBytes(StandardCharsets.UTF_8);
+            size += protocolsBytes[i].length;
+            // And one byte to store the size
+            size++;
+            i++;
+        }
+
+        size += ALPN_DEFAULT.length;
+
+        byte[] result = new byte[size];
+        int pos = 0;
+        for (byte[] protocolBytes : protocolsBytes) {
+            result[pos++] = (byte) (0xff & protocolBytes.length);
+            System.arraycopy(protocolBytes, 0, result, pos, 
protocolBytes.length);
+            pos += protocolBytes.length;
+        }
+
+        System.arraycopy(ALPN_DEFAULT, 0, result, pos, ALPN_DEFAULT.length);
+
+        return result;
+    }
+
     private void destroyPools() {
         // Guard against multiple destroyPools() calls triggered by 
construction exception and finalize() later
         if (aprPool != 0 && DESTROY_UPDATER.compareAndSet(this, 0, 1)) {
@@ -358,6 +400,15 @@ public class OpenSSLContext implements o
             SSLContext.setNpnProtos(ctx, protos, 
SSL.SSL_SELECTOR_FAILURE_CHOOSE_MY_LAST_PROTOCOL);
 
             sessionContext = new OpenSSLServerSessionContext(ctx);
+
+            if (negotiableProtocols != null && negotiableProtocols.size() > 0) 
{
+                byte[] protocols = buildAlpnConfig(negotiableProtocols);
+                if (SSLContext.setALPN(ctx, protocols, protocols.length) != 0) 
{
+                    log.warn(netSm.getString("endpoint.alpn.fail", 
negotiableProtocols));
+                }
+            }
+
+            sslHostConfig.setOpenSslContext(Long.valueOf(ctx));
             initialized = true;
         } catch (Exception e) {
             log.warn(sm.getString("openssl.errorSSLCtxInit"), e);

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=1691150&r1=1691149&r2=1691150&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 Wed 
Jul 15 09:33:16 2015
@@ -41,8 +41,8 @@ public class OpenSSLUtil implements SSLU
     }
 
     @Override
-    public SSLContext createSSLContext() throws Exception {
-        return new OpenSSLContext(sslHostConfig, certificate);
+    public SSLContext createSSLContext(List<String> negotiableProtocols) 
throws Exception {
+        return new OpenSSLContext(sslHostConfig, certificate, 
negotiableProtocols);
     }
 
     @Override



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

Reply via email to