From e511b8ecdc0edb97270f08c2879e73ecebb90b4c Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Mon, 27 Jan 2020 00:37:08 +0530 Subject: [PATCH 1/2] Fixes #3320 * Added SSL certificate for commons beta * Asked OKHTTP client to use SSLContext from beta certificate * Probable Fix of #3345 --- .../assets/*.wikimedia.beta.wmflabs.org.cer | Bin 0 -> 1870 bytes .../nrw/commons/OkHttpConnectionFactory.java | 11 ++- .../free/nrw/commons/di/NetworkingModule.java | 18 +++- .../java/fr/free/nrw/commons/di/SslUtils.kt | 90 ++++++++++++++++++ 4 files changed, 111 insertions(+), 8 deletions(-) create mode 100644 app/src/main/assets/*.wikimedia.beta.wmflabs.org.cer create mode 100644 app/src/main/java/fr/free/nrw/commons/di/SslUtils.kt diff --git a/app/src/main/assets/*.wikimedia.beta.wmflabs.org.cer b/app/src/main/assets/*.wikimedia.beta.wmflabs.org.cer new file mode 100644 index 0000000000000000000000000000000000000000..ffb4c37c991824ee2b3b563ee34202355eb0cbe8 GIT binary patch literal 1870 zcmXqLV)rs=Vl!I6%*4pVB*Yxpkasq{;iy4Tn#jz_UsmfrGT>$7)N1o+`_9YA$j!=N z;AO~dz{$oO%EBhh6dG(OW*`FMa0&DJq?V``E4bz*7gZLN7%Cemg2b7HrBK8b97{_w z@{2M{DitD(4dldm4J{1~4J`~T3=B*Sqr`cQ3=E76&7fQZbwgDHWw0?kGFp1&nc11S zsVSL>dP%7ziF)O^X*r2W#d`Tg=?0Mo!ffn7SDv$FVr1h0Gng6KnVlF|mcQ7@WHC*@ zVa=7y@X5ZjPUz~_X7%&2dQD${?$_)@R+F4(r$$%eXDocNxQSKFpovw;fDh;nS$;;w|12!bOzaH?vLL=H3&{T*+H8!htnAD{tD!6= z10ImHFi1I*0Ru!aABz}^$imfIF5mQWUYYK=tJvlK#2yFd_yPlYkYZ&P2?MbPkriH9 z$t<;ZcRjmkxqX>y>if?t-Yhi8hndXC$dYW3XrKq<8!)yhWt5Z@Sn2EMCl?p!W#*OW zRv7E$q?Qz?LSh0OKKgL=Ol`_g^~tG4B{&Mz%W#-cz0rl2gfs2G_1 z@EB2+UzwPW#R!-kC7JnoiA7jUfTmF#A%r&tH%UX%H}=qhYQ+&YP+1%y0}Oaj#=#XX zz<32o;|vw3c3fcsk;WM!iduSAsYUr(Fi?Z#5hg}4DOesU zD8|T3O^mE;Twtx&Dw$ZASQ@{vG=66I$WX?>zCA|zX>G>;j~kB3DvKW9^(?$5e9HE$ zcY6}8q%torl3`$A%&Xn!;>WxB>0$DRB~!5~^mB ze&tv6xwE~?bCSHxUf*x2Rx?Ao4z1(<2vqVqM`@exYvJ{*+Hz;umc;h@I!4SXvLM}G+wVcXcYr<6C)!-@cx)JRmB>z)zSK=vX5-~^=D(zmg~29<<}R7q}bdMbzv`D z{#k?L)3Jw=e@e`LJy)HO`A4;3o4MeFQ&YqrOV~Y3{J-(Obl%E#waEVCci;3yhON2r zlr=eSCePj@hi%p@Vn4IC_4Ml%`ZEG1C7zue|6}7#*P>;W6)`^+HNTor8JxU4@mxm# zLyIMj(_*40m!Dr>)?(zqdGsRl%J*+9c@}JNwleYKc`lm%eCpMnRr(8e|DC3C+1;T( z{2I5;t+MCQYo^_5-#0_@$K5hRsnS>rH^T|H7dhm8&J&+0!Ro&Ghg#SktJAJkTh|{s f^*4KWMdhcdGo)&4xx4Nq*!P{>v@Ugp{K66dVOyg> literal 0 HcmV?d00001 diff --git a/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java b/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java index 6fe317c0a4..ffb13df4d5 100644 --- a/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java +++ b/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java @@ -8,6 +8,7 @@ import java.io.File; import java.io.IOException; +import fr.free.nrw.commons.di.SslUtils; import okhttp3.Cache; import okhttp3.Interceptor; import okhttp3.OkHttpClient; @@ -29,13 +30,17 @@ public final class OkHttpConnectionFactory { @NonNull private static OkHttpClient createClient() { - return new OkHttpClient.Builder() + OkHttpClient.Builder builder = new OkHttpClient.Builder() .cookieJar(SharedPreferenceCookieManager.getInstance()) .cache(NET_CACHE) .addInterceptor(getLoggingInterceptor()) .addInterceptor(new UnsuccessfulResponseInterceptor()) - .addInterceptor(new CommonHeaderRequestInterceptor()) - .build(); + .addInterceptor(new CommonHeaderRequestInterceptor()); + + if(BuildConfig.FLAVOR.equals("beta")){ + builder.sslSocketFactory(SslUtils.INSTANCE.getSslContextForCertificateFile(CommonsApplication.getInstance(), "*.wikimedia.beta.wmflabs.org.cer").getSocketFactory()); + } + return builder.build(); } private static HttpLoggingInterceptor getLoggingInterceptor() { diff --git a/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java b/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java index c6e6033f58..db76628e71 100644 --- a/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java +++ b/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java @@ -18,6 +18,8 @@ import javax.inject.Named; import javax.inject.Singleton; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; import dagger.Module; import dagger.Provides; @@ -58,14 +60,20 @@ public class NetworkingModule { public OkHttpClient provideOkHttpClient(Context context, HttpLoggingInterceptor httpLoggingInterceptor) { File dir = new File(context.getCacheDir(), "okHttpCache"); - return new OkHttpClient.Builder().connectTimeout(60, TimeUnit.SECONDS) - .writeTimeout(60, TimeUnit.SECONDS) + OkHttpClient.Builder builder = new OkHttpClient.Builder().connectTimeout(60, TimeUnit.SECONDS) + .writeTimeout(60, TimeUnit.SECONDS) .addInterceptor(httpLoggingInterceptor) - .readTimeout(60, TimeUnit.SECONDS) - .cache(new Cache(dir, OK_HTTP_CACHE_SIZE)) - .build(); + .readTimeout(60, TimeUnit.SECONDS) + .cache(new Cache(dir, OK_HTTP_CACHE_SIZE)); + + if(BuildConfig.FLAVOR.equals("beta")){ + builder.sslSocketFactory(SslUtils.INSTANCE.getSslContextForCertificateFile(context, "*.wikimedia.beta.wmflabs.org.cer").getSocketFactory()); + } + return builder.build(); } + + @Provides @Singleton public HttpLoggingInterceptor provideHttpLoggingInterceptor() { diff --git a/app/src/main/java/fr/free/nrw/commons/di/SslUtils.kt b/app/src/main/java/fr/free/nrw/commons/di/SslUtils.kt new file mode 100644 index 0000000000..a24c6ddf91 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/di/SslUtils.kt @@ -0,0 +1,90 @@ +package fr.free.nrw.commons.di + +import android.content.Context +import android.util.Log +import java.security.KeyManagementException +import java.security.KeyStore +import java.security.NoSuchAlgorithmException +import java.security.SecureRandom +import java.security.cert.Certificate +import java.security.cert.CertificateException +import java.security.cert.CertificateFactory +import java.security.cert.X509Certificate +import javax.net.ssl.* + +object SslUtils { + + fun getSslContextForCertificateFile(context: Context, fileName: String): SSLContext { + try { + val keyStore = SslUtils.getKeyStore(context, fileName) + val sslContext = SSLContext.getInstance("SSL") + val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) + trustManagerFactory.init(keyStore) + sslContext.init(null, trustManagerFactory.trustManagers, SecureRandom()) + return sslContext + } catch (e: Exception) { + val msg = "Error during creating SslContext for certificate from assets" + e.printStackTrace() + throw RuntimeException(msg) + } + } + + private fun getKeyStore(context: Context, fileName: String): KeyStore? { + var keyStore: KeyStore? = null + try { + val assetManager = context.assets + val cf = CertificateFactory.getInstance("X.509") + val caInput = assetManager.open(fileName) + val ca: Certificate + try { + ca = cf.generateCertificate(caInput) + Log.d("SslUtilsAndroid", "ca=" + (ca as X509Certificate).subjectDN) + } finally { + caInput.close() + } + + val keyStoreType = KeyStore.getDefaultType() + keyStore = KeyStore.getInstance(keyStoreType) + keyStore!!.load(null, null) + keyStore.setCertificateEntry("ca", ca) + } catch (e: Exception) { + e.printStackTrace() + } + + return keyStore + } + + fun getTrustAllHostsSSLSocketFactory(): SSLSocketFactory? { + try { + // Create a trust manager that does not validate certificate chains + val trustAllCerts = arrayOf(object : X509TrustManager { + + override fun getAcceptedIssuers(): Array { + return arrayOf() + } + + @Throws(CertificateException::class) + override fun checkClientTrusted(chain: Array, authType: String) { + } + + @Throws(CertificateException::class) + override fun checkServerTrusted(chain: Array, authType: String) { + } + }) + + // Install the all-trusting trust manager + val sslContext = SSLContext.getInstance("SSL") + sslContext.init(null, trustAllCerts, java.security.SecureRandom()) + // Create an ssl socket factory with our all-trusting manager + + return sslContext.socketFactory + } catch (e: KeyManagementException) { + e.printStackTrace() + return null + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + return null + } + + } +} \ No newline at end of file From f62d2caa80c103ea0ec4ef5767bb553f00d740a1 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Mon, 27 Jan 2020 00:46:32 +0530 Subject: [PATCH 2/2] Use ConfigUtils to verify flavor --- .../main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java | 3 ++- app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java b/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java index ffb13df4d5..3e7f973031 100644 --- a/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java +++ b/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java @@ -9,6 +9,7 @@ import java.io.IOException; import fr.free.nrw.commons.di.SslUtils; +import fr.free.nrw.commons.utils.ConfigUtils; import okhttp3.Cache; import okhttp3.Interceptor; import okhttp3.OkHttpClient; @@ -37,7 +38,7 @@ private static OkHttpClient createClient() { .addInterceptor(new UnsuccessfulResponseInterceptor()) .addInterceptor(new CommonHeaderRequestInterceptor()); - if(BuildConfig.FLAVOR.equals("beta")){ + if(ConfigUtils.isBetaFlavour()){ builder.sslSocketFactory(SslUtils.INSTANCE.getSslContextForCertificateFile(CommonsApplication.getInstance(), "*.wikimedia.beta.wmflabs.org.cer").getSocketFactory()); } return builder.build(); diff --git a/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java b/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java index db76628e71..581ff37fd1 100644 --- a/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java +++ b/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java @@ -33,6 +33,7 @@ import fr.free.nrw.commons.mwapi.UserInterface; import fr.free.nrw.commons.review.ReviewInterface; import fr.free.nrw.commons.upload.UploadInterface; +import fr.free.nrw.commons.utils.ConfigUtils; import fr.free.nrw.commons.wikidata.WikidataInterface; import okhttp3.Cache; import okhttp3.HttpUrl; @@ -66,7 +67,7 @@ public OkHttpClient provideOkHttpClient(Context context, .readTimeout(60, TimeUnit.SECONDS) .cache(new Cache(dir, OK_HTTP_CACHE_SIZE)); - if(BuildConfig.FLAVOR.equals("beta")){ + if(ConfigUtils.isBetaFlavour()){ builder.sslSocketFactory(SslUtils.INSTANCE.getSslContextForCertificateFile(context, "*.wikimedia.beta.wmflabs.org.cer").getSocketFactory()); } return builder.build();