Specify ConnectionSpecs for domain fronts

// FREEBIE
This commit is contained in:
Moxie Marlinspike
2017-01-11 15:37:51 -08:00
parent ec5ac44cd3
commit 94a29e375f
5 changed files with 153 additions and 24 deletions

View File

@@ -16,12 +16,15 @@
*/
package org.thoughtcrime.securesms;
import android.app.Application;
import android.content.Context;
import android.os.AsyncTask;
import android.os.StrictMode;
import android.os.StrictMode.ThreadPolicy;
import android.os.StrictMode.VmPolicy;
import android.support.multidex.MultiDexApplication;
import android.util.Log;
import com.google.android.gms.security.ProviderInstaller;
import org.thoughtcrime.securesms.crypto.PRNGFixes;
import org.thoughtcrime.securesms.dependencies.AxolotlStorageModule;
@@ -57,6 +60,8 @@ import dagger.ObjectGraph;
*/
public class ApplicationContext extends MultiDexApplication implements DependencyInjector {
private static final String TAG = ApplicationContext.class.getName();
private ExpiringMessageManager expiringMessageManager;
private JobManager jobManager;
private ObjectGraph objectGraph;
@@ -79,6 +84,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
initializeGcmCheck();
initializeSignedPreKeyCheck();
initializePeriodicTasks();
initializeCircumvention();
}
@Override
@@ -159,4 +165,20 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
DirectoryRefreshListener.schedule(this);
}
private void initializeCircumvention() {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
if (new SignalServiceNetworkAccess(ApplicationContext.this).isCensored(ApplicationContext.this)) {
try {
ProviderInstaller.installIfNeeded(ApplicationContext.this);
} catch (Throwable t) {
Log.w(TAG, t);
}
}
return null;
}
}.execute();
}
}

View File

