diff options
author | ByteHamster <info@bytehamster.com> | 2021-03-01 16:21:39 +0100 |
---|---|---|
committer | ByteHamster <info@bytehamster.com> | 2021-03-01 16:21:39 +0100 |
commit | 0e94aa5d9d02dd9b8a88b3b03eb279cb386b3dc3 (patch) | |
tree | b1282edeb33eab01a5ad2ced49d40fa015c768af | |
parent | ddd6a12354b776bf0ae28b2d0ea2f1f067daf341 (diff) | |
download | AntennaPod-0e94aa5d9d02dd9b8a88b3b03eb279cb386b3dc3.zip |
Moved SSL providers to new module
17 files changed, 158 insertions, 69 deletions
diff --git a/build.gradle b/build.gradle index aa7f8ebbe..e4c95ae30 100644 --- a/build.gradle +++ b/build.gradle @@ -73,6 +73,7 @@ project.ext { // Google Play build wearableSupportVersion = "2.6.0" + playServicesVersion = "8.4.0" //Tests awaitilityVersion = "3.1.6" diff --git a/core/build.gradle b/core/build.gradle index e68fa9f97..75ad7faad 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -71,6 +71,7 @@ android { } dependencies { + implementation project(':net:ssl') implementation project(':ui:app-start-intent') implementation project(':ui:common') @@ -102,13 +103,10 @@ dependencies { // Non-free dependencies: playApi 'com.google.android.libraries.cast.companionlibrary:ccl:2.9.1' playApi 'androidx.mediarouter:mediarouter:1.0.0' - playApi 'com.google.android.gms:play-services-cast:8.4.0' + playApi "com.google.android.gms:play-services-cast:$playServicesVersion" playApi "com.google.android.support:wearable:$wearableSupportVersion" compileOnly "com.google.android.wearable:wearable:$wearableSupportVersion" - // bundle conscrypt with free builds - freeImplementation "org.conscrypt:conscrypt-android:$conscryptVersion" - testImplementation "org.awaitility:awaitility:$awaitilityVersion" testImplementation 'junit:junit:4.13' testImplementation 'org.mockito:mockito-inline:3.5.13' diff --git a/core/src/free/java/de/danoeh/antennapod/core/ClientConfig.java b/core/src/free/java/de/danoeh/antennapod/core/ClientConfig.java index 0193bf8ce..755bec14e 100644 --- a/core/src/free/java/de/danoeh/antennapod/core/ClientConfig.java +++ b/core/src/free/java/de/danoeh/antennapod/core/ClientConfig.java @@ -1,8 +1,8 @@ package de.danoeh.antennapod.core; import android.content.Context; -import java.security.Security; -import org.conscrypt.Conscrypt; + +import de.danoeh.antennapod.net.ssl.SslProviderInstaller; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; @@ -42,16 +42,11 @@ public class ClientConfig { UserPreferences.init(context); UsageStatistics.init(context); PlaybackPreferences.init(context); - installSslProvider(context); + SslProviderInstaller.install(context); NetworkUtils.init(context); AntennapodHttpClient.setCacheDirectory(new File(context.getCacheDir(), "okhttp")); SleepTimerPreferences.init(context); NotificationUtils.createChannels(context); initialized = true; } - - private static void installSslProvider(Context context) { - // Insert bundled conscrypt as highest security provider (overrides OS version). - Security.insertProviderAt(Conscrypt.newProvider(), 1); - } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java index a01b3cb52..c4029d57f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java @@ -1,19 +1,14 @@ package de.danoeh.antennapod.core.service.download; -import android.os.Build; import android.text.TextUtils; import android.util.Log; import androidx.annotation.NonNull; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.BasicAuthorizationInterceptor; import de.danoeh.antennapod.core.service.UserAgentInterceptor; -import de.danoeh.antennapod.core.ssl.BackportTrustManager; -import de.danoeh.antennapod.core.ssl.NoV1SslSocketFactory; import de.danoeh.antennapod.core.storage.DBWriter; -import de.danoeh.antennapod.core.util.Flavors; +import de.danoeh.antennapod.net.ssl.SslClientSetup; import okhttp3.Cache; -import okhttp3.CipherSuite; -import okhttp3.ConnectionSpec; import okhttp3.Credentials; import okhttp3.HttpUrl; import okhttp3.JavaNetCookieJar; @@ -21,8 +16,6 @@ import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import okhttp3.internal.http.StatusLine; - -import javax.net.ssl.X509TrustManager; import java.io.File; import java.net.CookieManager; import java.net.CookiePolicy; @@ -30,9 +23,6 @@ import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.SocketAddress; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import java.util.concurrent.TimeUnit; /** @@ -140,28 +130,7 @@ public class AntennapodHttpClient { } } - if (Flavors.FLAVOR == Flavors.FREE) { - // The Free flavor bundles a modern conscrypt (security provider), so CustomSslSocketFactory - // is only used to make sure that modern protocols (TLSv1.3 and TLSv1.2) are enabled and - // that old, deprecated, protocols (like SSLv3, TLSv1.0 and TLSv1.1) are disabled. - X509TrustManager trustManager = BackportTrustManager.create(); - builder.sslSocketFactory(new NoV1SslSocketFactory(trustManager), trustManager); - } else if (Build.VERSION.SDK_INT < 21) { - X509TrustManager trustManager = BackportTrustManager.create(); - builder.sslSocketFactory(new NoV1SslSocketFactory(trustManager), trustManager); - - // workaround for Android 4.x for certain web sites. - // see: https://github.com/square/okhttp/issues/4053#issuecomment-402579554 - List<CipherSuite> cipherSuites = new ArrayList<>(ConnectionSpec.MODERN_TLS.cipherSuites()); - cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA); - cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA); - - ConnectionSpec legacyTls = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) - .cipherSuites(cipherSuites.toArray(new CipherSuite[0])) - .build(); - builder.connectionSpecs(Arrays.asList(legacyTls, ConnectionSpec.CLEARTEXT)); - } - + SslClientSetup.installCertificates(builder); return builder; } diff --git a/core/src/play/java/de/danoeh/antennapod/core/ClientConfig.java b/core/src/play/java/de/danoeh/antennapod/core/ClientConfig.java index 0225c508a..48de7c6e1 100644 --- a/core/src/play/java/de/danoeh/antennapod/core/ClientConfig.java +++ b/core/src/play/java/de/danoeh/antennapod/core/ClientConfig.java @@ -2,10 +2,6 @@ package de.danoeh.antennapod.core; import android.content.Context; import android.util.Log; -import com.google.android.gms.common.GoogleApiAvailability; -import com.google.android.gms.common.GooglePlayServicesNotAvailableException; -import com.google.android.gms.common.GooglePlayServicesRepairableException; -import com.google.android.gms.security.ProviderInstaller; import de.danoeh.antennapod.core.cast.CastManager; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; @@ -15,6 +11,7 @@ import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.storage.PodDBAdapter; import de.danoeh.antennapod.core.util.NetworkUtils; import de.danoeh.antennapod.core.util.gui.NotificationUtils; +import de.danoeh.antennapod.net.ssl.SslProviderInstaller; import java.io.File; @@ -48,7 +45,7 @@ public class ClientConfig { UserPreferences.init(context); UsageStatistics.init(context); PlaybackPreferences.init(context); - installSslProvider(context); + SslProviderInstaller.install(context); NetworkUtils.init(context); // Don't initialize Cast-related logic unless it is enabled, to avoid the unnecessary // Google Play Service usage. @@ -64,15 +61,4 @@ public class ClientConfig { NotificationUtils.createChannels(context); initialized = true; } - - private static void installSslProvider(Context context) { - try { - ProviderInstaller.installIfNeeded(context); - } catch (GooglePlayServicesRepairableException e) { - e.printStackTrace(); - GoogleApiAvailability.getInstance().showErrorNotification(context, e.getConnectionStatusCode()); - } catch (GooglePlayServicesNotAvailableException e) { - e.printStackTrace(); - } - } } diff --git a/net/README.md b/net/README.md new file mode 100644 index 000000000..4d578407c --- /dev/null +++ b/net/README.md @@ -0,0 +1,3 @@ +# :net + +This folder contains modules that directly interact with the network. diff --git a/net/ssl/README.md b/net/ssl/README.md new file mode 100644 index 000000000..bf01f3ab6 --- /dev/null +++ b/net/ssl/README.md @@ -0,0 +1,3 @@ +# :net:ssl + +This module provides SSL backports and security provider implementations. diff --git a/net/ssl/build.gradle b/net/ssl/build.gradle new file mode 100644 index 000000000..92fb6cbd9 --- /dev/null +++ b/net/ssl/build.gradle @@ -0,0 +1,64 @@ +apply plugin: "com.android.library" + +android { + compileSdkVersion rootProject.ext.compileSdkVersion + + defaultConfig { + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + + multiDexEnabled false + + testApplicationId "de.danoeh.antennapod.core.tests" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile("proguard-android.txt") + } + debug { + // debug build has method count over 64k single-dex threshold. + // For building debug build to use on Android < 21 (pre-Android 5) devices, + // you need to manually change class + // de.danoeh.antennapod.PodcastApp to extend MultiDexApplication . + // See Issue #2813 + multiDexEnabled true + } + } + + flavorDimensions "market" + productFlavors { + free { + dimension "market" + } + play { + dimension "market" + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + testOptions { + unitTests { + includeAndroidResources = true + } + } + + lintOptions { + warningsAsErrors true + abortOnError true + } +} + +dependencies { + annotationProcessor "androidx.annotation:annotation:$annotationVersion" + implementation "androidx.appcompat:appcompat:$appcompatVersion" + implementation "com.squareup.okhttp3:okhttp:$okhttpVersion" + + playImplementation "com.google.android.gms:play-services-base:$playServicesVersion" + freeImplementation "org.conscrypt:conscrypt-android:$conscryptVersion" +} diff --git a/net/ssl/src/free/java/de/danoeh/antennapod/net/ssl/SslProviderInstaller.java b/net/ssl/src/free/java/de/danoeh/antennapod/net/ssl/SslProviderInstaller.java new file mode 100644 index 000000000..48b5690cc --- /dev/null +++ b/net/ssl/src/free/java/de/danoeh/antennapod/net/ssl/SslProviderInstaller.java @@ -0,0 +1,13 @@ +package de.danoeh.antennapod.net.ssl; + +import android.content.Context; +import org.conscrypt.Conscrypt; + +import java.security.Security; + +public class SslProviderInstaller { + public static void install(Context context) { + // Insert bundled conscrypt as highest security provider (overrides OS version). + Security.insertProviderAt(Conscrypt.newProvider(), 1); + } +} diff --git a/net/ssl/src/main/AndroidManifest.xml b/net/ssl/src/main/AndroidManifest.xml new file mode 100644 index 000000000..2acf91510 --- /dev/null +++ b/net/ssl/src/main/AndroidManifest.xml @@ -0,0 +1 @@ +<manifest package="de.danoeh.antennapod.net.ssl" /> diff --git a/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportCaCerts.java b/net/ssl/src/main/java/de/danoeh/antennapod/net/ssl/BackportCaCerts.java index 78c105e38..ecfc99e15 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportCaCerts.java +++ b/net/ssl/src/main/java/de/danoeh/antennapod/net/ssl/BackportCaCerts.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.ssl; +package de.danoeh.antennapod.net.ssl; public class BackportCaCerts { public static final String SECTIGO_USER_TRUST = "-----BEGIN CERTIFICATE-----\n" diff --git a/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportTrustManager.java b/net/ssl/src/main/java/de/danoeh/antennapod/net/ssl/BackportTrustManager.java index 81d2a0709..3a188b47a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportTrustManager.java +++ b/net/ssl/src/main/java/de/danoeh/antennapod/net/ssl/BackportTrustManager.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.ssl; +package de.danoeh.antennapod.net.ssl; import android.util.Log; diff --git a/core/src/main/java/de/danoeh/antennapod/core/ssl/CompositeX509TrustManager.java b/net/ssl/src/main/java/de/danoeh/antennapod/net/ssl/CompositeX509TrustManager.java index 7af96a492..16b2f0931 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/ssl/CompositeX509TrustManager.java +++ b/net/ssl/src/main/java/de/danoeh/antennapod/net/ssl/CompositeX509TrustManager.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.ssl; +package de.danoeh.antennapod.net.ssl; import javax.net.ssl.X509TrustManager; import java.security.cert.CertificateException; diff --git a/core/src/main/java/de/danoeh/antennapod/core/ssl/NoV1SslSocketFactory.java b/net/ssl/src/main/java/de/danoeh/antennapod/net/ssl/NoV1SslSocketFactory.java index 96a42f22d..0e31cda68 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/ssl/NoV1SslSocketFactory.java +++ b/net/ssl/src/main/java/de/danoeh/antennapod/net/ssl/NoV1SslSocketFactory.java @@ -1,6 +1,4 @@ -package de.danoeh.antennapod.core.ssl; - -import de.danoeh.antennapod.core.util.Flavors; +package de.danoeh.antennapod.net.ssl; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; @@ -22,7 +20,7 @@ public class NoV1SslSocketFactory extends SSLSocketFactory { try { SSLContext sslContext; - if (Flavors.FLAVOR == Flavors.FREE) { + if (BuildConfig.FLAVOR.equals("free")) { // Free flavor (bundles modern conscrypt): support for TLSv1.3 is guaranteed. sslContext = SSLContext.getInstance("TLSv1.3"); } else { @@ -84,7 +82,7 @@ public class NoV1SslSocketFactory extends SSLSocketFactory { } private void configureSocket(SSLSocket s) { - if (Flavors.FLAVOR == Flavors.FREE) { + if (BuildConfig.FLAVOR.equals("free")) { // Free flavor (bundles modern conscrypt): TLSv1.3 and modern cipher suites are // guaranteed. Protocols older than TLSv1.2 are now deprecated and can be disabled. s.setEnabledProtocols(new String[] { "TLSv1.3", "TLSv1.2" }); diff --git a/net/ssl/src/main/java/de/danoeh/antennapod/net/ssl/SslClientSetup.java b/net/ssl/src/main/java/de/danoeh/antennapod/net/ssl/SslClientSetup.java new file mode 100644 index 000000000..666010d2f --- /dev/null +++ b/net/ssl/src/main/java/de/danoeh/antennapod/net/ssl/SslClientSetup.java @@ -0,0 +1,37 @@ +package de.danoeh.antennapod.net.ssl; + +import android.os.Build; +import okhttp3.CipherSuite; +import okhttp3.ConnectionSpec; +import okhttp3.OkHttpClient; + +import javax.net.ssl.X509TrustManager; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class SslClientSetup { + public static void installCertificates(OkHttpClient.Builder builder) { + if (BuildConfig.FLAVOR.equals("free")) { + // The Free flavor bundles a modern conscrypt (security provider), so CustomSslSocketFactory + // is only used to make sure that modern protocols (TLSv1.3 and TLSv1.2) are enabled and + // that old, deprecated, protocols (like SSLv3, TLSv1.0 and TLSv1.1) are disabled. + X509TrustManager trustManager = BackportTrustManager.create(); + builder.sslSocketFactory(new NoV1SslSocketFactory(trustManager), trustManager); + } else if (Build.VERSION.SDK_INT < 21) { + X509TrustManager trustManager = BackportTrustManager.create(); + builder.sslSocketFactory(new NoV1SslSocketFactory(trustManager), trustManager); + + // workaround for Android 4.x for certain web sites. + // see: https://github.com/square/okhttp/issues/4053#issuecomment-402579554 + List<CipherSuite> cipherSuites = new ArrayList<>(ConnectionSpec.MODERN_TLS.cipherSuites()); + cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA); + cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA); + + ConnectionSpec legacyTls = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) + .cipherSuites(cipherSuites.toArray(new CipherSuite[0])) + .build(); + builder.connectionSpecs(Arrays.asList(legacyTls, ConnectionSpec.CLEARTEXT)); + } + } +} diff --git a/net/ssl/src/play/java/de/danoeh/antennapod/net/ssl/SslProviderInstaller.java b/net/ssl/src/play/java/de/danoeh/antennapod/net/ssl/SslProviderInstaller.java new file mode 100644 index 000000000..6c89df5ec --- /dev/null +++ b/net/ssl/src/play/java/de/danoeh/antennapod/net/ssl/SslProviderInstaller.java @@ -0,0 +1,20 @@ +package de.danoeh.antennapod.net.ssl; + +import android.content.Context; +import com.google.android.gms.common.GoogleApiAvailability; +import com.google.android.gms.common.GooglePlayServicesNotAvailableException; +import com.google.android.gms.common.GooglePlayServicesRepairableException; +import com.google.android.gms.security.ProviderInstaller; + +public class SslProviderInstaller { + public static void install(Context context) { + try { + ProviderInstaller.installIfNeeded(context); + } catch (GooglePlayServicesRepairableException e) { + e.printStackTrace(); + GoogleApiAvailability.getInstance().showErrorNotification(context, e.getConnectionStatusCode()); + } catch (GooglePlayServicesNotAvailableException e) { + e.printStackTrace(); + } + } +} diff --git a/settings.gradle b/settings.gradle index 0298c7b2a..a87de1afa 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,5 @@ include ':app' include ':core' +include ':net:ssl' include ':ui:app-start-intent' include ':ui:common' |