Author: markt Date: Wed Apr 29 16:59:08 2015 New Revision: 1676791 URL: http://svn.apache.org/r1676791 Log: Add the first pass at the Java side plumbing for SNI support with APR/native.
Modified: tomcat/trunk/java/org/apache/tomcat/jni/SSLContext.java tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Modified: tomcat/trunk/java/org/apache/tomcat/jni/SSLContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/jni/SSLContext.java?rev=1676791&r1=1676790&r2=1676791&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/jni/SSLContext.java (original) +++ tomcat/trunk/java/org/apache/tomcat/jni/SSLContext.java Wed Apr 29 16:59:08 2015 @@ -17,6 +17,9 @@ package org.apache.tomcat.jni; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + /** SSL Context * * @author Mladen Turk @@ -289,4 +292,25 @@ public final class SSLContext { public static native void setVerify(long ctx, int level, int depth); public static native int setALPN(long ctx, byte[] proto, int len); + + public static long sniCallback(long defaultCtx, String sniHostName) { + SNICallBack sniCallBack = sniCallBacks.get(Long.valueOf(defaultCtx)); + if (sniCallBack == null) { + return 0; + } + return sniCallBack.getSslContext(sniHostName); + } + + private static Map<Long,SNICallBack> sniCallBacks = new ConcurrentHashMap<>(); + public static void registerDefault(Long defaultSSLContext, + SNICallBack sniCallBack) { + sniCallBacks.put(defaultSSLContext, sniCallBack); + } + public static void unregisterDefault(Long ctx) { + sniCallBacks.remove(ctx); + } + + public static interface SNICallBack { + public long getSslContext(String sniHostName); + } } 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=1676791&r1=1676790&r2=1676791&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Wed Apr 29 16:59:08 2015 @@ -45,6 +45,7 @@ import org.apache.tomcat.jni.Poll; import org.apache.tomcat.jni.Pool; import org.apache.tomcat.jni.SSL; import org.apache.tomcat.jni.SSLContext; +import org.apache.tomcat.jni.SSLContext.SNICallBack; import org.apache.tomcat.jni.SSLSocket; import org.apache.tomcat.jni.Sockaddr; import org.apache.tomcat.jni.Socket; @@ -70,7 +71,7 @@ import org.apache.tomcat.util.net.SSLHos * @author Mladen Turk * @author Remy Maucherat */ -public class AprEndpoint extends AbstractEndpoint<Long> { +public class AprEndpoint extends AbstractEndpoint<Long> implements SNICallBack { // -------------------------------------------------------------- Constants @@ -472,12 +473,6 @@ public class AprEndpoint extends Abstrac if (isSSLEnabled()) { for (SSLHostConfig sslHostConfig : sslHostConfigs.values()) { - // TODO: No SNI support in APR/native so only process the - // default host. - if (!SSLHostConfig.DEFAULT_SSL_HOST_NAME.equals(sslHostConfig.getHostName())) { - continue; - } - if (sslHostConfig.getCertificateFile() == null) { // This is required throw new Exception(sm.getString("endpoint.apr.noSslCertFile")); @@ -514,8 +509,9 @@ public class AprEndpoint extends Abstrac } // Create SSL Context + long ctx = 0; try { - sslContext = SSLContext.make(rootPool, value, SSL.SSL_MODE_SERVER); + ctx = SSLContext.make(rootPool, value, SSL.SSL_MODE_SERVER); } catch (Exception e) { // If the sslEngine is disabled on the AprLifecycleListener // there will be an Exception here but there is no way to check @@ -529,7 +525,7 @@ public class AprEndpoint extends Abstrac try { legacyRenegSupported = SSL.hasOp(SSL.SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); if (legacyRenegSupported) - SSLContext.setOptions(sslContext, SSL.SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); + SSLContext.setOptions(ctx, SSL.SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); } catch (UnsatisfiedLinkError e) { // Ignore } @@ -546,7 +542,7 @@ public class AprEndpoint extends Abstrac try { orderCiphersSupported = SSL.hasOp(SSL.SSL_OP_CIPHER_SERVER_PREFERENCE); if (orderCiphersSupported) - SSLContext.setOptions(sslContext, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE); + SSLContext.setOptions(ctx, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE); } catch (UnsatisfiedLinkError e) { // Ignore } @@ -563,7 +559,7 @@ public class AprEndpoint extends Abstrac try { disableCompressionSupported = SSL.hasOp(SSL.SSL_OP_NO_COMPRESSION); if (disableCompressionSupported) - SSLContext.setOptions(sslContext, SSL.SSL_OP_NO_COMPRESSION); + SSLContext.setOptions(ctx, SSL.SSL_OP_NO_COMPRESSION); } catch (UnsatisfiedLinkError e) { // Ignore } @@ -580,7 +576,7 @@ public class AprEndpoint extends Abstrac try { disableSessionTicketsSupported = SSL.hasOp(SSL.SSL_OP_NO_TICKET); if (disableSessionTicketsSupported) - SSLContext.setOptions(sslContext, SSL.SSL_OP_NO_TICKET); + SSLContext.setOptions(ctx, SSL.SSL_OP_NO_TICKET); } catch (UnsatisfiedLinkError e) { // Ignore } @@ -593,16 +589,16 @@ public class AprEndpoint extends Abstrac } // List the ciphers that the client is permitted to negotiate - SSLContext.setCipherSuite(sslContext, SSLCipherSuite); + SSLContext.setCipherSuite(ctx, SSLCipherSuite); // Load Server key and certificate - SSLContext.setCertificate(sslContext, sslHostConfig.getCertificateFile(), + SSLContext.setCertificate(ctx, sslHostConfig.getCertificateFile(), sslHostConfig.getCertificateKeyFile(), SSLPassword, SSL.SSL_AIDX_RSA); // Set certificate chain file - SSLContext.setCertificateChainFile(sslContext, SSLCertificateChainFile, false); + SSLContext.setCertificateChainFile(ctx, SSLCertificateChainFile, false); // Support Client Certificates - SSLContext.setCACertificate(sslContext, SSLCACertificateFile, SSLCACertificatePath); + SSLContext.setCACertificate(ctx, SSLCACertificateFile, SSLCACertificatePath); // Set revocation - SSLContext.setCARevocation(sslContext, SSLCARevocationFile, SSLCARevocationPath); + SSLContext.setCARevocation(ctx, SSLCARevocationFile, SSLCARevocationPath); // Client certificate verification value = SSL.SSL_CVERIFY_NONE; if ("optional".equalsIgnoreCase(SSLVerifyClient)) { @@ -612,7 +608,7 @@ public class AprEndpoint extends Abstrac } else if ("optionalNoCA".equalsIgnoreCase(SSLVerifyClient)) { value = SSL.SSL_CVERIFY_OPTIONAL_NO_CA; } - SSLContext.setVerify(sslContext, value, SSLVerifyDepth); + SSLContext.setVerify(ctx, value, SSLVerifyDepth); // For now, sendfile is not supported with SSL if (getUseSendfile()) { setUseSendfileInternal(false); @@ -623,17 +619,35 @@ public class AprEndpoint extends Abstrac if (negotiableProtocols.size() > 0) { byte[] protocols = buildAlpnConfig(negotiableProtocols); - if (SSLContext.setALPN(sslContext, protocols, protocols.length) != 0) { + if (SSLContext.setALPN(ctx, protocols, protocols.length) != 0) { log.warn(sm.getString("endpoint.alpn.fail", negotiableProtocols)); } } + sslHostConfig.setSslContext(Long.valueOf(ctx)); } + SSLHostConfig defaultSSLHostConfig = sslHostConfigs.get(SSLHostConfig.DEFAULT_SSL_HOST_NAME); + Long defaultSSLContext = (Long) defaultSSLHostConfig.getSslContext(); + sslContext = defaultSSLContext.longValue(); + SSLContext.registerDefault(defaultSSLContext, this); + } else if (negotiableProtocols.size() > 0) { log.info(sm.getString("endpoint.noNegotiation", getName(), negotiableProtocols.toString())); } } + @Override + public long getSslContext(String sniHostName) { + SSLHostConfig sslHostConfig = getSSLHostConfig(sniHostName); + Long ctx = (Long) sslHostConfig.getSslContext(); + if (ctx != null) { + return ctx.longValue(); + } + // Default + return 0; + } + + private byte[] buildAlpnConfig(List<String> protocols) { /* * The expected format is zero or more of the following: @@ -792,7 +806,14 @@ public class AprEndpoint extends Abstrac serverSock = 0; } - sslContext = 0; + if (sslContext != 0) { + Long ctx = Long.valueOf(sslContext); + SSLContext.unregisterDefault(ctx); + for (SSLHostConfig sslHostConfig : sslHostConfigs.values()) { + sslHostConfig.setSslContext(null); + } + sslContext = 0; + } // Close all APR memory pools and resources if initialised if (rootPool != 0) { --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org