@@ -33,7 +33,6 @@ import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.util.CredentialsProvider;
import org.whispersystems.signalservice.internal.push.SignalServiceUrl;
import dagger.Module;
import dagger.Provides;
@@ -61,16 +60,16 @@ import dagger.Provides;
RotateSignedPreKeyJob.class})
public class SignalCommunicationModule {
private final Context context;
private final SignalServiceUrl[] urls;
private final Context context;
private final SignalServiceNetworkAccess networkAccess;
public SignalCommunicationModule(Context context, SignalServiceNetworkAccess networkAccess) {
this.context = context;
this.urls = networkAccess.getConfiguration(context);
this.context = context;
this.networkAccess = networkAccess;
}
@Provides SignalServiceAccountManager provideSignalAccountManager() {
return new SignalServiceAccountManager(urls,
return new SignalServiceAccountManager(networkAccess.getConfiguration(context),
TextSecurePreferences.getLocalNumber(context),
TextSecurePreferences.getPushServerPassword(context),
BuildConfig.USER_AGENT);
@@ -81,7 +80,7 @@ public class SignalCommunicationModule {
return new SignalMessageSenderFactory() {
@Override
public SignalServiceMessageSender create() {
return new SignalServiceMessageSender(urls,
return new SignalServiceMessageSender(networkAccess.getConfiguration(context),
TextSecurePreferences.getLocalNumber(context),
TextSecurePreferences.getPushServerPassword(context),
new SignalProtocolStoreImpl(context),
@@ -93,7 +92,7 @@ public class SignalCommunicationModule {
}
@Provides SignalServiceMessageReceiver provideSignalMessageReceiver() {
return new SignalServiceMessageReceiver(urls,
return new SignalServiceMessageReceiver(networkAccess.getConfiguration(context),
new DynamicCredentialsProvider(context),
BuildConfig.USER_AGENT);
}

View File

@@ -1,6 +1,13 @@
package org.thoughtcrime.securesms.push;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.util.Log;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.common.GooglePlayServicesRepairableException;
import com.google.android.gms.security.ProviderInstaller;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@@ -9,6 +16,8 @@ import org.whispersystems.signalservice.internal.push.SignalServiceUrl;
public class AccountManagerFactory {
private static final String TAG = AccountManagerFactory.class.getName();
public static SignalServiceAccountManager createManager(Context context) {
return new SignalServiceAccountManager(new SignalServiceNetworkAccess(context).getConfiguration(context),
TextSecurePreferences.getLocalNumber(context),
@@ -16,7 +25,21 @@ public class AccountManagerFactory {
BuildConfig.USER_AGENT);
}
public static SignalServiceAccountManager createManager(Context context, String number, String password) {
public static SignalServiceAccountManager createManager(final Context context, String number, String password) {
if (new SignalServiceNetworkAccess(context).isCensored(number)) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
try {
ProviderInstaller.installIfNeeded(context);
} catch (Throwable t) {
Log.w(TAG, t);
}
return null;
}
}.execute();
}
return new SignalServiceAccountManager(new SignalServiceNetworkAccess(context).getConfiguration(number),
number, password, BuildConfig.USER_AGENT);
}

View File

@@ -2,6 +2,8 @@ package org.thoughtcrime.securesms.push;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@@ -11,41 +13,118 @@ import org.whispersystems.signalservice.internal.push.SignalServiceUrl;
import java.util.HashMap;
import java.util.Map;
import okhttp3.CipherSuite;
import okhttp3.ConnectionSpec;
import okhttp3.TlsVersion;
public class SignalServiceNetworkAccess {
private static final String TAG = SignalServiceNetworkAccess.class.getName();
private static final String APPSPOT_REFLECTOR_HOST = "signal-reflector-meek.appspot.com";
private static final ConnectionSpec GMAPS_CONNECTION_SPEC = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.cipherSuites(CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384,
CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA)
.supportsTlsExtensions(true)
.build();
private static final ConnectionSpec GMAIL_CONNECTION_SPEC = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.cipherSuites(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384,
CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_RSA_WITH_RC4_128_SHA,
CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
.supportsTlsExtensions(true)
.build();
private static final ConnectionSpec PLAY_CONNECTION_SPEC = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.cipherSuites(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_RSA_WITH_RC4_128_SHA,
CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
.supportsTlsExtensions(true)
.build();
private final Map<String, SignalServiceUrl[]> censorshipConfiguration;
private final String[] censoredCountries;
private final SignalServiceUrl[] uncensoredConfiguration;
public SignalServiceNetworkAccess(Context context) {
final TrustStore googleTrustStore = new GoogleFrontingTrustStore(context);
final SignalServiceUrl baseGoogle = new SignalServiceUrl("https://www.google.com", APPSPOT_REFLECTOR_HOST, googleTrustStore);
final SignalServiceUrl baseAndroid = new SignalServiceUrl("https://android.clients.google.com", APPSPOT_REFLECTOR_HOST, googleTrustStore);
final SignalServiceUrl baseGoogle = new SignalServiceUrl("https://www.google.com", APPSPOT_REFLECTOR_HOST, googleTrustStore, GMAIL_CONNECTION_SPEC);
final SignalServiceUrl baseAndroid = new SignalServiceUrl("https://android.clients.google.com", APPSPOT_REFLECTOR_HOST, googleTrustStore, PLAY_CONNECTION_SPEC);
final SignalServiceUrl mapsOneAndroid = new SignalServiceUrl("https://clients3.google.com", APPSPOT_REFLECTOR_HOST, googleTrustStore, GMAPS_CONNECTION_SPEC);
final SignalServiceUrl mapsTwoAndroid = new SignalServiceUrl("https://clients4.google.com", APPSPOT_REFLECTOR_HOST, googleTrustStore, GMAPS_CONNECTION_SPEC);
final SignalServiceUrl mailAndroid = new SignalServiceUrl("https://mail.google.com", APPSPOT_REFLECTOR_HOST, googleTrustStore, GMAIL_CONNECTION_SPEC);
this.censorshipConfiguration = new HashMap<String, SignalServiceUrl[]>() {{
put("+20", new SignalServiceUrl[] {new SignalServiceUrl("https://www.google.com.eg",
APPSPOT_REFLECTOR_HOST,
googleTrustStore),
baseAndroid});
googleTrustStore, GMAIL_CONNECTION_SPEC),
baseAndroid, mapsOneAndroid, mapsTwoAndroid, mailAndroid});
put("+971", new SignalServiceUrl[] {new SignalServiceUrl("https://www.google.ae",
APPSPOT_REFLECTOR_HOST,
googleTrustStore),
baseAndroid, baseGoogle});
googleTrustStore, GMAIL_CONNECTION_SPEC),
baseAndroid, baseGoogle, mapsOneAndroid, mapsTwoAndroid, mailAndroid});
put("+53", new SignalServiceUrl[] {new SignalServiceUrl("https://www.google.com.cu",
APPSPOT_REFLECTOR_HOST,
googleTrustStore),
baseAndroid, baseGoogle});
googleTrustStore, GMAIL_CONNECTION_SPEC),
baseAndroid, baseGoogle, mapsOneAndroid, mapsTwoAndroid, mailAndroid});
put("+968", new SignalServiceUrl[] {new SignalServiceUrl("https://www.google.com.om",
APPSPOT_REFLECTOR_HOST,
googleTrustStore),
baseAndroid, baseGoogle});
googleTrustStore, GMAIL_CONNECTION_SPEC),
baseAndroid, baseGoogle, mapsOneAndroid, mapsTwoAndroid, mailAndroid});
}};
this.uncensoredConfiguration = new SignalServiceUrl[] {
@@ -60,7 +139,9 @@ public class SignalServiceNetworkAccess {
return getConfiguration(localNumber);
}
public SignalServiceUrl[] getConfiguration(String localNumber) {
public SignalServiceUrl[] getConfiguration(@Nullable String localNumber) {
if (localNumber == null) return this.uncensoredConfiguration;
for (String censoredRegion : this.censoredCountries) {
if (localNumber.startsWith(censoredRegion)) {
return this.censorshipConfiguration.get(censoredRegion);
@@ -74,4 +155,8 @@ public class SignalServiceNetworkAccess {
return getConfiguration(context) != this.uncensoredConfiguration;
}
public boolean isCensored(String number) {
return getConfiguration(number) != this.uncensoredConfiguration;
}
}