Author: markt Date: Fri Jun 19 21:20:02 2015 New Revision: 1686501 URL: http://svn.apache.org/r1686501 Log: First pass at an implementation that supports multiple certificate types for all connectors. Smoke test (SNI with 2 hosts with NIO) passes. Further testing required. Configuration via server.xml is still TODO
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java tomcat/trunk/java/org/apache/tomcat/util/net/jsse/openssl/Authentication.java tomcat/trunk/java/org/apache/tomcat/util/net/jsse/openssl/OpenSSLCipherConfigurationParser.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=1686501&r1=1686500&r2=1686501&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java Fri Jun 19 21:20:02 2015 @@ -16,6 +16,9 @@ */ package org.apache.tomcat.util.net; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -132,19 +135,36 @@ public abstract class AbstractJsseEndpoi private SSLHostConfigCertificate selectCertificate( - SSLHostConfig sslHostConfig, List<Cipher> clientRequestedCiphers) { + SSLHostConfig sslHostConfig, List<Cipher> clientCiphers) { Set<SSLHostConfigCertificate> certificates = sslHostConfig.getCertificates(true); if (certificates.size() == 1) { return certificates.iterator().next(); } - // TODO: - // Need to select correct certificate based on the ciphers requested by - // the client, the ciphers configured for the server and which is - // configured to define the preference order + LinkedHashSet<Cipher> serverCiphers = sslHostConfig.getCipherList(); - // For now, just return the first certificate + List<Cipher> candidateCiphers = new ArrayList<>(); + if (sslHostConfig.getHonorCipherOrder()) { + candidateCiphers.addAll(serverCiphers); + candidateCiphers.retainAll(clientCiphers); + } else { + candidateCiphers.addAll(clientCiphers); + candidateCiphers.retainAll(serverCiphers); + } + + Iterator<Cipher> candidateIter = candidateCiphers.iterator(); + while (candidateIter.hasNext()) { + Cipher candidate = candidateIter.next(); + for (SSLHostConfigCertificate certificate : certificates) { + if (certificate.getType().isCompatibleWith(candidate.getAu())) { + return certificate; + } + } + } + + // No matches. Just return the first certificate. The handshake will + // then fail due to no matching ciphers. return certificates.iterator().next(); } Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java?rev=1686501&r1=1686500&r2=1686501&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfig.java Fri Jun 19 21:20:02 2015 @@ -19,6 +19,8 @@ package org.apache.tomcat.util.net; import java.io.File; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -27,6 +29,7 @@ import javax.net.ssl.TrustManagerFactory import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.net.jsse.openssl.Cipher; import org.apache.tomcat.util.net.jsse.openssl.OpenSSLCipherConfigurationParser; import org.apache.tomcat.util.res.StringManager; @@ -75,6 +78,8 @@ public class SSLHostConfig { private CertificateVerification certificateVerification = CertificateVerification.NONE; private int certificateVerificationDepth = 10; private String ciphers = "HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!kRSA"; + private LinkedHashSet<Cipher> cipherList = null; + private List<String> jsseCipherNames = null; private boolean honorCipherOrder = true; private Set<String> protocols = new HashSet<>(); // JSSE @@ -250,6 +255,9 @@ public class SSLHostConfig { } else { this.ciphers = ciphersList; } + this.cipherList = null; + this.jsseCipherNames = null; + } @@ -258,6 +266,22 @@ public class SSLHostConfig { } + public LinkedHashSet<Cipher> getCipherList() { + if (cipherList == null) { + cipherList = OpenSSLCipherConfigurationParser.parse(ciphers); + } + return cipherList; + } + + + public List<String> getJsseCipherNames() { + if (jsseCipherNames == null) { + jsseCipherNames = OpenSSLCipherConfigurationParser.convertForJSSE(getCipherList()); + } + return jsseCipherNames; + } + + public void setHonorCipherOrder(boolean honorCipherOrder) { this.honorCipherOrder = honorCipherOrder; } Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java?rev=1686501&r1=1686500&r2=1686501&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java Fri Jun 19 21:20:02 2015 @@ -16,7 +16,11 @@ */ package org.apache.tomcat.util.net; +import java.util.HashSet; +import java.util.Set; + import org.apache.tomcat.util.net.AbstractJsseEndpoint.SSLContextWrapper; +import org.apache.tomcat.util.net.jsse.openssl.Authentication; public class SSLHostConfigCertificate { @@ -174,9 +178,25 @@ public class SSLHostConfigCertificate { // Nested types public static enum Type { + UNDEFINED, - RSA, - DSA, - ECC + RSA(Authentication.RSA), + DSA(Authentication.DSS), + ECC(Authentication.ECDH, Authentication.ECDSA); + + private final Set<Authentication> compatibleAuthentications; + + private Type(Authentication... authentications) { + compatibleAuthentications = new HashSet<>(); + if (authentications != null) { + for (Authentication authentication : authentications) { + compatibleAuthentications.add(authentication); + } + } + } + + public boolean isCompatibleWith(Authentication au) { + return compatibleAuthentications.contains(au); + } } } 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=1686501&r1=1686500&r2=1686501&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 Fri Jun 19 21:20:02 2015 @@ -58,7 +58,6 @@ import org.apache.tomcat.util.net.SSLCon import org.apache.tomcat.util.net.SSLHostConfig; import org.apache.tomcat.util.net.SSLHostConfigCertificate; import org.apache.tomcat.util.net.SSLUtil; -import org.apache.tomcat.util.net.jsse.openssl.OpenSSLCipherConfigurationParser; import org.apache.tomcat.util.res.StringManager; /** @@ -142,17 +141,14 @@ public class JSSESocketFactory implement @Override public String[] getEnableableCiphers(SSLContext context) { - String requestedCiphersStr = sslHostConfig.getCiphers(); - - List<String> requestedCiphers = - OpenSSLCipherConfigurationParser.parseExpression(requestedCiphersStr); + List<String> requestedCiphers = sslHostConfig.getJsseCipherNames(); List<String> ciphers = new ArrayList<>(requestedCiphers); ciphers.retainAll(Arrays.asList(context.getSupportedSSLParameters().getCipherSuites())); if (ciphers.isEmpty()) { log.warn(sm.getString("jsse.requested_ciphers_not_supported", - requestedCiphersStr)); + sslHostConfig.getCiphers())); } if (log.isDebugEnabled()) { log.debug(sm.getString("jsse.enableable_ciphers", ciphers)); Modified: tomcat/trunk/java/org/apache/tomcat/util/net/jsse/openssl/Authentication.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/jsse/openssl/Authentication.java?rev=1686501&r1=1686500&r2=1686501&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/jsse/openssl/Authentication.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/jsse/openssl/Authentication.java Fri Jun 19 21:20:02 2015 @@ -17,7 +17,7 @@ package org.apache.tomcat.util.net.jsse.openssl; -enum Authentication { +public enum Authentication { RSA /* RSA auth */, DSS /* DSS auth */, aNULL /* no auth (i.e. use ADH or AECDH) */, Modified: tomcat/trunk/java/org/apache/tomcat/util/net/jsse/openssl/OpenSSLCipherConfigurationParser.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/jsse/openssl/OpenSSLCipherConfigurationParser.java?rev=1686501&r1=1686500&r2=1686501&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/jsse/openssl/OpenSSLCipherConfigurationParser.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/jsse/openssl/OpenSSLCipherConfigurationParser.java Fri Jun 19 21:20:02 2015 @@ -629,7 +629,7 @@ public class OpenSSLCipherConfigurationP return result; } - static LinkedHashSet<Cipher> parse(String expression) { + public static LinkedHashSet<Cipher> parse(String expression) { if (!initialized) { init(); } @@ -676,7 +676,7 @@ public class OpenSSLCipherConfigurationP return defaultSort(ciphers); } - static List<String> convertForJSSE(Collection<Cipher> ciphers) { + public static List<String> convertForJSSE(Collection<Cipher> ciphers) { List<String> result = new ArrayList<>(ciphers.size()); for (Cipher cipher : ciphers) { result.addAll(cipher.getJsseNames()); --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org