Author: rjung Date: Sun Aug 13 14:35:05 2017 New Revision: 1804915 URL: http://svn.apache.org/viewvc?rev=1804915&view=rev Log: Wrap the KeyManagers used by the client to allow tracking for which CA subjects a client certificate was requested.
Modified: tomcat/trunk/test/org/apache/tomcat/util/net/TesterSupport.java Modified: tomcat/trunk/test/org/apache/tomcat/util/net/TesterSupport.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/net/TesterSupport.java?rev=1804915&r1=1804914&r2=1804915&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/tomcat/util/net/TesterSupport.java (original) +++ tomcat/trunk/test/org/apache/tomcat/util/net/TesterSupport.java Sun Aug 13 14:35:05 2017 @@ -20,7 +20,10 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.net.Socket; import java.security.KeyStore; +import java.security.Principal; +import java.security.PrivateKey; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Locale; @@ -28,9 +31,13 @@ import java.util.Locale; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509ExtendedKeyManager; +import javax.net.ssl.X509KeyManager; import javax.net.ssl.X509TrustManager; +import javax.security.auth.x500.X500Principal; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -63,6 +70,10 @@ public final class TesterSupport { public static final String ROLE = "testrole"; + private static String clientAuthExpectedIssuer = null; + private static String lastUsage = "NONE"; + private static Principal[] lastRequestedIssuers = new Principal[0]; + public static void initSsl(Tomcat tomcat) { initSsl(tomcat, LOCALHOST_JKS, null, null); } @@ -113,7 +124,17 @@ public final class TesterSupport { KeyManagerFactory kmf = KeyManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm()); kmf.init(getKeyStore(CLIENT_JKS), JKS_PASS.toCharArray()); - return kmf.getKeyManagers(); + KeyManager[] managers = kmf.getKeyManagers(); + KeyManager manager; + for (int i=0; i < managers.length; i++) { + manager = managers[i]; + if (manager instanceof X509ExtendedKeyManager) { + managers[i] = new TrackingExtendedKeyManager((X509ExtendedKeyManager)manager); + } else if (manager instanceof X509KeyManager) { + managers[i] = new TrackingKeyManager((X509KeyManager)manager); + } + } + return managers; } protected static TrustManager[] getTrustManagers() throws Exception { @@ -199,6 +220,15 @@ public final class TesterSupport { // Configure the Realm TesterMapRealm realm = new TesterMapRealm(); + // Get the CA subject the server should send us for client cert selection + try { + KeyStore ks = getKeyStore(CA_JKS); + X509Certificate cert = (X509Certificate)ks.getCertificate(CA_ALIAS); + clientAuthExpectedIssuer = cert.getSubjectDN().getName(); + } catch (Exception ex) { + // Ignore + } + String cn = "NOTFOUND"; try { KeyStore ks = getKeyStore(CLIENT_JKS); @@ -219,6 +249,35 @@ public final class TesterSupport { ctx.getPipeline().addValve(new SSLAuthenticator()); } + protected static String getClientAuthExpectedIssuer() { + return clientAuthExpectedIssuer; + } + + protected static void trackTrackingKeyManagers(KeyManager wrapper, KeyManager wrapped, + String usage, Principal[] issuers) { + lastUsage = usage; + lastRequestedIssuers = issuers; + } + + protected static String getLastClientAuthKeyManagerUsage() { + return lastUsage; + } + + protected static int getLastClientAuthRequestedIssuerCount() { + return lastRequestedIssuers == null ? 0 : lastRequestedIssuers.length; + } + + protected static Principal getLastClientAuthRequestedIssuer(int index) { + return lastRequestedIssuers[0]; + } + + protected static boolean checkLastClientAuthRequestedIssuers() { + if (lastRequestedIssuers == null || lastRequestedIssuers.length != 1) + return false; + return (new X500Principal(clientAuthExpectedIssuer)).equals( + new X500Principal(lastRequestedIssuers[0].getName())); + } + public static final byte DATA = (byte)33; public static class SimpleServlet extends HttpServlet { @@ -263,6 +322,104 @@ public final class TesterSupport { } } + public static class TrackingKeyManager implements X509KeyManager { + + private X509KeyManager manager = null; + + public TrackingKeyManager(X509KeyManager manager) { + this.manager = manager; + } + + @Override + public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { + trackTrackingKeyManagers(this, manager, "chooseClientAlias", issuers); + return manager.chooseClientAlias(keyType, issuers, socket); + } + + @Override + public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { + trackTrackingKeyManagers(this, manager, "chooseServerAlias", issuers); + return manager.chooseServerAlias(keyType, issuers, socket); + } + + @Override + public X509Certificate[] getCertificateChain(String alias) { + return manager.getCertificateChain(alias); + } + + @Override + public String[] getClientAliases(String keyType, Principal[] issuers) { + trackTrackingKeyManagers(this, manager, "getClientAliases", issuers); + return manager.getClientAliases(keyType, issuers); + } + + @Override + public PrivateKey getPrivateKey(String alias) { + return manager.getPrivateKey(alias); + } + + @Override + public String[] getServerAliases(String keyType, Principal[] issuers) { + trackTrackingKeyManagers(this, manager, "getServerAliases", issuers); + return manager.getServerAliases(keyType, issuers); + } + } + + public static class TrackingExtendedKeyManager extends X509ExtendedKeyManager { + + private X509ExtendedKeyManager manager = null; + + public TrackingExtendedKeyManager(X509ExtendedKeyManager manager) { + this.manager = manager; + } + + @Override + public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { + trackTrackingKeyManagers(this, manager, "chooseClientAlias", issuers); + return manager.chooseClientAlias(keyType, issuers, socket); + } + + @Override + public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { + trackTrackingKeyManagers(this, manager, "chooseServerAlias", issuers); + return manager.chooseServerAlias(keyType, issuers, socket); + } + + @Override + public X509Certificate[] getCertificateChain(String alias) { + return manager.getCertificateChain(alias); + } + + @Override + public String[] getClientAliases(String keyType, Principal[] issuers) { + trackTrackingKeyManagers(this, manager, "getClientAliases", issuers); + return manager.getClientAliases(keyType, issuers); + } + + @Override + public PrivateKey getPrivateKey(String alias) { + return manager.getPrivateKey(alias); + } + + @Override + public String[] getServerAliases(String keyType, Principal[] issuers) { + trackTrackingKeyManagers(this, manager, "getServerAliases", issuers); + return manager.getServerAliases(keyType, issuers); + } + + @Override + public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine) { + trackTrackingKeyManagers(this, manager, "chooseEngineClientAlias", issuers); + return manager.chooseEngineClientAlias(keyType, issuers, engine); + } + + @Override + public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) { + trackTrackingKeyManagers(this, manager, "chooseEngineServerAlias", issuers); + return manager.chooseEngineServerAlias(keyType, issuers, engine); + } + } + public static class TrustAllCerts implements X509TrustManager { @Override --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org