Closed enricods closed 7 years ago
You'll need to configure your ConnectionSpec to enable obsolete cipher suites in OkHttp. https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/CustomCipherSuites.java
It seems that IBMJSSE2, the JSSE implementation used by Websphere, in not compatible with this solution. The problem is that for this implementation, the cipher suite names may starts with SSL or TLS (IBM documentation), both accepted: but that is not true for OkHttp.
Example: The cipher TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 is not legacy (like the SSL_RSA_WITH_3DES_EDE_CBC_SHA cipher) and its Java name is the same as its id in the CipherSuite class.
The socket implementation correctly registers the cipher
socket.setEnabledCipherSuites(javaNames(spec.cipherSuites()));
but in the getEnabledCipherSuites list, the name is returned with the SSL_ prefix. For that reason the following lines of code, in the method CipherSuite.isCompatible(SSLSocket socket), return false
if (cipherSuites != null
&& !nonEmptyIntersection(cipherSuites, socket.getEnabledCipherSuites())) {
return false;
}
and the class ConnectionSpecSelector throws the "Unable to find acceptable protocols" exception.
This problem seems very similar to the one descripted in this page https://github.com/cloudant/java-cloudant/issues/215
Is it possible that this is the real cause of the presence of the single cipher SSL_RSA_WITH_3DES_EDE_CBC_SHA in the client hello phase of my test servlet?
Oh interesting. We can probably fix to handle TLS or SSL prefixes
@swankjesse Our implementation would benefit greatly from this proposal, does the team have an estimated ETA on bringing this patch into a release?
I experienced the same problem today running an okhttp based client within IBM Bluemix. A solution would be appreciated!
@swankjesse Hey, any update on an ETA?
No ETA. Any advice on reproducing this as a person who doesn’t use WebSphere? Ideally on a Mac?
This issue probably does not need all of WebSphere to be seen. It is likely that only IBM Java is needed. IBM publishes Docker images with IBM Java in it
docker run -it --rm ibmcom/ibmjava:8-sdk java -version
java version "1.8.0"
Java(TM) SE Runtime Environment (build pxa6480sr4fp1-20170215_01(SR4 FP1))
IBM J9 VM (build 2.8, JRE 1.8.0 Linux amd64-64 Compressed References 20170209_336038 (JIT enabled, AOT enabled)
J9VM - R28_20170209_0201_B336038
JIT - tr.r14.java.green_20170125_131456
GC - R28_20170209_0201_B336038_CMPRSS
J9CL - 20170209_336038)
JCL - 20170215_01 based on Oracle jdk8u121-b13
Similar issue for Apache's HTTP client: https://issues.apache.org/jira/browse/HTTPCLIENT-1784
Some relevant IBM documentation: http://www.ibm.com/support/knowledgecenter/SSYKE2_8.0.0/com.ibm.java.security.component.80.doc/security-component/jsse2Docs/matchsslcontext_tls.html
That helps a lot. Thanks @bruceadams !
Please note that the IBM doc @bruceadams linked to points out that OkHttpClient's usage of TLS
in the creation of the default SSLContext will also cause problems for IBM Java users when attempting to connect to a server that does not offer TLS 1.0. Wanted to make sure that was clear given the initial focus was on 3DES being the only suite chosen.
I'm not a real coder these days - but I believe you could explicitly supply TLSv1,TLSv1.1,TLSv1.2
to get support for all 3 protocols consistently across Oracle and IBM. I do not know about other JDKs though.
Good news: I was able to establish connectivity with OkHttp and this particular server using the IBM docker image. That was a really good help.
But I need to make a code change. I need to change OkHttp’s CipherSuite class to ignore the TLS_
or SSL
prefix when identifying a cipher suite. I didn’t realize that IBM and Oracle used different prefixes, and our code is too simple. This is ugly, but should be straightforward to overcome.
The other trick to connecting to this particular server is enabling TLS 1.2 on in the SSLSocket. This is awkward code. In my test I used DelegatingSSLSocketFactory configured like so:
// Force TLS 1.2 on. This isn’t the on by default for IBM Java8.
sslSocketFactory = new DelegatingSSLSocketFactory(sslSocketFactory) {
@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;
}
};
I’ll make the OkHttp change to ignore TLS_
vs. SSL_
prefixes.
For reference, here’s my updates to your test harness: https://gist.github.com/swankjesse/d094cb17d0562520cdbf64254542694a
@JakeWharton @swankjesse, Thanks for fixing this. Are you guys planning on doing a release?
The reason I'm asking is because based on your CHANGELOG, it could be weeks before you release a new version.
In the meantime, I'm going to add a workaround similar to the one @swankjesse described in his gist.
Thanks again for fixing this.
@JakeWharton @swankjesse Adding to the request to see if you can accelerate 3.7.0 if your not already on the verge of releasing it. With the sweet32 vulnerability more and more people are removing 3DES as a supported suite on their servers - including us (IBM). I realize we apparently made a bad choice at some point to be different and unfortunately stuck with it are now suffering for it. Because Oracle still used SSL_ for older suites there have been suites available when using IBM Java until now when the last of these - the 3DES suites - are going away.
We did look into creating our own SslSocketFactory as a temporary solution with 3.6.0 but you don't just accept the suites configured in that factory - you require overlap with your hard-coded list.
@JakeWharton @swankjesse please ignore the entreaty above (which I think you already were 😄 ). The ability to simply turn off the cleansing of the default cipher suites provided by the socket by via providing a ConnectionSpec
which has had .allEnabledCipherSuites()
invoked on it was totally missed when looking at this.
Glad you're not blocked. Sorry for the radio silence; just lots going on at the moment.
Hi @swankjesse - Am using version 3.9.1 of the jar, but am still running into the handshake_failure exception. javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure at com.ibm.jsse2.j.a(j.java:23)
Am trying to communicate to APNS, using okhttp library. We are using IBM WAS 8.5.5 and Java 1.7. Can you pls let me know how can we work around this problem? thanks for your help.
It seems that okhttp does not load a correct a SSL context configuration during the ClientHello phase during a SSL handshake, when deployed on Websphere 8.5 (tested on 8.5.5.0 and 8.5.5.10).
Here the code we use in our test servlet:
This code generates the following ClientHello logs:
The proposed protocol is TLSv1 and only one (old) cipher in present in the list: because of that sometimes the SSL handshake terminates with error when the called server does not support this single cipher.
But the Websphere server has full cipher suite support: in fact if we setup a connection using directly the javax.net API, the cipher list is complete.
The Java net connection code:
The corresponding ClientHello logs:
It seems that okhttp is not working correctly on Websphere 8.5.
These tests are based on okhttp version 3.6.0.
What kind of issue is this?
[ ] Question. This issue tracker is not the place for questions. If you want to ask how to do something, or to understand why something isn't working the way you expect it to, use Stack Overflow. https://stackoverflow.com/questions/tagged/okhttp
[x] Bug report. If you’ve found a bug, spend the time to write a failing test. Bugs with tests get fixed. Here’s an example: https://gist.github.com/swankjesse/981fcae102f513eb13ed
[ ] Feature Request. Start by telling us what problem you’re trying to solve. Often a solution already exists! Don’t send pull requests to implement new features without first getting our support. Sometimes we leave features out on purpose to keep the project small.