diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/DelegatingSSLSocketFactory.java b/okhttp-tests/src/test/java/com/squareup/okhttp/DelegatingSSLSocketFactory.java index 38a5de8f8..f72bd1ace 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/DelegatingSSLSocketFactory.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/DelegatingSSLSocketFactory.java @@ -35,51 +35,43 @@ public class DelegatingSSLSocketFactory extends SSLSocketFactory { this.delegate = delegate; } - @Override - public SSLSocket createSocket() throws IOException { + @Override public SSLSocket createSocket() throws IOException { SSLSocket sslSocket = (SSLSocket) delegate.createSocket(); return configureSocket(sslSocket); } - @Override - public SSLSocket createSocket(String host, int port) throws IOException, UnknownHostException { + @Override public SSLSocket createSocket(String host, int port) throws IOException { SSLSocket sslSocket = (SSLSocket) delegate.createSocket(host, port); return configureSocket(sslSocket); } - @Override - public SSLSocket createSocket(String host, int port, InetAddress localAddress, int localPort) - throws IOException, UnknownHostException { + @Override public SSLSocket createSocket( + String host, int port, InetAddress localAddress, int localPort) throws IOException { SSLSocket sslSocket = (SSLSocket) delegate.createSocket(host, port, localAddress, localPort); return configureSocket(sslSocket); } - @Override - public SSLSocket createSocket(InetAddress host, int port) throws IOException { + @Override public SSLSocket createSocket(InetAddress host, int port) throws IOException { SSLSocket sslSocket = (SSLSocket) delegate.createSocket(host, port); return configureSocket(sslSocket); } - @Override - public SSLSocket createSocket(InetAddress host, int port, InetAddress localAddress, int localPort) - throws IOException { + @Override public SSLSocket createSocket( + InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException { SSLSocket sslSocket = (SSLSocket) delegate.createSocket(host, port, localAddress, localPort); return configureSocket(sslSocket); } - @Override - public String[] getDefaultCipherSuites() { + @Override public String[] getDefaultCipherSuites() { return delegate.getDefaultCipherSuites(); } - @Override - public String[] getSupportedCipherSuites() { + @Override public String[] getSupportedCipherSuites() { return delegate.getSupportedCipherSuites(); } - @Override - public SSLSocket createSocket(Socket socket, String host, int port, boolean autoClose) - throws IOException { + @Override public SSLSocket createSocket( + Socket socket, String host, int port, boolean autoClose) throws IOException { SSLSocket sslSocket = (SSLSocket) delegate.createSocket(socket, host, port, autoClose); return configureSocket(sslSocket); } diff --git a/okhttp/src/main/java/com/squareup/okhttp/OkHttpClient.java b/okhttp/src/main/java/com/squareup/okhttp/OkHttpClient.java index aabc2d2de..12a0c58bf 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/OkHttpClient.java +++ b/okhttp/src/main/java/com/squareup/okhttp/OkHttpClient.java @@ -17,6 +17,7 @@ package com.squareup.okhttp; import com.squareup.okhttp.internal.Internal; import com.squareup.okhttp.internal.InternalCache; +import com.squareup.okhttp.internal.Platform; import com.squareup.okhttp.internal.RouteDatabase; import com.squareup.okhttp.internal.Util; import com.squareup.okhttp.internal.http.AuthenticatorAdapter; @@ -38,6 +39,7 @@ import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.X509TrustManager; /** * Configures and creates HTTP connections. Most applications can use a single @@ -116,6 +118,7 @@ public class OkHttpClient implements Cloneable { /** Lazily-initialized. */ private static SSLSocketFactory defaultSslSocketFactory; + private static X509TrustManager defaultTrustManager; private final RouteDatabase routeDatabase; private Dispatcher dispatcher; @@ -133,6 +136,7 @@ public class OkHttpClient implements Cloneable { private SocketFactory socketFactory; private SSLSocketFactory sslSocketFactory; + private X509TrustManager trustManager; private HostnameVerifier hostnameVerifier; private CertificatePinner certificatePinner; private Authenticator authenticator; @@ -164,6 +168,7 @@ public class OkHttpClient implements Cloneable { this.internalCache = cache != null ? cache.internalCache : okHttpClient.internalCache; this.socketFactory = okHttpClient.socketFactory; this.sslSocketFactory = okHttpClient.sslSocketFactory; + this.trustManager = okHttpClient.trustManager; this.hostnameVerifier = okHttpClient.hostnameVerifier; this.certificatePinner = okHttpClient.certificatePinner; this.authenticator = okHttpClient.authenticator; @@ -343,6 +348,11 @@ public class OkHttpClient implements Cloneable { */ public OkHttpClient setSslSocketFactory(SSLSocketFactory sslSocketFactory) { this.sslSocketFactory = sslSocketFactory; + this.trustManager = Platform.get().trustManager(sslSocketFactory); + if (this.trustManager == null) { + throw new IllegalStateException("Unable to extract the trust manager on " + Platform.get() + + ", sslSocketFactory is " + sslSocketFactory.getClass()); + } return this; } @@ -589,6 +599,7 @@ public class OkHttpClient implements Cloneable { } if (result.sslSocketFactory == null) { result.sslSocketFactory = getDefaultSSLSocketFactory(); + result.trustManager = getDefaultTrustManager(); } if (result.hostnameVerifier == null) { result.hostnameVerifier = OkHostnameVerifier.INSTANCE; @@ -638,6 +649,17 @@ public class OkHttpClient implements Cloneable { return defaultSslSocketFactory; } + private synchronized X509TrustManager getDefaultTrustManager() { + if (defaultTrustManager == null) { + defaultTrustManager = Platform.get().trustManager(defaultSslSocketFactory); + if (defaultTrustManager == null) { + throw new IllegalStateException("Unable to extract the trust manager on " + Platform.get() + + ", sslSocketFactory is " + defaultSslSocketFactory.getClass()); + } + } + return defaultTrustManager; + } + /** Returns a shallow copy of this OkHttpClient. */ @Override public OkHttpClient clone() { return new OkHttpClient(this); diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/Platform.java b/okhttp/src/main/java/com/squareup/okhttp/internal/Platform.java index 4e578aef0..044ed0842 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/Platform.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/Platform.java @@ -19,6 +19,7 @@ package com.squareup.okhttp.internal; import android.util.Log; import com.squareup.okhttp.Protocol; import java.io.IOException; +import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -30,6 +31,8 @@ import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.X509TrustManager; import okio.Buffer; import static com.squareup.okhttp.internal.Internal.logger; @@ -51,6 +54,11 @@ import static com.squareup.okhttp.internal.Internal.logger; * unstable. * * Supported on OpenJDK 7 and 8 (via the JettyALPN-boot library). + * + *
Supported on Android 2.3+ and OpenJDK 7+. There are no public APIs to recover the trust
+ * manager that was used to create an {@link SSLSocketFactory}.
*/
public class Platform {
private static final Platform PLATFORM = findPlatform();
@@ -74,6 +82,10 @@ public class Platform {
public void untagSocket(Socket socket) throws SocketException {
}
+ public X509TrustManager trustManager(SSLSocketFactory sslSocketFactory) {
+ return null;
+ }
+
/**
* Configure TLS extensions on {@code sslSocket} for {@code route}.
*
@@ -109,11 +121,13 @@ public class Platform {
private static Platform findPlatform() {
// Attempt to find Android 2.3+ APIs.
try {
+ Class> sslParametersClass;
try {
- Class.forName("com.android.org.conscrypt.OpenSSLSocketImpl");
+ sslParametersClass = Class.forName("com.android.org.conscrypt.SSLParametersImpl");
} catch (ClassNotFoundException e) {
// Older platform before being unbundled.
- Class.forName("org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl");
+ sslParametersClass = Class.forName(
+ "org.apache.harmony.xnet.provider.jsse.SSLParametersImpl");
}
OptionalMethod