keycloak-uncached

Merge pull request #2166 from mstruk/ose-sni KEYCLOAK-2439

2/3/2016 12:07:21 PM

Details

diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpClientBuilder.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpClientBuilder.java
index 97600a7..d6914e1 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpClientBuilder.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpClientBuilder.java
@@ -243,15 +243,15 @@ public class HttpClientBuilder {
                 theContext.init(null, new TrustManager[]{new PassthroughTrustManager()},
                         new SecureRandom());
                 verifier = new AllowAllHostnameVerifier();
-                sslsf = new SSLSocketFactory(theContext, verifier);
+                sslsf = new SniSSLSocketFactory(theContext, verifier);
             } else if (theContext != null) {
-                sslsf = new SSLSocketFactory(theContext, verifier);
+                sslsf = new SniSSLSocketFactory(theContext, verifier);
             } else if (clientKeyStore != null || truststore != null) {
-                sslsf = new SSLSocketFactory(SSLSocketFactory.TLS, clientKeyStore, clientPrivateKeyPassword, truststore, null, verifier);
+                sslsf = new SniSSLSocketFactory(SSLSocketFactory.TLS, clientKeyStore, clientPrivateKeyPassword, truststore, null, verifier);
             } else {
                 final SSLContext tlsContext = SSLContext.getInstance(SSLSocketFactory.TLS);
                 tlsContext.init(null, null, null);
-                sslsf = new SSLSocketFactory(tlsContext, verifier);
+                sslsf = new SniSSLSocketFactory(tlsContext, verifier);
             }
             SchemeRegistry registry = new SchemeRegistry();
             registry.register(
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/SniSSLSocketFactory.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/SniSSLSocketFactory.java
new file mode 100644
index 0000000..fa44aad
--- /dev/null
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/SniSSLSocketFactory.java
@@ -0,0 +1,117 @@
+package org.keycloak.adapters;
+
+import org.apache.http.HttpHost;
+import org.apache.http.conn.scheme.HostNameResolver;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.conn.ssl.TrustStrategy;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
+import org.apache.http.protocol.HttpContext;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.security.AccessController;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivilegedExceptionAction;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+public class SniSSLSocketFactory extends SSLSocketFactory {
+
+    private static Logger log = Logger.getLogger(SniSSLSocketFactory.class.getName());
+
+    public SniSSLSocketFactory(String algorithm, KeyStore keystore, String keyPassword, KeyStore truststore, SecureRandom random, HostNameResolver nameResolver) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+        super(algorithm, keystore, keyPassword, truststore, random, nameResolver);
+    }
+
+    public SniSSLSocketFactory(String algorithm, KeyStore keystore, String keyPassword, KeyStore truststore, SecureRandom random, TrustStrategy trustStrategy, X509HostnameVerifier hostnameVerifier) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+        super(algorithm, keystore, keyPassword, truststore, random, trustStrategy, hostnameVerifier);
+    }
+
+    public SniSSLSocketFactory(String algorithm, KeyStore keystore, String keyPassword, KeyStore truststore, SecureRandom random, X509HostnameVerifier hostnameVerifier) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+        super(algorithm, keystore, keyPassword, truststore, random, hostnameVerifier);
+    }
+
+    public SniSSLSocketFactory(KeyStore keystore, String keystorePassword, KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+        super(keystore, keystorePassword, truststore);
+    }
+
+    public SniSSLSocketFactory(KeyStore keystore, String keystorePassword) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+        super(keystore, keystorePassword);
+    }
+
+    public SniSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+        super(truststore);
+    }
+
+    public SniSSLSocketFactory(TrustStrategy trustStrategy, X509HostnameVerifier hostnameVerifier) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+        super(trustStrategy, hostnameVerifier);
+    }
+
+    public SniSSLSocketFactory(TrustStrategy trustStrategy) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+        super(trustStrategy);
+    }
+
+    public SniSSLSocketFactory(SSLContext sslContext) {
+        super(sslContext);
+    }
+
+    public SniSSLSocketFactory(SSLContext sslContext, HostNameResolver nameResolver) {
+        super(sslContext, nameResolver);
+    }
+
+    public SniSSLSocketFactory(SSLContext sslContext, X509HostnameVerifier hostnameVerifier) {
+        super(sslContext, hostnameVerifier);
+    }
+
+    public SniSSLSocketFactory(SSLContext sslContext, String[] supportedProtocols, String[] supportedCipherSuites, X509HostnameVerifier hostnameVerifier) {
+        super(sslContext, supportedProtocols, supportedCipherSuites, hostnameVerifier);
+    }
+
+    public SniSSLSocketFactory(javax.net.ssl.SSLSocketFactory socketfactory, X509HostnameVerifier hostnameVerifier) {
+        super(socketfactory, hostnameVerifier);
+    }
+
+    public SniSSLSocketFactory(javax.net.ssl.SSLSocketFactory socketfactory, String[] supportedProtocols, String[] supportedCipherSuites, X509HostnameVerifier hostnameVerifier) {
+        super(socketfactory, supportedProtocols, supportedCipherSuites, hostnameVerifier);
+    }
+
+    @Override
+    public Socket connectSocket(int connectTimeout, Socket socket, HttpHost host, InetSocketAddress remoteAddress, InetSocketAddress localAddress, HttpContext context) throws IOException {
+        return super.connectSocket(connectTimeout, applySNI(socket, host.getHostName()), host, remoteAddress, localAddress, context);
+    }
+
+    @Override
+    public Socket createLayeredSocket(Socket socket, String target, int port, HttpContext context) throws IOException {
+        return super.createLayeredSocket(applySNI(socket, target), target, port, context);
+    }
+
+    private Socket applySNI(final Socket socket, String hostname) {
+        if (socket instanceof SSLSocket) {
+            try {
+                Method setHostMethod = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
+                    public Method run() throws NoSuchMethodException {
+                        return socket.getClass().getMethod("setHost", String.class);
+                    }
+                });
+
+                setHostMethod.invoke(socket, hostname);
+                log.finest("Applied SNI to socket for: " + hostname);
+            } catch (Exception e) {
+                log.log(Level.WARNING, "Failed to apply SNI to SSLSocket", e);
+            }
+        }
+        return socket;
+    }
+}