-
-
Save swankjesse/d094cb17d0562520cdbf64254542694a to your computer and use it in GitHub Desktop.
package okhttp3.recipes; | |
import java.io.IOException; | |
import java.net.InetAddress; | |
import java.net.Socket; | |
import java.security.KeyStore; | |
import java.util.Arrays; | |
import javax.net.ssl.SSLContext; | |
import javax.net.ssl.SSLSocket; | |
import javax.net.ssl.SSLSocketFactory; | |
import javax.net.ssl.TrustManager; | |
import javax.net.ssl.TrustManagerFactory; | |
import javax.net.ssl.X509TrustManager; | |
import okhttp3.Handshake; | |
import okhttp3.Headers; | |
import okhttp3.OkHttpClient; | |
import okhttp3.Request; | |
import okhttp3.Response; | |
import okhttp3.TlsVersion; | |
public class TlsOnIbm { | |
public static void main(String[] args) throws Exception { | |
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( | |
TrustManagerFactory.getDefaultAlgorithm()); | |
trustManagerFactory.init((KeyStore) null); | |
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); | |
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) { | |
throw new IllegalStateException("Unexpected default trust managers:" | |
+ Arrays.toString(trustManagers)); | |
} | |
X509TrustManager trustManager = (X509TrustManager) trustManagers[0]; | |
SSLContext sslContext = SSLContext.getInstance("TLS"); | |
sslContext.init(null, new TrustManager[] {trustManager}, null); | |
SSLSocketFactory sslSocketFactory | |
= new DelegatingSSLSocketFactory(sslContext.getSocketFactory()) { | |
@Override protected SSLSocket configureSocket(SSLSocket socket) throws IOException { | |
socket.setEnabledProtocols(new String[] { | |
TlsVersion.TLS_1_0.javaName(), | |
TlsVersion.TLS_1_1.javaName(), | |
TlsVersion.TLS_1_2.javaName() | |
}); | |
return socket; | |
} | |
}; | |
OkHttpClient client = new OkHttpClient.Builder() | |
.sslSocketFactory(sslSocketFactory, trustManager) | |
.retryOnConnectionFailure(false) | |
.build(); | |
Request requestOkhttp = new Request.Builder() | |
.url("https://ps.pndsn.com") | |
.build(); | |
Response response = client.newCall(requestOkhttp).execute(); | |
Handshake handshake = response.handshake(); | |
Headers headers = response.headers(); | |
System.out.println("Cipher suite: " + handshake.cipherSuite()); | |
System.out.println("TLS version: " + handshake.tlsVersion()); | |
System.out.println(); | |
System.out.println(response.code() + ": " + response.message()); | |
for (int i = 0, size = headers.size(); i < size; i++) { | |
System.out.println(headers.name(i) + ": " + headers.value(i)); | |
} | |
System.out.println(); | |
System.out.println(response.body().string()); | |
} | |
/** | |
* An SSL socket factory that forwards all calls to a delegate. Override {@link #configureSocket} | |
* to customize a created socket before it is returned. | |
*/ | |
static class DelegatingSSLSocketFactory extends SSLSocketFactory { | |
protected final SSLSocketFactory delegate; | |
public DelegatingSSLSocketFactory(SSLSocketFactory delegate) { | |
this.delegate = delegate; | |
} | |
@Override public String[] getDefaultCipherSuites() { | |
return delegate.getDefaultCipherSuites(); | |
} | |
@Override public String[] getSupportedCipherSuites() { | |
return delegate.getSupportedCipherSuites(); | |
} | |
@Override public Socket createSocket( | |
Socket socket, String host, int port, boolean autoClose) throws IOException { | |
return configureSocket((SSLSocket) delegate.createSocket(socket, host, port, autoClose)); | |
} | |
@Override public Socket createSocket(String host, int port) throws IOException { | |
return configureSocket((SSLSocket) delegate.createSocket(host, port)); | |
} | |
@Override public Socket createSocket( | |
String host, int port, InetAddress localHost, int localPort) throws IOException { | |
return configureSocket((SSLSocket) delegate.createSocket(host, port, localHost, localPort)); | |
} | |
@Override public Socket createSocket(InetAddress host, int port) throws IOException { | |
return configureSocket((SSLSocket) delegate.createSocket(host, port)); | |
} | |
@Override public Socket createSocket( | |
InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { | |
return configureSocket((SSLSocket) delegate.createSocket( | |
address, port, localAddress, localPort)); | |
} | |
protected SSLSocket configureSocket(SSLSocket socket) throws IOException { | |
return socket; | |
} | |
} | |
} |
I believe these ten lines https://gist.github.com/swankjesse/d094cb17d0562520cdbf64254542694a#file-tlsonibm-java-L33:L44 can be replaced with:
SSLContext sslContext = SSLContext.getInstance("TLS");
if ( "IBM J9 VM".equals(System.getProperty("java.vm.name") ) {
SSLContext sslContext = SSLContext.getInstance("SSL");
}
The problem with IBM Java is what, exactly, does "TLS"
mean in the call to SSLContext.getInstance
, see:
https://www.ibm.com/support/knowledgecenter/SSYKE2_8.0.0/com.ibm.java.security.component.80.doc/security-component/jsse2Docs/protocols.html
IBM chose, a long time ago, for "TLS"
in this context to mean only TLSv1.0. Over time, this diverged from Oracle's choices. For reference, here is Oracle's documentation for the meanings of names passed into SSLContext.getInstance
:
http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext
I'm doing the same as what @swankjesse is suggesting here, but I can't make it work.
https://gist.github.com/germanattanasio/3f0e7458328e817b4e63952ffaa93da2
It seems like it won't work with okhttp 3.6.0 it will only work with the code in master
I ran it like so: