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