import javax.net.ssl.*; import java.security.Principal; import java.security.PrivateKey; import java.security.cert.X509Certificate; sclass SNIKeyManager implements X509KeyManager { Map> keyManagersByDomain; // key = domain name, value = (key manager, alias) bool verbose; *(Map> *keyManagersByDomain) {} @Override public String[] getClientAliases(String keyType, Principal[] issuers) { throw printStackTrace(new UnsupportedOperationException()); } @Override public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { throw printStackTrace(new UnsupportedOperationException()); } @Override public String[] getServerAliases(String keyType, Principal[] issuers) { return toStringArray(keys(keyManagersByDomain)); } @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(); if (verbose) print("chooseServerAlias session type: " + className(session)); List names = session.getRequestedServerNames(); if (verbose) print("Requested server names: " + names); S requestedName = str(first(names)); // rough, will look like this: "type=host_name (0), value=botcompany.de" requestedName = substring(requestedName, lastIndexOf(requestedName, "=")+1); for (S knownName : keys(keyManagersByDomain)) //if (ewic(requestedName, knownName)) { if (domainIsUnder(requestedName, knownName)) { if (verbose) print("Matched server name: " + knownName); ret knownName; } if (verbose) print("Reverting to default server name"); ret first(keys(keyManagersByDomain)); } @Override public X509Certificate[] getCertificateChain(String alias) { X509KeyManager man, S alias2 = unpair keyManagersByDomain.get(alias); if (verbose) print("getCertificateChain " + alias + " => " + alias2); return man.getCertificateChain(alias2); } @Override public PrivateKey getPrivateKey(String alias) { X509KeyManager man, S alias2 = unpair keyManagersByDomain.get(alias); if (verbose) print("getPrivateKey " + alias + " => " + alias2); return man.getPrivateKey(alias2); } }