From dc5f0c87a230b7be948191917617fd9b6a2938a9 Mon Sep 17 00:00:00 2001 From: Konrad Pozniak Date: Sun, 31 Jan 2021 19:35:39 +0100 Subject: [PATCH] remove let's encrypt root cert again (#2056) * remove let's encrypt root cert again * fix user-agent example --- .../keylesspalace/tusky/di/NetworkModule.kt | 41 ++++++- .../keylesspalace/tusky/util/OkHttpUtils.kt | 115 ------------------ 2 files changed, 38 insertions(+), 118 deletions(-) delete mode 100644 app/src/main/java/com/keylesspalace/tusky/util/OkHttpUtils.kt diff --git a/app/src/main/java/com/keylesspalace/tusky/di/NetworkModule.kt b/app/src/main/java/com/keylesspalace/tusky/di/NetworkModule.kt index ca60bac8..fb232a64 100644 --- a/app/src/main/java/com/keylesspalace/tusky/di/NetworkModule.kt +++ b/app/src/main/java/com/keylesspalace/tusky/di/NetworkModule.kt @@ -16,6 +16,8 @@ package com.keylesspalace.tusky.di import android.content.Context +import android.content.SharedPreferences +import android.os.Build import android.text.Spanned import com.google.gson.Gson import com.google.gson.GsonBuilder @@ -24,15 +26,20 @@ import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.json.SpannedTypeAdapter import com.keylesspalace.tusky.network.InstanceSwitchAuthInterceptor import com.keylesspalace.tusky.network.MastodonApi -import com.keylesspalace.tusky.util.okhttpClient +import com.keylesspalace.tusky.util.getNonNullString import dagger.Module import dagger.Provides +import okhttp3.Cache +import okhttp3.OkHttp import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory import retrofit2.converter.gson.GsonConverterFactory import retrofit2.create +import java.net.InetSocketAddress +import java.net.Proxy +import java.util.concurrent.TimeUnit import javax.inject.Singleton /** @@ -54,9 +61,37 @@ class NetworkModule { @Singleton fun providesHttpClient( accountManager: AccountManager, - context: Context + context: Context, + preferences: SharedPreferences ): OkHttpClient { - return okhttpClient(context) + val httpProxyEnabled = preferences.getBoolean("httpProxyEnabled", false) + val httpServer = preferences.getNonNullString("httpProxyServer", "") + val httpPort = preferences.getNonNullString("httpProxyPort", "-1").toIntOrNull() ?: -1 + val cacheSize = 25 * 1024 * 1024L // 25 MiB + val builder = OkHttpClient.Builder() + .addInterceptor { chain -> + /** + * Add a custom User-Agent that contains Tusky, Android and OkHttp Version to all requests + * Example: + * User-Agent: Tusky/1.1.2 Android/5.0.2 OkHttp/4.9.0 + * */ + val requestWithUserAgent = chain.request().newBuilder() + .header( + "User-Agent", + "Tusky/${BuildConfig.VERSION_NAME} Android/${Build.VERSION.RELEASE} OkHttp/${OkHttp.VERSION}" + ) + .build() + chain.proceed(requestWithUserAgent) + } + .readTimeout(30, TimeUnit.SECONDS) + .writeTimeout(30, TimeUnit.SECONDS) + .cache(Cache(context.cacheDir, cacheSize)) + + if (httpProxyEnabled && httpServer.isNotEmpty() && httpPort > 0 && httpPort < 65535) { + val address = InetSocketAddress.createUnresolved(httpServer, httpPort) + builder.proxy(Proxy(Proxy.Type.HTTP, address)) + } + return builder .apply { addInterceptor(InstanceSwitchAuthInterceptor(accountManager)) if (BuildConfig.DEBUG) { diff --git a/app/src/main/java/com/keylesspalace/tusky/util/OkHttpUtils.kt b/app/src/main/java/com/keylesspalace/tusky/util/OkHttpUtils.kt deleted file mode 100644 index 3e1b89c6..00000000 --- a/app/src/main/java/com/keylesspalace/tusky/util/OkHttpUtils.kt +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright 2020 Tusky Contributors - * - * This file is part of Tusky. - * - * Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU - * Lesser General Public License as published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with Tusky. If - * not, see . */ - -package com.keylesspalace.tusky.util - -import android.content.Context -import android.os.Build -import androidx.preference.PreferenceManager -import com.keylesspalace.tusky.BuildConfig -import okhttp3.Cache -import okhttp3.OkHttp -import okhttp3.OkHttpClient -import okhttp3.tls.HandshakeCertificates -import java.io.ByteArrayInputStream -import java.net.InetSocketAddress -import java.net.Proxy -import java.security.cert.CertificateFactory -import java.security.cert.X509Certificate -import java.util.concurrent.TimeUnit - -fun okhttpClient(context: Context): OkHttpClient.Builder { - val preferences = PreferenceManager.getDefaultSharedPreferences(context) - - val httpProxyEnabled = preferences.getBoolean("httpProxyEnabled", false) - val httpServer = preferences.getNonNullString("httpProxyServer", "") - val httpPort = preferences.getNonNullString("httpProxyPort", "-1").toIntOrNull() ?: -1 - - val cacheSize = 25 * 1024 * 1024 // 25 MiB - val builder = OkHttpClient.Builder() - .addInterceptor { chain -> - /** - * Add a custom User-Agent that contains Tusky, Android and Okhttp Version to all requests - * Example: - * User-Agent: Tusky/1.1.2 Android/5.0.2 - * */ - val requestWithUserAgent = chain.request().newBuilder() - .header( - "User-Agent", - "Tusky/${BuildConfig.VERSION_NAME} Android/${Build.VERSION.RELEASE} OkHttp/${OkHttp.VERSION}" - ) - .build() - chain.proceed(requestWithUserAgent) - } - .readTimeout(30, TimeUnit.SECONDS) - .writeTimeout(30, TimeUnit.SECONDS) - .cache(Cache(context.cacheDir, cacheSize.toLong())) - - if (httpProxyEnabled && httpServer.isNotEmpty() && httpPort > 0 && httpPort < 65535) { - val address = InetSocketAddress.createUnresolved(httpServer, httpPort) - builder.proxy(Proxy(Proxy.Type.HTTP, address)) - } - - // trust the new Let's Encrypt root certificate that is not available on Android < 7.1.1 - // new cert https://letsencrypt.org/certs/isrgrootx1.pem - // see https://letsencrypt.org/2020/11/06/own-two-feet.html - // see https://stackoverflow.com/questions/64844311/certpathvalidatorexception-connecting-to-a-lets-encrypt-host-on-android-m-or-ea - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - val isgCert = """ - -----BEGIN CERTIFICATE----- - MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw - TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh - cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 - WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu - ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY - MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc - h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ - 0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U - A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW - T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH - B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC - B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv - KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn - OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn - jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw - qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI - rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV - HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq - hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL - ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ - 3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK - NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 - ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur - TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC - jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc - oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq - 4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA - mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d - emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= - -----END CERTIFICATE----- - """.trimIndent() - val cf = CertificateFactory.getInstance("X.509") - val isgCertificate = cf.generateCertificate(ByteArrayInputStream(isgCert.toByteArray(charset("UTF-8")))) - val certificates = HandshakeCertificates.Builder() - .addTrustedCertificate(isgCertificate as X509Certificate) - .addPlatformTrustedCertificates() - .build() - builder.sslSocketFactory( - certificates.sslSocketFactory(), - certificates.trustManager - ) - } - return builder -}