import javax.net.ssl.*; import java.security.Principal; import java.security.PrivateKey; import java.security.cert.X509Certificate; // from https://github.com/grahamedgecombe/netty-sni-example/blob/master/src/main/java/SniKeyManager.java sclass SNIKeyManager extends X509ExtendedKeyManager { X509ExtendedKeyManager keyManager; S defaultAlias = "test1.example.com"; bool verbose; *(X509ExtendedKeyManager *keyManager) {} @Override public String[] getClientAliases(String keyType, Principal[] issuers) { throw printStackTrace(new UnsupportedOperationException()); // we don't use client mode } @Override public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { throw printStackTrace(new UnsupportedOperationException()); // as above } @Override public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine) { throw printStackTrace(new UnsupportedOperationException()); // as above } @Override public String[] getServerAliases(String keyType, Principal[] issuers) { return keyManager.getServerAliases(keyType, issuers); } @Override public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { // This is the one used by serveHttps right now ExtendedSSLSession session = cast ((SSLSocket) socket).getHandshakeSession(); print("chooseServerAlias session type: " + className(session)); List names = session.getRequestedServerNames(); if (verbose) print("Requested server names: " + names); ret keyManager.chooseServerAlias(keyType, issuers, socket); } @Override public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) { ExtendedSSLSession session = (ExtendedSSLSession) engine.getHandshakeSession(); // Pick first SNIHostName in the list of SNI names. String hostname = null; List names = session.getRequestedServerNames(); if (verbose) print("Requested server names: " + names); for (SNIServerName name : names) { if (name.getType() == StandardConstants.SNI_HOST_NAME) { hostname = ((SNIHostName) name).getAsciiName(); break; } } // If we got given a hostname over SNI, check if we have a cert and key for that hostname. If so, we use it. // Otherwise, we fall back to the default certificate. if (hostname != null && (getCertificateChain(hostname) != null && getPrivateKey(hostname) != null)) return hostname; else return defaultAlias; } @Override public X509Certificate[] getCertificateChain(String alias) { return keyManager.getCertificateChain(alias); } @Override public PrivateKey getPrivateKey(String alias) { return keyManager.getPrivateKey(alias); } }