Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OkHttp changes the global SSL context, breaks other HTTP clients #184

Closed
skyisle opened this issue May 10, 2013 · 33 comments · Fixed by #518
Closed

OkHttp changes the global SSL context, breaks other HTTP clients #184

skyisle opened this issue May 10, 2013 · 33 comments · Fixed by #518
Labels
bug Bug in existing code
Milestone

Comments

@skyisle
Copy link

skyisle commented May 10, 2013

We're enabling SPDY for the shared SSL context, and other HTTP clients like HttpURLConnection don't anticipate this, causing them to freak out and crash the app.

@skyisle's original report...

Here is backtrace.

DEBUG I backtrace:
DEBUG I #00 pc 00022430 /system/lib/libssl.so (SSL_select_next_proto+25)
DEBUG I #1 pc 000222ef /system/lib/libjavacore.so
DEBUG I #2 pc 0002905f /system/lib/libssl.so (ssl_parse_serverhello_tlsext+458)
DEBUG I #3 pc 00015957 /system/lib/libssl.so (ssl3_get_server_hello+894)
DEBUG I #4 pc 00018193 /system/lib/libssl.so (ssl3_connect+618)
DEBUG I #5 pc 000235d7 /system/lib/libssl.so (SSL_connect+18)
DEBUG I #6 pc 0001126b /system/lib/libssl.so (ssl23_connect+1970)
DEBUG I #7 pc 0002350f /system/lib/libssl.so (SSL_do_handshake+66)
DEBUG I #8 pc 00024bc5 /system/lib/libjavacore.so
DEBUG I #9 pc 0001e490 /system/lib/libdvm.so (dvmPlatformInvoke+112)
DEBUG I #10 pc 0004d2b1 /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const_, JValue_, Method const_, Thread_)+396)
DEBUG I #11 pc 000278a0 /system/lib/libdvm.so
DEBUG I #12 pc 0002b77c /system/lib/libdvm.so (dvmInterpret(Thread_, Method const_, JValue_)+176)
DEBUG I #13 pc 0005fae5 /system/lib/libdvm.so (dvmCallMethodV(Thread_, Method const_, Object_, bool, JValue_, std::va_list)+272)
DEBUG I #14 pc 0005fb0f /system/lib/libdvm.so (dvmCallMethod(Thread
, Method const
, Object_, JValue*, ...)+20)
DEBUG I #15 pc 0005466f /system/lib/libdvm.so
DEBUG I #16 pc 0000e418 /system/lib/libc.so (__thread_entry+72)
DEBUG I #17 pc 0000db0c /system/lib/libc.so (pthread_create+168)
DEBUG I #18 pc 00052f34

@skyisle
Copy link
Author

skyisle commented May 10, 2013

and reproduction code : https://gist.github.com/skyisle/5553239

@swankjesse
Copy link
Member

Which device is this? Please tell me its a Droid RAZR...

@skyisle
Copy link
Author

skyisle commented May 10, 2013

Sorry. It's stock galaxy nexus 4.2.2.

@swankjesse
Copy link
Member

Alright, good to know. I'll try to reproduce this. In the interim you can disable SPDY with setTransports("http/1.1").

@andy572
Copy link

andy572 commented May 15, 2013

Crashes with SSL on Stock HTC One X (Android 4.1.1) too :(

@mauimauer
Copy link

Same here...this seems to be happening on all my devices > 4.1

@lexer
Copy link
Contributor

lexer commented May 30, 2013

Nexus 4. OS 4.2.2

@lexer
Copy link
Contributor

lexer commented May 30, 2013

Workaround is to use only OkHttp connection. Possible problems that 3rd party libraries will still use Android UrlConnection that could cause this crushes.

@andy572
Copy link

andy572 commented May 30, 2013

It has nothing to do with URLConnection - the underlaying libSSL is crashing in
method "SSL_select_next_proto" ... there is possibly a null pointer, for me it seems libSSL get a empty object
when trying to validate a certificate.

The workaround is to force http/1.1 and not to use http 2.0:
ArrayList list = new ArrayList();
list.add("http/1.1");
client.setTransports(list);

@codebutler
Copy link

I started running into this on a Nexus 4 after adding Google Analytics to an app that already was using OkHttp (Note the thread name "GAThread": https://gist.github.com/codebutler/5681044). Unfortunately there doesn't seem to be a way to change the HTTPClient used by GA, so "just use OkHttp everywhere" isn't an available workaround.

Please let me know if I can help with debugging.

@mauimauer
Copy link

Doesn't seem to help in my case. I am using OkHttp as transport for both my own API (using Volley) and for gapi-client. Still crashes when SSL endpoints are involved.

@swankjesse
Copy link
Member

Thanks for reporting. I'm able to reproduce this.

@swankjesse
Copy link
Member

Yeah, looks like this occurs consistently if you use OkHttp and HttpURLConnection in the same application.

@swankjesse
Copy link
Member

So the problem is that Java and Android programs default to using a single global SSL context, accessible to our HTTP clients as the SSLSocketFactory. When OkHttp enables NPN for its own SPDY-related stuff, it ends up turning on NPN for the singleton shared SSL socket factory. Later when HttpURLConnection attempts to do SSL, it freaks out and crashes because NPN is enabled when it isn't expected to be.

A simple immediate workaround for OkHttp is to configure the client to create its own SSL context rather than using the system default. The code to set that up looks like this:

      OkHttpClient okHttpClient = new OkHttpClient();
      SSLContext sslContext;
      try {
        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, null, null);
      } catch (GeneralSecurityException e) {
        throw new AssertionError(); // The system has no TLS. Just give up.
      }
      okHttpClient.setSslSocketFactory(sslContext.getSocketFactory());

I'll investigate changing OkHttp to prefer its own SSL context over the system default. The significant drawback of this approach is that apps that customize the global SSL context will lose these customizations. This could break important features like certificate pinning! So I should be extremely careful if I'm changing behavior here.

@andy572
Copy link

andy572 commented Jun 1, 2013

the workaround is working nice, now i can use spdy and my app is very fast with internet connections.
The problem was as described, i use the twitter4j jar library which is using a httpurlconnection :)

