I pushed a new version of my app to production and started to get bunch of complains from users.
Turns out with okhttp 4.3.0 there is SSLHandshakeException happening only on Android 5 for some reason. I'm getting this exception for all my requests including requests from 3th party SDKs. It's reproducible on API 21 Emulator.
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:306)
at com.android.okhttp.Connection.upgradeToTls(Connection.java:197)
at com.android.okhttp.Connection.connect(Connection.java:151)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:276)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:211)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:373)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:323)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:491)
at com.android.okhttp.internal.http.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:105)
at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:25)
...
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:318)
at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:219)
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:113)
at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:525)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:302)
at com.android.okhttp.Connection.upgradeToTls(Connection.java:197)聽
at com.android.okhttp.Connection.connect(Connection.java:151)聽
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:276)聽
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:211)聽
at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:373)聽
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:323)聽
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:491)聽
at com.android.okhttp.internal.http.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:105)聽
at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:25)聽
...
Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:318)聽
at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:219)聽
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:113)聽
at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:525)聽
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)聽
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:302)聽
at com.android.okhttp.Connection.upgradeToTls(Connection.java:197)聽
at com.android.okhttp.Connection.connect(Connection.java:151)聽
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:276)聽
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:211)聽
at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:373)聽
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:323)聽
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:491)聽
at com.android.okhttp.internal.http.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:105)聽
at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:25)聽
...
Is there a URL to test against? What version did you upgrade from 4.2?
If you can make a failing test case with our Android test it would make this quicker to debug
Hi, I was using 4.2.2 before.
It happens with almost every HTTPS request I believe on API 21, maybe with some exception as github pages worked fine.
Will try to make a test now.
I just noticed that I get different types of exceptions for different websites. Eg I get SSLHandshakeException for my backend and from fabric SDK and I simply get ConnectException for some other websites.
Sorry I have to go out now, will make tests in a few hours if it's still needed, but it's easy to repro.
Eg try with this url: https://news.am/arm/news/552948.html
It works fine on 4.2.2, but I get java.net.ConnectException: Failed to connect to news.am/2606:4700:20::681a:85c:443 on 4.3
@minas90 That's enough. Thanks!
And to repro SSLHandshakeException use this url: https://docs.fabric.io/android/changelog.html
Two failing reproductions
@Test
fun testRequestFailing1() {
assumeNetwork()
client = client.newBuilder().connectionSpecs(listOf(ConnectionSpec.COMPATIBLE_TLS)).build()
val request = Request.Builder().url("https://news.am/arm/news/552948.html").build()
val response = client.newCall(request).execute()
response.use {
assertEquals(200, response.code)
}
}
@Test
fun testRequestFailing2() {
assumeNetwork()
client = client.newBuilder().connectionSpecs(listOf(ConnectionSpec.COMPATIBLE_TLS)).build()
val request = Request.Builder().url("https://docs.fabric.io/android/changelog.html").build()
val response = client.newCall(request).execute()
response.use {
assertEquals(200, response.code)
}
}
Confirmed working against 4.2.2 https://github.com/yschimke/okhttp/tree/4.2.2_test
Failing against 4.3 https://github.com/yschimke/okhttp/tree/4.3_test
Reviewing git diff parent-4.2.2..parent-4.3.0
It's mostly relevant functional changes in http/2 settings, pings, and AndroidSocketAdapter. Starting with the latter.
@swankjesse heads up another fix for 4.3.1
We lost this code in 4.3, which breaks some hosts on Android 5
// This is SSLParameters.setServerNames() in API 24+.
setHostname.invoke(sslSocket, hostname)
Most helpful comment
@swankjesse heads up another fix for 4.3.1
We lost this code in 4.3, which breaks some hosts on Android 5