Okhttp: [okhttp:3.8.0] SSLSocketFactory Crash with Android 4.1.2.

Created on 11 Sep 2017  Â·  9Comments  Â·  Source: square/okhttp

I observed this crash often occurring with Samsung 4.1.2 devices for my app.
Crash occurs while building a OkHttpClient.

Crash :

MyNetworkServiceRetryThread:null:java.lang.AssertionError:
at okhttp3.OkHttpClient.javax.net.ssl.SSLSocketFactory systemDefaultSslSocketFactory(javax.net.ssl.X509TrustManager)(SourceFile:292)
at okhttp3.OkHttpClient.void <init>(okhttp3.OkHttpClient$Builder)(SourceFile:250)
at a.b.c.net.MyNetworkService.okhttp3.OkHttpClient okhttp3.OkHttpClient$Builder.build()(SourceFile:3907)

Scenario :
I have set the socket factory and trust manager for "TLS" something like this :

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 = sslContext.getSocketFactory();

OkHttpClient client = new OkHttpClient.Builder()
    .sslSocketFactory(sslSocketFactory, trustManager);
    .build();

However, I am providing my own KeyStore
so trustManagerFactory.init((KeyStore) null); above is not set to null.

Any help/workarounds ?

needs info

Most helpful comment

The first two look like broken JVMs. In the first, the harmony provider is inconsistent internally. In the second it doesn't provide the well known "X509" trust manager.

If you really want to track these down, I think you might need to collect details about the phone, OS version. But ultimately I don't think you will get a direct fix anyway. These are on really old versions of Android, so updates are unlikely.

If these are happening enough to worry about, you might consider using the Google Play provider. https://developer.android.com/training/articles/security-gms-provider.html.

@swankjesse @JakeWharton thoughts?

All 9 comments

Can you easily reproduce with 3.9.0, it should give us additional information as we now log the root cause.

throw assertionError("No System TLS", e); // The system has no TLS. Just give up.

Also, what is the intention for the TrustManager and SSLContext code you show. It looks pretty much like the default behaviour anyway. But systemDefaultSslSocketFactory shouldn't be called if you actually configure your client as indicated above.

Thanks, I have updated the the version and will provide additional information. It might take couple of weeks for the same crash to show up.

The intention is to use our CAs for certificate validation. Hence, we generate our own keystore and add them to the TMF (TrustManagerFactory). As shown here : https://developer.android.com/training/articles/security-ssl.html, under section "Unknown certificate authority".

Yep, without the actual exception or the code so we can reproduce it is hard to see what is happening. Include to 3.9.0 stacktrace when you have it.

@yschimke Got more info for you as requested :

java.lang.AssertionError: No System TLS
at okhttp3.internal.Util.java.lang.AssertionError assertionError(java.lang.String,java.lang.Exception(SourceFile:482)
at okhttp3.OkHttpClient.javax.net.ssl.SSLSocketFactory systemDefaultSslSocketFactory(javax.net.ssl.X509TrustManager)(SourceFile:302)
at okhttp3.OkHttpClient.void <init>(okhttp3.OkHttpClient$Builder)(SourceFile:253)
at a.b.c.dokhttp3.OkHttpClient okhttp3.OkHttpClient$Builder.build()(SourceFile:3919)

Interesting to mention is that, the same client/device could perform REST requests/response to our backend. But then randomly we also see this crash occurring. Any workaround to avoid such crashes ?

@shailesh-mota is there a root cause exception also logged?

That exception tries to keep the root cause around, but you only have the top one.

return (AssertionError) new AssertionError(message).initCause(e);

@yschimke Okay. We have implemented our own exception logger (implements Thread.UncaughtExceptionHandler) due to the nature of our app. Maybe it is not catching the entire stack trace. I will get back to you with _Caused by_ part of the trace.

@yschimke these are the following different types of "Causes" reported with the exception :

    1.
Caused by:
java.security.KeyManagementException: 
java.security.KeyStoreException: 
java.security.NoSuchAlgorithmException:
KeyStore BKS implementation not found:
org.apache.harmony.xnet.provider.jsse.SSLParametersImpl.createDefaultKeyManager(SSLParametersImpl.java:370):
org.apache.harmony.xnet.provider.jsse.SSLParametersImpl.getDefaultKeyManager(SSLParametersImpl.java:356):
org.apache.harmony.xnet.provider.jsse.SSLParametersImpl.<init>(SSLParametersImpl.java:112):
    2.
Caused by:
java.security.NoSuchAlgorithmException: 
TrustManagerFactory X509 implementation not found:
org.apache.harmony.security.fortress.Engine.notFound(Engine.java:177):
org.apache.harmony.security.fortress.Engine.getInstance(Engine.java:151):
javax.net.ssl.TrustManagerFactory.getInstance(TrustManagerFactory.java:72):
    3.
java.lang.IllegalStateException
Cause already initialized
at okhttp3.internal.Util.java.lang.AssertionError assertionError(java.lang.String,java.lang.Exception)(SourceFile:482)
at okhttp3.OkHttpClient.javax.net.ssl.SSLSocketFactory systemDefaultSslSocketFactory(javax.net.ssl.X509TrustManager)(SourceFile:302)
at okhttp3.OkHttpClient.void <init>(okhttp3.OkHttpClient$Builder)(SourceFile:253) 
at my.package.MyService.okhttp3.OkHttpClient okhttp3.OkHttpClient$Builder.build()(SourceFile:3919)

Any suggestions ? (Especially for 2nd and 3rd crash type.)

The third one looks crazy to me. The code works, it doesn't already have a cause as we create teh AssertionError without a cause.

  @Test
  public void testAssertionError() {
    NullPointerException nullPointerException = new NullPointerException();
    AssertionError ae = Util.assertionError("npe", nullPointerException);
    assertSame(nullPointerException, ae.getCause());
    assertEquals("npe", ae.getMessage());
  }

The first two look like broken JVMs. In the first, the harmony provider is inconsistent internally. In the second it doesn't provide the well known "X509" trust manager.

If you really want to track these down, I think you might need to collect details about the phone, OS version. But ultimately I don't think you will get a direct fix anyway. These are on really old versions of Android, so updates are unlikely.

If these are happening enough to worry about, you might consider using the Google Play provider. https://developer.android.com/training/articles/security-gms-provider.html.

@swankjesse @JakeWharton thoughts?

Was this page helpful?
0 / 5 - 0 ratings