@JakeWharton
Copy link
Member

The pull request to allow installing OkHttp as the backer for URL#openConnection will also mitigate.

@swankjesse
Copy link
Member

Yup. This is the official workaround:

  URL.setURLStreamHandlerFactory(new OkHttpClient());

@kkocel
Copy link
Contributor

kkocel commented Jun 24, 2013

Is there any plan / way to fix this issue?

@swankjesse
Copy link
Member

@kkocel yup. Plan is to switch OkHttp to prefer a private default SSL context rather than the shared singleton context. Unfortunately that's an API incompatible change so it'll need to be on a major release. I'm planning a major 2.0 release within 3 months.

@brycehendrix
Copy link

The workaround did resolve the issue I was having with bugsense causing the crash, as long as I did it prior to calling BugSenseHandler.initAndStartSession()

@orip
Copy link

orip commented Jul 23, 2013

In our case, running URL.setURLStreamHandlerFactory as early as possible (in MyApplication.onCreate) didn't seem to fix the problem.

It was easy enough to convert all our uses of OkHttpClient to create their own SSL context but converting Picasso was a little trickier, so now we have PicassoUtils.with instead of Picasso.with. Works with Picasso 1.1.1 (easy to make it work with Picasso HEAD).

@brycehendrix
Copy link

I take back what I said, I'm still having problems using BugSense and OkHttp together, though less frequently. In my Application class I overload onCreate:

@OverRide
public void onCreate(){
super.onCreate();

URL.setURLStreamHandlerFactory(new OkHttpClient());
BugSenseHandler.initAndStartSession(this, "apikey");

}

Sometimes when an unhandled exception is thrown, BugSense will catch it, then try to report it via SSL and fail with the SSL error. It doesn't always happen, which makes it hard to track down. Maybe the original SSL context is released?

tmszdmsk added a commit to tmszdmsk/arij that referenced this issue Jul 31, 2013
Only jql like inputs are handled.
Wanted to use OkHttp library by retrofit, but there is nasty unresolved for few months bug square/okhttp#184 which doesn't work very well when some parts (e.g. analytics library in that case) doesn't use him.
Fixed bug with calling quicksearch two times when using hardware keyboard ENTER button (key down and key up).
Extracted AuthorizationHeaderGenerator because it's used also with this QuerySearch call.
@robUx4
Copy link
Contributor

robUx4 commented Aug 7, 2013

I am also having issues with Google Analytics when mixed with okhttp. I still get some crashes with URL.setURLStreamHandlerFactory() but not with this hack

@swankjesse
Copy link
Member

For 2.0 we should change the default to not use the global SSL context.

@skykelsey
Copy link

Is there a fix scheduled for this? A lot of people are using this library, and since it doesn't play nicely with other libraries, it should be considered a major bug.

@codefromthecrypt
Copy link

@swankjesse WDYT about a default for this. A naive approach would be to plug the following into OkHttpClient.copyWithDefaults(). Another could be to handle it as a Platform hook.

    if (result.sslSocketFactory == null) {
      try {
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, null, null);
        result.sslSocketFactory = sslContext.getSocketFactory();
      } catch (GeneralSecurityException e) {
        throw new AssertionError(); // The system has no TLS. Just give up.
      }
    }

@swankjesse
Copy link
Member

Yes, but with two small changes:
If you create an OkHttpClient and don't configure anything, all HTTPS requests created with that client share an SSL Socket factory.

If you create an OkHttpClient and install your own SSLSocketFactory, then we don't waste time creating an unused SSLSocketFactory. (Ie. the SSLSocketFactory above must be created lazily.)

@swankjesse
Copy link
Member

(Not sharing an SSLSocketFactory is bad because requests that don't share an SSLSocketFactory can't share a connection in the connection pool.)

@ghost
Copy link

ghost commented Feb 26, 2014

But at now, it crashes.

I tested in
Samsung Galaxy Note 4.3 and LG Optimus G 4.1

I use volley with okhttp stack and google analytics.
"GAThread" crashes with okhttp

When will 2.0 released??

@swankjesse
Copy link
Member

@ceram1 I was hoping soon, but we've made some API changes that make it tricky. I'll talk to @JakeWharton about doing an RC1 or something.

@DanMorganiOS
Copy link

If you come across this thread with a PhoneGap/Cordova application check here for the issue: https://issues.apache.org/jira/browse/CB-7925

@jimmyhmiller
Copy link

I know this was closed a long time ago. But I'm having trouble with okhttp3 and the facebook sdk. I was wondering if this could still be causing an issue, or if there could be some other cause.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Bug in existing code
Projects
None yet
Development

Successfully merging a pull request may close this issue.