commons-app / apps-android-commons

The Wikimedia Commons Android app allows users to upload pictures from their Android phone/tablet to Wikimedia Commons
https://commons-app.github.io/
Apache License 2.0
1.03k stars 1.24k forks source link

[Bug]: java.security.cert.CertPathValidatorException on devices below API 25 #5857

Open parneet-guraya opened 1 month ago

parneet-guraya commented 1 month ago

Summary

java.security.cert.CertPathValidatorException on devices below API 25 i.e 24 ,23, 22, 21

When logging in, app raises the said exception. It varies on different flavor (both debug) ->

I found out the this issue did occur a while ago #2885 and was fixed at that time. Also, it could be that it occurs on emulator only (not likely though)

Steps to reproduce

Expected behaviour

Shouldn't raise exception.

Actual behaviour

Exception raised

Device name

Android Emulators

Android version

Android 7, 6, 5.1, 5

Commons app version

5.0.2

Device logs

Logs, when error occur in prod flavor ->

Fetching upload count failed javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:322) at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:379) at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:337) at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:209) at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226) at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106) at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74) at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255) at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.kt:221) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201) at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154) at fr.free.nrw.commons.mwapi.OkHttpJsonApiClient.lambda$getUploadCount$2$fr-free-nrw-commons-mwapi-OkHttpJsonApiClient(OkHttpJsonApiClient.java:178) at fr.free.nrw.commons.mwapi.OkHttpJsonApiClient$$ExternalSyntheticLambda6.call(D8$$SyntheticClass:0) at io.reactivex.internal.operators.single.SingleFromCallable.subscribeActual(SingleFromCallable.java:44) at io.reactivex.Single.subscribe(Single.java:3603) at io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89) at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:578) at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66) at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) at java.lang.Thread.run(Thread.java:818) 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:114) at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:550) at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:318) at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:379)  at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:337)  at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:209)  at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)  at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)  at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)  at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)  at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)  at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)  at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)  at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)  at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.kt:221)  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)  at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)  at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154)  at fr.free.nrw.commons.mwapi.OkHttpJsonApiClient.lambda$getUploadCount$2$fr-free-nrw-commons-mwapi-OkHttpJsonApiClient(OkHttpJsonApiClient.java:178)  at fr.free.nrw.commons.mwapi.OkHttpJsonApiClient$$ExternalSyntheticLambda6.call(D8$$SyntheticClass:0)  at io.reactivex.internal.operators.single.SingleFromCallable.subscribeActual(SingleFromCallable.java:44)  at io.reactivex.Single.subscribe(Single.java:3603)  at io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89)  at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:578)  at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)  at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)  at java.util.concurrent.FutureTask.run(FutureTask.java:237)  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)  at java.lang.Thread.run(Thread.java:818)  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:114)  at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:550)  at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)  at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:318)  at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:379)  at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:337)  at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:209)  at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)  at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)  at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)  at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)  at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)  at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)  at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)  at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)  at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.kt:221)  at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)  at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)  at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154)  at fr.free.nrw.commons.mwapi.OkHttpJsonApiClient.lambda$getUploadCount$2$fr-free-nrw-commons-mwapi-OkHttpJsonApiClient(OkHttpJsonApiClient.java:178)  at fr.free.nrw.commons.mwapi.OkHttpJsonApiClient$$ExternalSyntheticLambda6.call(D8$$SyntheticClass:0)  at io.reactivex.internal.operators.single.SingleFromCallable.subscribeActual(SingleFromCallable.java:44)  at io.reactivex.Single.subscribe(Single.java:3603)  at io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89)  at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:578)  at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)  at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)  at java.util.concurrent.FutureTask.run(FutureTask.java:237)  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)  at java.lang.Thread.run(Thread.java:818) 

Screen-shots

On Beta flavor

test beta

On Prod flavor

test prod

Would you like to work on the issue?

None

sivaraam commented 3 weeks ago

I'm able to reproduce this on a Android 5.x device. I came across this relevant thread. The problem appears to be with the certificate chain of the Let's Enrcypt certificate that is used by the beta server and the Commons Toolforge instance. We could check with the Toolforge team and beta cluster team to see if there is a possibility of changing the certificate to a widely accepted one as mentioned in the article.

As a workaround, I was able to manually install the new root certificate in my device and the error went away for me. If possible, could you try the same if feasible ?