public String getServerName() { String ret = serverName; if (sslEngine != null && sslEngine.getSession() != null) { SSLSession session = sslEngine.getSession(); if (session instanceof ExtendedSSLSession) { ExtendedSSLSession es = (ExtendedSSLSession) session; for (SNIServerName sni : es.getRequestedServerNames()) { SNIHostName hn = new SNIHostName(sni.getEncoded()); ret = hn.getAsciiName(); break; } } } LOG.log("HS DONE, servername is " + ret); return ret; }
/** * Method retrieves requested server name from ExtendedSSLSession and * uses it to return proper alias for server certificate * * @param session * @return */ private String chooseServerAlias(ExtendedSSLSession session) { // Pick first SNIHostName in the list of SNI names. String hostname = null; for (SNIServerName name : session.getRequestedServerNames()) { 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 def_cert_alias; } }
@Test public void test_SSLSocket_SNIHostName() throws Exception { TestUtils.assumeSNIHostnameAvailable(); TestSSLContext c = TestSSLContext.create(); final SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(); SSLParameters clientParams = client.getSSLParameters(); clientParams.setServerNames( Collections.singletonList((SNIServerName) new SNIHostName("www.example.com"))); client.setSSLParameters(clientParams); SSLParameters serverParams = c.serverSocket.getSSLParameters(); serverParams.setSNIMatchers( Collections.singletonList(SNIHostName.createSNIMatcher("www\\.example\\.com"))); c.serverSocket.setSSLParameters(serverParams); client.connect(new InetSocketAddress(c.host, c.port)); final SSLSocket server = (SSLSocket) c.serverSocket.accept(); @SuppressWarnings("unused") Future<?> future = runAsync(new Callable<Object>() { @Override public Object call() throws Exception { client.startHandshake(); return null; } }); server.startHandshake(); SSLSession serverSession = server.getSession(); assertTrue(serverSession instanceof ExtendedSSLSession); ExtendedSSLSession extendedServerSession = (ExtendedSSLSession) serverSession; List<SNIServerName> requestedNames = extendedServerSession.getRequestedServerNames(); assertNotNull(requestedNames); assertEquals(1, requestedNames.size()); SNIServerName serverName = requestedNames.get(0); assertEquals(StandardConstants.SNI_HOST_NAME, serverName.getType()); assertTrue(serverName instanceof SNIHostName); SNIHostName serverHostName = (SNIHostName) serverName; assertEquals("www.example.com", serverHostName.getAsciiName()); }
@Override public String chooseServerAlias(String string, Principal[] prncpls, Socket socket) { if (socket instanceof SSLSocket) { ExtendedSSLSession session = (ExtendedSSLSession) ((SSLSocket) socket).getSession(); return chooseServerAlias(session); } return null; }
@Override public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) { ExtendedSSLSession session = (ExtendedSSLSession) engine.getHandshakeSession(); return chooseServerAlias(session); }