Merge pull request #4077 from Slinger/conscrypt_bundle

Bundle a modern Security Provider (Conscrypt) in the Free builds.
This commit is contained in:
H. Lehmann 2020-10-04 15:21:18 +02:00 committed by GitHub
commit e1ff4c8763
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 47 additions and 4 deletions

View File

@ -67,6 +67,9 @@ project.ext {
iconifyVersion = "2.2.2" iconifyVersion = "2.2.2"
audioPlayerVersion = "v2.0.0" audioPlayerVersion = "v2.0.0"
// Only used for free builds. This version should be updated regularly.
conscryptVersion = "2.4.0"
// Google Play build // Google Play build
wearableSupportVersion = "2.6.0" wearableSupportVersion = "2.6.0"

View File

@ -91,6 +91,9 @@ dependencies {
System.out.println("core: free build hack, skipping some dependencies") System.out.println("core: free build hack, skipping some dependencies")
} }
// bundle conscrypt with free builds
freeImplementation "org.conscrypt:conscrypt-android:$conscryptVersion"
testImplementation "org.awaitility:awaitility:$awaitilityVersion" testImplementation "org.awaitility:awaitility:$awaitilityVersion"
testImplementation 'junit:junit:4.13' testImplementation 'junit:junit:4.13'
testImplementation 'org.mockito:mockito-core:1.10.19' testImplementation 'org.mockito:mockito-core:1.10.19'

View File

@ -1,6 +1,8 @@
package de.danoeh.antennapod.core; package de.danoeh.antennapod.core;
import android.content.Context; import android.content.Context;
import java.security.Security;
import org.conscrypt.Conscrypt;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; import de.danoeh.antennapod.core.preferences.SleepTimerPreferences;
@ -53,6 +55,7 @@ public class ClientConfig {
} }
private static void installSslProvider(Context context) { private static void installSslProvider(Context context) {
// ProviderInstaller is a closed-source Google library // Insert bundled conscrypt as highest security provider (overrides OS version).
Security.insertProviderAt(Conscrypt.newProvider(), 1);
} }
} }

View File

@ -34,6 +34,7 @@ import javax.net.ssl.X509TrustManager;
import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.UserAgentInterceptor; import de.danoeh.antennapod.core.service.UserAgentInterceptor;
import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.Flavors;
import okhttp3.Cache; import okhttp3.Cache;
import okhttp3.CipherSuite; import okhttp3.CipherSuite;
import okhttp3.ConnectionSpec; import okhttp3.ConnectionSpec;
@ -149,7 +150,16 @@ public class AntennapodHttpClient {
}); });
} }
} }
if (Build.VERSION.SDK_INT < 21) {
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.
builder.sslSocketFactory(new CustomSslSocketFactory(), trustManager());
} else if (Build.VERSION.SDK_INT < 21) {
// The Play flavor can not be assumed to have a modern security provider, so for Android
// older than 5.0 CustomSslSocketFactory is used to enable all possible protocols (modern
// and deprecated). And we explicitly enable deprecated cipher suites disabled by default.
builder.sslSocketFactory(new CustomSslSocketFactory(), trustManager()); builder.sslSocketFactory(new CustomSslSocketFactory(), trustManager());
// workaround for Android 4.x for certain web sites. // workaround for Android 4.x for certain web sites.
@ -178,6 +188,9 @@ public class AntennapodHttpClient {
} }
} }
/**
* Reimplements default trust manager (required for calling sslSocketFactory).
*/
private static X509TrustManager trustManager() { private static X509TrustManager trustManager() {
try { try {
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
@ -199,13 +212,26 @@ public class AntennapodHttpClient {
AntennapodHttpClient.cacheDirectory = cacheDirectory; AntennapodHttpClient.cacheDirectory = cacheDirectory;
} }
/**
* Used to disable deprecated protocols and explicitly enable TLSv1.3 and TLSv1.2, or to enable
* all protocols (including deprecated) up to TLSv1.2, depending on build flavor (Free or Play).
*/
private static class CustomSslSocketFactory extends SSLSocketFactory { private static class CustomSslSocketFactory extends SSLSocketFactory {
private SSLSocketFactory factory; private SSLSocketFactory factory;
public CustomSslSocketFactory() { public CustomSslSocketFactory() {
try { try {
SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); SSLContext sslContext;
if (Flavors.FLAVOR == Flavors.FREE) {
// Free flavor (bundles modern conscrypt): support for TLSv1.3 is guaranteed.
sslContext = SSLContext.getInstance("TLSv1.3");
} else {
// Play flavor (security provider can vary): only TLSv1.2 is guaranteed.
sslContext = SSLContext.getInstance("TLSv1.2");
}
sslContext.init(null, null, null); sslContext.init(null, null, null);
factory= sslContext.getSocketFactory(); factory= sslContext.getSocketFactory();
} catch(GeneralSecurityException e) { } catch(GeneralSecurityException e) {
@ -260,7 +286,15 @@ public class AntennapodHttpClient {
} }
private void configureSocket(SSLSocket s) { private void configureSocket(SSLSocket s) {
s.setEnabledProtocols(new String[] { "TLSv1.2", "TLSv1.1", "TLSv1" } ); if (Flavors.FLAVOR == Flavors.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" });
} else {
// Play flavor (security provider can vary): only TLSv1.2 is guaranteed, supported
// cipher suites may vary. Old protocols might be necessary to keep things working.
s.setEnabledProtocols(new String[] { "TLSv1.2", "TLSv1.1", "TLSv1" });
}
} }
} }