diff --git a/app/src/main/java/org/thoughtcrime/securesms/push/DomainFrontingDigicertTrustStore.java b/app/src/main/java/org/thoughtcrime/securesms/push/DomainFrontingDigicertTrustStore.java new file mode 100644 index 00000000000..b5216a87e1c --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/push/DomainFrontingDigicertTrustStore.java @@ -0,0 +1,28 @@ +package org.thoughtcrime.securesms.push; + +import android.content.Context; + +import org.thoughtcrime.securesms.R; +import org.whispersystems.signalservice.api.push.TrustStore; + +import java.io.InputStream; + +public class DomainFrontingDigicertTrustStore implements TrustStore { + + private final Context context; + + public DomainFrontingDigicertTrustStore(Context context) { + this.context = context.getApplicationContext(); + } + + @Override + public InputStream getKeyStoreInputStream() { + return context.getResources().openRawResource(R.raw.censorship_digicert); + } + + @Override + public String getKeyStorePassword() { + return "whisper"; + } + +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/push/SignalServiceNetworkAccess.java b/app/src/main/java/org/thoughtcrime/securesms/push/SignalServiceNetworkAccess.java index dd62cb00d94..b7a6db3e932 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/push/SignalServiceNetworkAccess.java +++ b/app/src/main/java/org/thoughtcrime/securesms/push/SignalServiceNetworkAccess.java @@ -3,6 +3,8 @@ import android.content.Context; +import com.annimon.stream.Stream; + import androidx.annotation.Nullable; import org.thoughtcrime.securesms.BuildConfig; @@ -30,6 +32,8 @@ import java.util.List; import java.util.Map; +import javax.net.ssl.SSLContext; + import okhttp3.CipherSuite; import okhttp3.ConnectionSpec; import okhttp3.Dns; @@ -47,8 +51,15 @@ public class SignalServiceNetworkAccess { private static final String COUNTRY_CODE_UAE = "+971"; private static final String COUNTRY_CODE_OMAN = "+968"; private static final String COUNTRY_CODE_QATAR = "+974"; + private static final String COUNTRY_CODE_IRAN = "+98"; private static final String SERVICE_REFLECTOR_HOST = "europe-west1-signal-cdn-reflector.cloudfunctions.net"; + private static final String SERVICE_FASTLY_HOST = "textsecure-service.whispersystems.org.global.prod.fastly.net"; + private static final String STORAGE_FASTLY_HOST = "storage.signal.org.global.prod.fastly.net"; + private static final String CDN_FASTLY_HOST = "cdn.signal.org.global.prod.fastly.net"; + private static final String CDN2_FASTLY_HOST = "cdn2.signal.org.global.prod.fastly.net"; + private static final String DIRECTORY_FASTLY_HOST = "api.directory.signal.org.global.prod.fastly.net"; + private static final String KBS_FASTLY_HOST = "api.backup.signal.org.global.prod.fastly.net"; private static final ConnectionSpec GMAPS_CONNECTION_SPEC = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) .tlsVersions(TlsVersion.TLS_1_2) @@ -97,6 +108,7 @@ public class SignalServiceNetworkAccess { .supportsTlsExtensions(true) .build(); + private static final ConnectionSpec APP_CONNECTION_SPEC = ConnectionSpec.MODERN_TLS; private final Map censorshipConfiguration; private final String[] censoredCountries; @@ -145,6 +157,7 @@ public SignalServiceNetworkAccess(Context context) { final SignalContactDiscoveryUrl omanGoogleDiscovery = new SignalContactDiscoveryUrl("https://www.google.com.om/directory", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC); final SignalContactDiscoveryUrl qatarGoogleDiscovery = new SignalContactDiscoveryUrl("https://www.google.com.qa/directory", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC); + final SignalKeyBackupServiceUrl baseGoogleKbs = new SignalKeyBackupServiceUrl("https://www.google.com/backup", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC); final SignalKeyBackupServiceUrl baseAndroidKbs = new SignalKeyBackupServiceUrl("https://android.clients.google.com/backup", SERVICE_REFLECTOR_HOST, trustStore, PLAY_CONNECTION_SPEC); final SignalKeyBackupServiceUrl mapsOneAndroidKbs = new SignalKeyBackupServiceUrl("https://clients3.google.com/backup", SERVICE_REFLECTOR_HOST, trustStore, GMAPS_CONNECTION_SPEC); @@ -165,6 +178,8 @@ public SignalServiceNetworkAccess(Context context) { final SignalStorageUrl omanGoogleStorage = new SignalStorageUrl("https://www.google.com.om/storage", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC); final SignalStorageUrl qatarGoogleStorage = new SignalStorageUrl("https://www.google.com.qa/storage", SERVICE_REFLECTOR_HOST, trustStore, GMAIL_CONNECTION_SPEC); + final String[] fastUrls = {"https://cdn.sstatic.net", "https://github.githubassets.com", "https://pinterest.com", "https://open.scdn.co", "https://www.redditstatic.com"}; + final List interceptors = Arrays.asList(new StandardUserAgentInterceptor(), new RemoteDeprecationDetectorInterceptor(), new DeprecatedClientPreventionInterceptor()); final Optional dns = Optional.of(DNS); @@ -177,6 +192,7 @@ public SignalServiceNetworkAccess(Context context) { } this.censorshipConfiguration = new HashMap() {{ + put(COUNTRY_CODE_EGYPT, new SignalServiceConfiguration(new SignalServiceUrl[] {egyptGoogleService, baseGoogleService, baseAndroidService, mapsOneAndroidService, mapsTwoAndroidService, mailAndroidService}, makeSignalCdnUrlMapFor(new SignalCdnUrl[] {egyptGoogleCdn, baseAndroidCdn, baseGoogleCdn, mapsOneAndroidCdn, mapsTwoAndroidCdn, mailAndroidCdn, mailAndroidCdn}, new SignalCdnUrl[] {egyptGoogleCdn2, baseAndroidCdn2, baseGoogleCdn2, mapsOneAndroidCdn2, mapsTwoAndroidCdn2, mailAndroidCdn2, mailAndroidCdn2}), @@ -221,6 +237,17 @@ public SignalServiceNetworkAccess(Context context) { dns, Optional.absent(), zkGroupServerPublicParams)); + + put(COUNTRY_CODE_IRAN, new SignalServiceConfiguration(Stream.of(fastUrls).map(url -> new SignalServiceUrl(url, SERVICE_FASTLY_HOST, new DomainFrontingDigicertTrustStore(context), APP_CONNECTION_SPEC)).toArray(SignalServiceUrl[]::new), + makeSignalCdnUrlMapFor(Stream.of(fastUrls).map(url -> new SignalCdnUrl(url, CDN_FASTLY_HOST, new DomainFrontingDigicertTrustStore(context), APP_CONNECTION_SPEC)).toArray(SignalCdnUrl[]::new), + Stream.of(fastUrls).map(url -> new SignalCdnUrl(url, CDN2_FASTLY_HOST, new DomainFrontingDigicertTrustStore(context), APP_CONNECTION_SPEC)).toArray(SignalCdnUrl[]::new)), + Stream.of(fastUrls).map(url -> new SignalContactDiscoveryUrl(url, DIRECTORY_FASTLY_HOST, new DomainFrontingDigicertTrustStore(context), APP_CONNECTION_SPEC)).toArray(SignalContactDiscoveryUrl[]::new), + Stream.of(fastUrls).map(url -> new SignalKeyBackupServiceUrl(url, KBS_FASTLY_HOST, new DomainFrontingDigicertTrustStore(context), APP_CONNECTION_SPEC)).toArray(SignalKeyBackupServiceUrl[]::new), + Stream.of(fastUrls).map(url -> new SignalStorageUrl(url, STORAGE_FASTLY_HOST, new DomainFrontingDigicertTrustStore(context), APP_CONNECTION_SPEC)).toArray(SignalStorageUrl[]::new), + interceptors, + dns, + Optional.absent(), + zkGroupServerPublicParams)); }}; this.uncensoredConfiguration = new SignalServiceConfiguration(new SignalServiceUrl[] {new SignalServiceUrl(BuildConfig.SIGNAL_URL, new SignalServiceTrustStore(context))}, @@ -248,7 +275,7 @@ public SignalServiceConfiguration getConfiguration(@Nullable String localNumber) } if (SignalStore.internalValues().forcedCensorship()) { - return this.censorshipConfiguration.get(COUNTRY_CODE_QATAR); + return this.censorshipConfiguration.get(COUNTRY_CODE_IRAN); } for (String censoredRegion : this.censoredCountries) { diff --git a/app/src/main/res/raw/censorship_digicert.store b/app/src/main/res/raw/censorship_digicert.store new file mode 100644 index 00000000000..e4fb8c6fe5c Binary files /dev/null and b/app/src/main/res/raw/censorship_digicert.store differ