I'm facing a strange issue. I use OkHTTP to request a web form, parse it and show it as native Android UI.
Everything used to work fine but then recently, the requests started failing on Android versions below Lollipop. It started raising the following exception:
Caused by: javax.net.ssl.SSLException: Connection closed by peer
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:405)
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:242)
at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:200)
at okhttp3.internal.connection.RealConnection.buildConnection(RealConnection.java:174)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:114)
at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:196)
at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:132)
at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:101)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:212)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:179)
at okhttp3.RealCall.execute(RealCall.java:63)
I searched the internet and found out that it could be caused because Android had TLS1.2 disable before Lollipop and the server might have stopped supporting other protocols.
But I suspect that to be the issue since the same URLs load perfectly fine in a WebView on versions below Lollipop. This leads me to believe that it could be a configuration issue with the OkHTTP client.
What could be the reason for this bug?
Here is how I build the HTTP client:
public static synchronized OkHttpClient getAllAcceptingOkHttpClient() {
if (sOkHttpClient == null) {
SSLSocketFactory factory = getAllAcceptingSSLSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.cookieJar(new JavaNetCookieJar(AadharApplication.cookieManager));
if (factory != null) {
builder.sslSocketFactory(factory);
}
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
sOkHttpClient = builder.build();
}
return sOkHttpClient;
}
private static SSLSocketFactory getAllAcceptingSSLSocketFactory() {
try {
final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, sTrustAllCerts, new java.security.SecureRandom());
return sslContext.getSocketFactory();
} catch (KeyManagementException | NoSuchAlgorithmException e) {
Log.d(TAG, "", e);
return null;
}
}
private static final TrustManager[] sTrustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
};
PS: I know this enables MITM attacks, but I know exactly what I'm doing. :)