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

@ -57,7 +57,7 @@ dependencies {
compile 'org.whispersystems:jobmanager:1.0.2'
compile 'org.whispersystems:libpastelog:1.0.7'
compile 'org.whispersystems:signal-service-android:2.4.6'
compile 'org.whispersystems:signal-service-android:2.4.7'
compile 'me.leolin:ShortcutBadger:1.1.0-WS1'
compile 'se.emilsjolander:stickylistheaders:2.7.0'
@ -123,7 +123,7 @@ dependencyVerification {
'com.google.android.gms:play-services-places:abf3a4a3b146ec7e6e753be62775e512868cf37d6f88ffe2d81167b33b57132b',
'org.whispersystems:jobmanager:506f679fc2fcf7bb6d10f00f41d6f6ea0abf75c70dc95b913398661ad538a181',
'org.whispersystems:libpastelog:bb331d9a98240fc139101128ba836c1edec3c40e000597cdbb29ebf4cbf34d88',
'org.whispersystems:signal-service-android:737c3e8e572bd5f149d2202d768c4e0f50205f85794e05fee4045d3dfca1fc27',
'org.whispersystems:signal-service-android:c7835376e426d4789444f1e8c02c3528fb57f148441d8f96d5d595244d7120a2',
'me.leolin:ShortcutBadger:3142d017234bfa0cdd69ccded7cc5ea63f13b97574803c8c616c9bbeaad33ad9',
'se.emilsjolander:stickylistheaders:a08ca948aa6b220f09d82f16bbbac395f6b78897e9eeac6a9f0b0ba755928eeb',
'com.jpardogo.materialtabstrip:library:c6ef812fba4f74be7dc4a905faa4c2908cba261a94c13d4f96d5e67e4aad4aaa',
@ -157,7 +157,7 @@ dependencyVerification {
'com.google.android.gms:play-services-basement:95dd882c5ffba15b9a99de3fefb05d3a01946623af67454ca00055d222f85a8d',
'com.google.android.gms:play-services-iid:54e919f9957b8b7820da7ee9b83471d00d0cac1cf08ddea8b5b41aea80bb1a70',
'org.whispersystems:signal-protocol-android:1b4b9d557c8eaf861797ff683990d482d4aa8e9f23d9b17ff0cc67a02f38cb19',
'org.whispersystems:signal-service-java:c9b9c8585ba60e391ff08dce2351068b576d3c55531fc46141dfdae8dea20bff',
'org.whispersystems:signal-service-java:60aad86f4af3e93220c980e3ac9b75015e1f65b6ab02418492e9c6c1d1dfe0be',
'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a',
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',

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;
}
}