diff options
Diffstat (limited to 'app/src/main')
33 files changed, 486 insertions, 175 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5d221529..cbc06854 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -33,7 +33,9 @@ <application android:name=".base.BitmaskApp" - android:allowBackup="true" + android:allowBackup="false" + android:fullBackupContent="false" + android:dataExtractionRules="@xml/data_extraction_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:extractNativeLibs="true" @@ -82,6 +84,7 @@ android:name=".base.StartActivity" android:label="@string/app_name" android:launchMode="singleTop" + android:taskAffinity="" android:theme="@style/SplashTheme" android:exported="true" > diff --git a/app/src/main/aidl/de/blinkt/openvpn/api/ExternalCertificateProvider.aidl b/app/src/main/aidl/de/blinkt/openvpn/api/ExternalCertificateProvider.aidl index c6db965b..1f77b15f 100644 --- a/app/src/main/aidl/de/blinkt/openvpn/api/ExternalCertificateProvider.aidl +++ b/app/src/main/aidl/de/blinkt/openvpn/api/ExternalCertificateProvider.aidl @@ -1,16 +1,16 @@ // ExternalCertificateProvider.aidl package de.blinkt.openvpn.api; - /* * This is very simple interface that is specialised to have only the minimal set of crypto * operation that are needed for OpenVPN to authenticate with an external certificate */ interface ExternalCertificateProvider { /** + * @deprecated use {@link #getSignedDataWithExtra} instead * Requests signing the data with RSA/ECB/PKCS1PADDING * for RSA certficate and with NONEwithECDSA for EC certificates - * @parm alias the parameter that + * @param alias user certificate identifier */ byte[] getSignedData(in String alias, in byte[] data); @@ -36,4 +36,33 @@ interface ExternalCertificateProvider { * */ Bundle getCertificateMetaData(in String alias); + + /** + * Requests signing the data with RSA/ECB/nopadding, RSA/ECB/PKCS1PADDING or PKCS1PSSPADDING + * for RSA certficate and with NONEwithECDSA for EC certificates + * @param alias user certificate identifier + * @param data the data to be signed + * @param extra additional information. + * Should contain the following keys: + * <ul> + * <li>int key "de.blinkt.openvpn.api.RSA_PADDING_TYPE", may be set as: + * <ul> + * <li>0 - for RSA/ECB/nopadding + * <li>1 - for RSA/ECB/PKCS1PADDING + * <li>2 - for PKCS1PSSPADDING + * </ul> + * <li>string key "de.blinkt.openvpn.api.SALTLEN", may be set as: + * <ul> + * <li>"digest" - use the same salt size as the hash to sign + * <li>"max" - use maximum possible saltlen which is '(nbits-1)/8 - hlen - 2'. Here + * 'nbits' is the number of bits in the key modulus and 'hlen' is the size in octets of + * the hash. See: RFC 8017 sec 8.1.1 and 9.1.1. + * </ul> + * <li>boolean key "de.blinkt.openvpn.api.NEEDS_DIGEST", indicating that the data should be + * hashed before signing or not + * <li>string key "de.blinkt.openvpn.api.DIGEST", the short common digest algorithm name to + * use (such as SHA256, SHA224, etc.) + * </ul> + */ + byte[] getSignedDataWithExtra(in String alias, in byte[] data, in Bundle extra); } diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java index 9baac195..780ac9d8 100644 --- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java +++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java @@ -15,6 +15,7 @@ import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Build; +import android.os.Bundle; import android.preference.PreferenceManager; import android.security.KeyChain; import android.security.KeyChainException; @@ -37,7 +38,9 @@ import java.io.FileWriter; import java.io.IOException; import java.io.Serializable; import java.io.StringWriter; +import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; +import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Signature; @@ -45,6 +48,9 @@ import java.security.SignatureException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateKey; +import java.security.spec.MGF1ParameterSpec; +import java.security.spec.PSSParameterSpec; import java.util.Collection; import java.util.HashSet; import java.util.Locale; @@ -58,6 +64,7 @@ import javax.crypto.NoSuchPaddingException; import de.blinkt.openvpn.core.ExtAuthHelper; import de.blinkt.openvpn.core.NativeUtils; +import de.blinkt.openvpn.core.OpenVPNManagement; import de.blinkt.openvpn.core.OpenVPNService; import de.blinkt.openvpn.core.OrbotHelper; import de.blinkt.openvpn.core.PasswordCache; @@ -69,6 +76,7 @@ import de.blinkt.openvpn.core.connection.Connection; import de.blinkt.openvpn.core.connection.ConnectionAdapter; import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.base.models.ProviderObservable; public class VpnProfile implements Serializable, Cloneable { // Note that this class cannot be moved to core where it belongs since @@ -104,6 +112,10 @@ public class VpnProfile implements Serializable, Cloneable { private static final long serialVersionUID = 7085688938959334563L; private static final int AUTH_RETRY_NONE_KEEP = 1; private static final int AUTH_RETRY_INTERACT = 3; + private static final String EXTRA_RSA_PADDING_TYPE = "de.blinkt.openvpn.api.RSA_PADDING_TYPE"; + private static final String EXTRA_SALTLEN = "de.blinkt.openvpn.api.SALTLEN"; + private static final String EXTRA_NEEDS_DIGEST = "de.blinkt.openvpn.api.NEEDS_DIGEST"; + private static final String EXTRA_DIGEST = "de.blinkt.openvpn.api.DIGEST"; public static String DEFAULT_DNS1 = "8.8.8.8"; public static String DEFAULT_DNS2 = "8.8.4.4"; // variable named wrong and should haven beeen transient @@ -431,8 +443,9 @@ public class VpnProfile implements Serializable, Cloneable { cfg.append(insertFileData("ca", mCaFilename)); // Client Cert + Key - cfg.append(insertFileData("key", mClientKeyFilename)); cfg.append(insertFileData("cert", mClientCertFilename)); + mPrivateKey = ProviderObservable.getInstance().getCurrentProvider().getRSAPrivateKey(); + cfg.append("management-external-key nopadding pkcs1 pss digest\n"); break; case VpnProfile.TYPE_USERPASS_PKCS12: @@ -458,7 +471,7 @@ public class VpnProfile implements Serializable, Cloneable { if (!TextUtils.isEmpty(ks[1])) cfg.append("<extra-certs>\n").append(ks[1]).append("\n</extra-certs>\n"); cfg.append("<cert>\n").append(ks[2]).append("\n</cert>\n"); - cfg.append("management-external-key nopadding\n"); + cfg.append("management-external-key nopadding pkcs1 pss digest\n"); } else { cfg.append(context.getString(R.string.keychain_access)).append("\n"); } @@ -750,7 +763,7 @@ public class VpnProfile implements Serializable, Cloneable { public Intent prepareStartService(Context context) { Intent intent = getStartServiceIntent(context); - // TODO: Handle this?! + // This can remain outcommented for now, Bitmask uses VpnProfile.TYPE_CERTIFICATE // if (mAuthenticationType == VpnProfile.TYPE_KEYSTORE || mAuthenticationType == VpnProfile.TYPE_USERPASS_KEYSTORE) { // if (getKeyStoreCertificates(context) == null) // return null; @@ -832,6 +845,14 @@ public class VpnProfile implements Serializable, Cloneable { return ExtAuthHelper.getCertificateChain(context, mExternalAuthenticator, mAlias); } + /** + * returns an array certificates, depending on the profile type either from the keychain or an external cert provider + * @param context + * @return pem encoded certificates, where: + * [0] is the ca cert + * [1] is an optional extra cert + * [2] is the vpn certificate + */ public String[] getExternalCertificates(Context context) { return getExternalCertificates(context, 5); } @@ -966,8 +987,9 @@ public class VpnProfile implements Serializable, Cloneable { if (mUseTLSAuth && TextUtils.isEmpty(mTLSAuthFilename)) return R.string.missing_tlsauth; - if ((mAuthenticationType == TYPE_USERPASS_CERTIFICATES || mAuthenticationType == TYPE_CERTIFICATES) - && (TextUtils.isEmpty(mClientCertFilename) || TextUtils.isEmpty(mClientKeyFilename))) + if ((mAuthenticationType == TYPE_USERPASS_CERTIFICATES && + (TextUtils.isEmpty(mClientCertFilename) || (TextUtils.isEmpty(mClientKeyFilename)))) || + mAuthenticationType == TYPE_CERTIFICATES && TextUtils.isEmpty(mClientCertFilename)) return R.string.missing_certificates; if ((mAuthenticationType == TYPE_CERTIFICATES || mAuthenticationType == TYPE_USERPASS_CERTIFICATES) @@ -1148,13 +1170,14 @@ public class VpnProfile implements Serializable, Cloneable { } @Nullable - public String getSignedData(Context c, String b64data, boolean pkcs1padding) { + public String getSignedData(Context c, String b64data, OpenVPNManagement.SignaturePadding padding, String saltlen, String hashalg, boolean needDigest) { byte[] data = Base64.decode(b64data, Base64.DEFAULT); byte[] signed_bytes; - if (mAuthenticationType == TYPE_EXTERNAL_APP) - signed_bytes = getExtAppSignedData(c, data); - else - signed_bytes = getKeyChainSignedData(data, pkcs1padding); + if (mAuthenticationType == TYPE_EXTERNAL_APP) { + signed_bytes = getExtAppSignedData(c, data, padding, saltlen, hashalg, needDigest); + } else { + signed_bytes = getKeyChainSignedData(data, padding, saltlen, hashalg, needDigest); + } if (signed_bytes != null) return Base64.encodeToString(signed_bytes, Base64.NO_WRAP); @@ -1162,19 +1185,41 @@ public class VpnProfile implements Serializable, Cloneable { return null; } - private byte[] getExtAppSignedData(Context c, byte[] data) { + private byte[] getExtAppSignedData(Context c, byte[] data, OpenVPNManagement.SignaturePadding padding, String saltlen, String hashalg, boolean needDigest) + { + + Bundle extra = new Bundle(); + RsaPaddingType paddingType; + switch (padding) { + case RSA_PKCS1_PADDING: + paddingType = RsaPaddingType.PKCS1_PADDING; + break; + case NO_PADDING: + paddingType = RsaPaddingType.NO_PADDING; + break; + case RSA_PKCS1_PSS_PADDING: + paddingType = RsaPaddingType.RSAPSS_PADDING; + break; + default: + paddingType = RsaPaddingType.NO_PADDING; + } + + extra.putInt(EXTRA_RSA_PADDING_TYPE, paddingType.ordinal()); + extra.putString(EXTRA_SALTLEN, saltlen); + extra.putString(EXTRA_DIGEST, hashalg); + extra.putBoolean(EXTRA_NEEDS_DIGEST, needDigest); + if (TextUtils.isEmpty(mExternalAuthenticator)) return null; try { - return ExtAuthHelper.signData(c, mExternalAuthenticator, mAlias, data); + return ExtAuthHelper.signData(c, mExternalAuthenticator, mAlias, data, extra); } catch (KeyChainException | InterruptedException e) { VpnStatus.logError(R.string.error_extapp_sign, mExternalAuthenticator, e.getClass().toString(), e.getLocalizedMessage()); return null; } } - private byte[] getKeyChainSignedData(byte[] data, boolean pkcs1padding) { - + private byte[] getKeyChainSignedData(byte[] data, OpenVPNManagement.SignaturePadding padding, String saltlen, String hashalg, boolean needDigest) { PrivateKey privkey = getKeystoreKey(); try { @@ -1182,36 +1227,121 @@ public class VpnProfile implements Serializable, Cloneable { String keyalgorithm = privkey.getAlgorithm(); byte[] signed_bytes; - if (keyalgorithm.equals("EC")) { - Signature signer = Signature.getInstance("NONEwithECDSA"); - - signer.initSign(privkey); - signer.update(data); - signed_bytes = signer.sign(); - + if (needDigest || keyalgorithm.equals("EC")) { + return doDigestSign(privkey, data, padding, hashalg, saltlen); } else { - /* ECB is perfectly fine in this special case, since we are using it for - the public/private part in the TLS exchange - */ - Cipher signer; - if (pkcs1padding) - signer = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); - else - signer = Cipher.getInstance("RSA/ECB/NoPadding"); - + /* ECB is perfectly fine in this special case, since we are using it for + the public/private part in the TLS exchange */ + Cipher signer = null; + switch (padding) { + case RSA_PKCS1_PADDING: + signer = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); + break; + case NO_PADDING: + signer = Cipher.getInstance("RSA/ECB/NoPadding"); + break; + case RSA_PKCS1_PSS_PADDING: + throw new NoSuchPaddingException("Cannot do PKCS1 PSS padding without also doing the digest"); + } signer.init(Cipher.ENCRYPT_MODE, privkey); signed_bytes = signer.doFinal(data); + + return signed_bytes; } - return signed_bytes; - } catch (NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException - | BadPaddingException | NoSuchPaddingException | SignatureException e) { + } catch + (NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException | SignatureException | InvalidAlgorithmParameterException + e) { VpnStatus.logError(R.string.error_rsa_sign, e.getClass().toString(), e.getLocalizedMessage()); return null; } } + private byte[] addPSSPadding(PrivateKey privkey, String digest, byte[] data) throws NoSuchAlgorithmException { + /* For < API 23, add padding ourselves */ + int hashtype = getHashtype(digest); + + MessageDigest msgDigest = MessageDigest.getInstance(digest); + byte[] hash = msgDigest.digest(data); + + /* MSBits = (BN_num_bits(rsa->n) - 1) & 0x7; */ + int numbits = ((RSAPrivateKey) privkey).getModulus().bitLength(); + + int MSBits = (numbits - 1) & 0x7; + + return NativeUtils.addRssPssPadding(hashtype, MSBits, numbits/8, hash); + } + + private int getHashtype(String digest) throws NoSuchAlgorithmException { + int hashtype = 0; + switch (digest) { + case "SHA1": + hashtype = 1; + break; + case "SHA224": + hashtype = 2; + break; + case "SHA256": + hashtype = 3; + break; + case "SHA384": + hashtype = 4; + break; + case "SHA512": + hashtype = 5; + break; + default: + throw new NoSuchAlgorithmException("Unknown digest algorithm: " + digest); + } + return hashtype; + } + + private byte[] doDigestSign(PrivateKey privkey, byte[] data, OpenVPNManagement.SignaturePadding padding, String hashalg, String saltlen) throws SignatureException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException { + /* RSA */ + Signature sig = null; + + if (privkey.getAlgorithm().equals("EC")) { + if (hashalg.equals("")) + hashalg = "NONE"; + /* e.g. SHA512withECDSA */ + hashalg = hashalg + "withECDSA"; + sig = Signature.getInstance(hashalg.toUpperCase(Locale.ROOT)); + } else if (padding == OpenVPNManagement.SignaturePadding.RSA_PKCS1_PSS_PADDING) { + /* https://developer.android.com/training/articles/keystore#SupportedSignatures */ + if (!"digest".equals(saltlen)) + throw new SignatureException("PSS signing requires saltlen=digest"); + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + data = addPSSPadding(privkey, hashalg, data); + return getKeyChainSignedData(data, OpenVPNManagement.SignaturePadding.NO_PADDING, "none", "none", false); + } + + sig = Signature.getInstance(hashalg + "withRSA/PSS"); + + PSSParameterSpec pssspec = null; + switch (hashalg) { + case "SHA256": + pssspec = new PSSParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1); + break; + case "SHA512": + pssspec = new PSSParameterSpec("SHA-512", "MGF1", MGF1ParameterSpec.SHA512, 64, 1); + break; + case "SHA384": + pssspec = new PSSParameterSpec("SHA-384", "MGF1", MGF1ParameterSpec.SHA384, 48, 1); + break; + } + sig.setParameter(pssspec); + } else if (padding == OpenVPNManagement.SignaturePadding.RSA_PKCS1_PADDING) { + sig = Signature.getInstance(hashalg + "withRSA"); + } + + sig.initSign(privkey); + sig.update(data); + return sig.sign(); + } + + private boolean usesExtraProxyOptions() { if (mUseCustomConfig && mCustomConfigOptions != null && mCustomConfigOptions.contains("http-proxy-option ")) return true; @@ -1222,6 +1352,16 @@ public class VpnProfile implements Serializable, Cloneable { return false; } + /** + * The order of elements is important! + */ + private enum RsaPaddingType { + NO_PADDING, + PKCS1_PADDING, + RSAPSS_PADDING + } + + class NoCertReturnedException extends Exception { public NoCertReturnedException(String msg) { super(msg); diff --git a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java index e8d333e3..ff27a5a2 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java @@ -70,9 +70,7 @@ public class ConfigParser { "management", "management-client", "management-query-remote", - "management-query-passwords", "management-query-proxy", - "management-external-key", "management-forget-disconnect", "management-signal", "management-log-cache", diff --git a/app/src/main/java/de/blinkt/openvpn/core/ExtAuthHelper.java b/app/src/main/java/de/blinkt/openvpn/core/ExtAuthHelper.java index a62a4c62..d102dce2 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ExtAuthHelper.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ExtAuthHelper.java @@ -108,15 +108,23 @@ public class ExtAuthHelper { public static byte[] signData(@NonNull Context context, @NonNull String extAuthPackageName, @NonNull String alias, - @NonNull byte[] data + @NonNull byte[] data, + @NonNull Bundle extra ) throws KeyChainException, InterruptedException { - try (ExternalAuthProviderConnection authProviderConnection = bindToExtAuthProvider(context.getApplicationContext(), extAuthPackageName)) { + try (ExternalAuthProviderConnection authProviderConnection = + bindToExtAuthProvider(context.getApplicationContext(), extAuthPackageName)) { ExternalCertificateProvider externalAuthProvider = authProviderConnection.getService(); - return externalAuthProvider.getSignedData(alias, data); + + byte[] result = externalAuthProvider.getSignedDataWithExtra(alias, data, extra); + // When the desired method is not implemented, a default implementation is called, returning null + if (result == null) + result = externalAuthProvider.getSignedData(alias, data); + + return result; } catch (RemoteException e) { throw new KeyChainException(e); diff --git a/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java b/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java index f769b38e..818564c7 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java +++ b/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java @@ -29,6 +29,21 @@ public class NativeUtils { private static native String getJNIAPI(); + static boolean rsspssloaded = false; + + public static byte[] addRssPssPadding(int hashtype, int MSBits, int rsa_size, byte[] from) + { + if (!rsspssloaded) { + rsspssloaded = true; + System.loadLibrary("rsapss"); + } + + return rsapss(hashtype, MSBits, rsa_size, from); + } + + private static native byte[] rsapss(int hashtype, int MSBits, int rsa_size, byte[] from); + + public final static int[] openSSLlengths = { 16, 64, 256, 1024, 8 * 1024, 16 * 1024 }; diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java index ef17e98b..02e4eca9 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java @@ -16,6 +16,12 @@ public interface OpenVPNManagement { screenOff, } + enum SignaturePadding { + RSA_PKCS1_PSS_PADDING, + RSA_PKCS1_PADDING, + NO_PADDING + } + int mBytecountInterval = 2; void reconnect(); diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java index a02e7e27..88b933eb 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java @@ -194,7 +194,7 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { // Closing one of the two sockets also closes the other //mServerSocketLocal.close(); - managmentCommand("version 2\n"); + managmentCommand("version 3\n"); while (true) { @@ -730,9 +730,33 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { releaseHold(); } - private void processSignCommand(String b64data) { + private void processSignCommand(String argument) { - String signed_string = mProfile.getSignedData(mOpenVPNService, b64data, false); + String[] arguments = argument.split(","); + + // NC9t8IkYrjAQcCzc85zN0H5TvwfAUDwYkR4j2ga6fGw=,RSA_PKCS1_PSS_PADDING,hashalg=SHA256,saltlen=digest + + + SignaturePadding padding = SignaturePadding.NO_PADDING; + String saltlen=""; + String hashalg=""; + boolean needsDigest = false; + + for (int i=1;i < arguments.length;i++) { + String arg = arguments[i]; + if(arg.equals("RSA_PKCS1_PADDING")) + padding = SignaturePadding.RSA_PKCS1_PADDING; + else if (arg.equals("RSA_PKCS1_PSS_PADDING")) + padding = SignaturePadding.RSA_PKCS1_PSS_PADDING; + else if (arg.startsWith("saltlen=")) + saltlen= arg.substring(8); + else if (arg.startsWith("hashalg=")) + hashalg = arg.substring(8); + else if (arg.equals("data=message")) + needsDigest = true; + } + + String signed_string = mProfile.getSignedData(mOpenVPNService, arguments[0], padding, saltlen, hashalg, needsDigest); if (signed_string == null) { managmentCommand("pk-sig\n"); diff --git a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java index 80427a03..67636762 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java +++ b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java @@ -5,7 +5,6 @@ package de.blinkt.openvpn.core; -import android.annotation.TargetApi; import android.content.Context; import android.os.Build; diff --git a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java index f28651f3..8115548f 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java +++ b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java @@ -5,6 +5,8 @@ package de.blinkt.openvpn.core; +import static se.leap.bitmaskclient.base.utils.ConfigHelper.getProviderFormattedString; + import android.content.Context; import android.os.Build; import android.os.HandlerThread; @@ -23,8 +25,6 @@ import de.blinkt.openvpn.VpnProfile; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.utils.PreferenceHelper; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.getProviderFormattedString; - public class VpnStatus { @@ -485,10 +485,6 @@ public class VpnStatus { mLogFileHandler.sendMessage(mLogFileHandler.obtainMessage(LogFileHandler.TRIM_LOG_FILE)); } - //if (BuildConfig.DEBUG && !cachedLine && !BuildConfig.FLAVOR.equals("test")) - // Log.d("OpenVPN", logItem.getString(null)); - - for (LogListener ll : logListener) { ll.newLog(logItem); } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/BitmaskApp.java b/app/src/main/java/se/leap/bitmaskclient/base/BitmaskApp.java index 0ccef0ae..74b789a9 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/BitmaskApp.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/BitmaskApp.java @@ -22,11 +22,9 @@ import static se.leap.bitmaskclient.appUpdate.DownloadBroadcastReceiver.ACTION_D import static se.leap.bitmaskclient.appUpdate.DownloadServiceCommand.CHECK_VERSION_FILE; import static se.leap.bitmaskclient.appUpdate.DownloadServiceCommand.DOWNLOAD_UPDATE; import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_DOWNLOAD_SERVICE_EVENT; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.utils.ConfigHelper.isCalyxOSWithTetheringSupport; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getSavedProviderFromSharedPreferences; -import android.content.Context; import android.content.IntentFilter; import android.content.SharedPreferences; @@ -42,6 +40,7 @@ import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.appUpdate.DownloadBroadcastReceiver; import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.base.utils.PRNGFixes; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.eip.EipSetupObserver; import se.leap.bitmaskclient.tethering.TetheringStateManager; import se.leap.bitmaskclient.tor.TorStatusObservable; @@ -64,7 +63,7 @@ public class BitmaskApp extends MultiDexApplication { // Normal app init code...*/ PRNGFixes.apply(); Security.insertProviderAt(Conscrypt.newProvider(), 1); - SharedPreferences preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = PreferenceHelper.getSharedPreferences(this); providerObservable = ProviderObservable.getInstance(); providerObservable.updateProvider(getSavedProviderFromSharedPreferences(preferences)); torStatusObservable = TorStatusObservable.getInstance(); diff --git a/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java index 9225755e..248d96c7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java @@ -33,7 +33,6 @@ import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_CONFIGURE_LEAP; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_LOG_IN; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_SWITCH_PROVIDER; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.storeProviderInPreferences; import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_INVALID_VPN_CERTIFICATE; import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_VPN_PREPARE; @@ -113,7 +112,7 @@ public class MainActivity extends AppCompatActivity implements EipSetupListener, navigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager().findFragmentById(R.id.navigation_drawer); - preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + preferences = PreferenceHelper.getSharedPreferences(this); provider = ProviderObservable.getInstance().getCurrentProvider(); EipSetupObserver.addListener(this); diff --git a/app/src/main/java/se/leap/bitmaskclient/base/OnBootReceiver.java b/app/src/main/java/se/leap/bitmaskclient/base/OnBootReceiver.java index 3b534a7d..a508329c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/OnBootReceiver.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/OnBootReceiver.java @@ -1,5 +1,10 @@ package se.leap.bitmaskclient.base; +import static android.content.Intent.ACTION_BOOT_COMPLETED; +import static se.leap.bitmaskclient.base.models.Constants.APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE; +import static se.leap.bitmaskclient.base.models.Constants.EIP_RESTART_ON_BOOT; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; + import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -8,12 +13,7 @@ import android.os.Build; import android.util.Log; import de.blinkt.openvpn.core.VpnStatus; - -import static android.content.Intent.ACTION_BOOT_COMPLETED; -import static se.leap.bitmaskclient.base.models.Constants.APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE; -import static se.leap.bitmaskclient.base.models.Constants.EIP_RESTART_ON_BOOT; -import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; public class OnBootReceiver extends BroadcastReceiver { @@ -26,7 +26,7 @@ public class OnBootReceiver extends BroadcastReceiver { if (intent == null || !ACTION_BOOT_COMPLETED.equals(intent.getAction())) { return; } - preferences = context.getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE); + preferences = PreferenceHelper.getSharedPreferences(context); boolean providerConfigured = !preferences.getString(PROVIDER_VPN_CERTIFICATE, "").isEmpty(); boolean startOnBoot = preferences.getBoolean(EIP_RESTART_ON_BOOT, false) && Build.VERSION.SDK_INT < Build.VERSION_CODES.O; boolean isAlwaysOnConfigured = VpnStatus.isAlwaysOn(); diff --git a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java index 58b057b7..94000a0f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java @@ -25,7 +25,6 @@ import static se.leap.bitmaskclient.base.models.Constants.PREFERENCES_APP_VERSIO import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_EIP_DEFINITION; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_CONFIGURE_LEAP; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.storeProviderInPreferences; @@ -81,7 +80,7 @@ public class StartActivity extends Activity{ @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + preferences = PreferenceHelper.getSharedPreferences(this); Log.d(TAG, "Started"); @@ -103,10 +102,27 @@ public class StartActivity extends Activity{ // initialize app necessities VpnStatus.initLogCache(getApplicationContext().getCacheDir()); + sanitizeStartIntent(); prepareEIP(); } + private void sanitizeStartIntent() { + Intent intent = new Intent(); + try { + if (getIntent().hasExtra(EIP_RESTART_ON_BOOT)) { + intent.putExtra(EIP_RESTART_ON_BOOT, getIntent().getBooleanExtra(EIP_RESTART_ON_BOOT, false)); + } + if (getIntent().hasExtra(APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE)) { + intent.putExtra(APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE, false); + } + } catch (RuntimeException e) { + + } + this.setIntent(intent); + } + + /** * check if normal start, first run, up or downgrade * @return @StartupMode @@ -180,6 +196,11 @@ public class StartActivity extends Activity{ } } + if (hasNewFeature(FeatureVersionCode.ENCRYPTED_SHARED_PREFS)) { + PreferenceHelper.migrateToEncryptedPrefs(this); + preferences = PreferenceHelper.getSharedPreferences(this); + } + // always check if manual gateway selection feature switch has been disabled if (!BuildConfig.allow_manual_gateway_selection && PreferenceHelper.getPreferredCity(this) != null) { PreferenceHelper.setPreferredCity(this, null); diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java index a2fb2683..a8d11869 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java @@ -25,7 +25,6 @@ import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_CONFIGURE_LEAP; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_LOG_IN; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_SWITCH_PROVIDER; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferredCity; import static se.leap.bitmaskclient.eip.EipSetupObserver.reconnectingWithDifferentGateway; @@ -159,7 +158,7 @@ public class EipFragment extends Fragment implements Observer { torStatusObservable = TorStatusObservable.getInstance(); Activity activity = getActivity(); if (activity != null) { - preferences = getActivity().getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE); + preferences = PreferenceHelper.getSharedPreferences(activity); } else { Log.e(TAG, "activity is null in onCreate - no preferences set!"); } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java index 749ffd9f..793c6407 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java @@ -16,6 +16,16 @@ */ package se.leap.bitmaskclient.base.fragments; +import static android.view.View.GONE; +import static android.view.View.VISIBLE; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.PT; +import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT; +import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseBridges; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useBridges; +import static se.leap.bitmaskclient.base.utils.ViewHelper.setActionBarSubtitle; + import android.app.Activity; import android.content.Context; import android.content.Intent; @@ -49,18 +59,6 @@ import se.leap.bitmaskclient.eip.EipCommand; import se.leap.bitmaskclient.eip.EipStatus; import se.leap.bitmaskclient.eip.GatewaysManager; -import static android.content.Context.MODE_PRIVATE; -import static android.view.View.GONE; -import static android.view.View.VISIBLE; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.PT; -import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; -import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseBridges; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useBridges; -import static se.leap.bitmaskclient.base.utils.ViewHelper.setActionBarSubtitle; - interface LocationListSelectionListener { void onLocationManuallySelected(Location location); } @@ -89,7 +87,7 @@ public class GatewaySelectionFragment extends Fragment implements Observer, Loca super.onCreate(savedInstanceState); gatewaysManager = new GatewaysManager(getContext()); eipStatus = EipStatus.getInstance(); - preferences = getContext().getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + preferences = PreferenceHelper.getSharedPreferences(getContext()); } @Override diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java index aa894cca..f51fd342 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java @@ -25,7 +25,6 @@ import static se.leap.bitmaskclient.base.models.Constants.ENABLE_DONATION; import static se.leap.bitmaskclient.base.models.Constants.PREFERRED_CITY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_SWITCH_PROVIDER; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferredCity; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getSaveBattery; @@ -63,6 +62,7 @@ import se.leap.bitmaskclient.base.FragmentManagerEnhanced; import se.leap.bitmaskclient.base.MainActivity; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.models.ProviderObservable; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.base.views.IconSwitchEntry; import se.leap.bitmaskclient.base.views.IconTextEntry; import se.leap.bitmaskclient.eip.EipStatus; @@ -110,7 +110,7 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen super.onCreate(savedInstanceState); // Reads in the flag indicating whether or not the user has demonstrated awareness of the // drawer. See PREF_USER_LEARNED_DRAWER for details. - preferences = getContext().getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + preferences = PreferenceHelper.getSharedPreferences(getContext()); preferences.registerOnSharedPreferenceChangeListener(this); } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java index 40bc256c..f36b17ad 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java @@ -1,12 +1,10 @@ package se.leap.bitmaskclient.base.fragments; -import static android.content.Context.MODE_PRIVATE; import static android.view.View.GONE; import static android.view.View.VISIBLE; import static se.leap.bitmaskclient.R.string.advanced_settings; import static se.leap.bitmaskclient.base.models.Constants.GATEWAY_PINNING; import static se.leap.bitmaskclient.base.models.Constants.PREFER_UDP; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES; import static se.leap.bitmaskclient.base.models.Constants.USE_IPv6_FIREWALL; import static se.leap.bitmaskclient.base.models.Constants.USE_OBFUSCATION_PINNING; @@ -71,7 +69,7 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - preferences = getContext().getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + preferences = PreferenceHelper.getSharedPreferences(getContext()); preferences.registerOnSharedPreferenceChangeListener(this); firewallManager = new FirewallManager(getContext().getApplicationContext(), false); } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java index 57467974..70bf3943 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java @@ -27,6 +27,7 @@ public interface Constants { ///////////////////////////////////////////// String SHARED_PREFERENCES = "LEAPPreferences"; + String SHARED_ENCRYPTED_PREFERENCES = "LEAPEncryptedPreferences"; String PREFERENCES_APP_VERSION = "bitmask version"; String ALWAYS_ON_SHOW_DIALOG = "DIALOG.ALWAYS_ON_SHOW_DIALOG"; String CLEARLOG = "clearlogconnect"; diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java b/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java index f7251acb..c2eb9694 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java @@ -5,4 +5,6 @@ public interface FeatureVersionCode { int GEOIP_SERVICE = 148; int CALYX_PROVIDER_LILYPAD_UPDATE = 165000; int RISEUP_PROVIDER_LILYPAD_UPDATE = 165000; + + int ENCRYPTED_SHARED_PREFS = 170000; } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java index 08e13cf6..14c78cc3 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java @@ -29,6 +29,7 @@ import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_ALLOW_ANONYMO import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT; import static se.leap.bitmaskclient.base.models.Constants.TYPE; import static se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper.useObfsVpn; +import static se.leap.bitmaskclient.base.utils.ConfigHelper.RSAHelper.parseRsaKeyFromString; import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS; import android.os.Parcel; @@ -44,6 +45,7 @@ import org.json.JSONObject; import java.net.MalformedURLException; import java.net.URL; +import java.security.interfaces.RSAPrivateKey; import java.util.ArrayList; import java.util.HashSet; import java.util.Locale; @@ -79,6 +81,8 @@ public final class Provider implements Parcelable { private String caCert = ""; private String apiVersion = ""; private String privateKey = ""; + + private transient RSAPrivateKey rsaPrivateKey = null; private String vpnCertificate = ""; private long lastEipServiceUpdate = 0L; private long lastGeoIpUpdate = 0L; @@ -701,6 +705,13 @@ public final class Provider implements Parcelable { return privateKey; } + public RSAPrivateKey getRSAPrivateKey() { + if (rsaPrivateKey == null) { + rsaPrivateKey = parseRsaKeyFromString(privateKey); + } + return rsaPrivateKey; + } + public void setPrivateKey(String privateKey) { this.privateKey = privateKey; } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java index 2412efdd..9289738a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java @@ -131,35 +131,37 @@ public class ConfigHelper { return null; } - public static RSAPrivateKey parseRsaKeyFromString(String rsaKeyString) { - RSAPrivateKey key; - try { - KeyFactory kf; - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { - kf = KeyFactory.getInstance("RSA", "BC"); - } else { - kf = KeyFactory.getInstance("RSA"); + public static class RSAHelper { + public static RSAPrivateKey parseRsaKeyFromString(String rsaKeyString) { + RSAPrivateKey key; + try { + KeyFactory kf; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { + kf = KeyFactory.getInstance("RSA", "BC"); + } else { + kf = KeyFactory.getInstance("RSA"); + } + rsaKeyString = rsaKeyString.replaceFirst("-----BEGIN RSA PRIVATE KEY-----", "").replaceFirst("-----END RSA PRIVATE KEY-----", ""); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(rsaKeyString)); + key = (RSAPrivateKey) kf.generatePrivate(keySpec); + } catch (InvalidKeySpecException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } catch (NullPointerException e) { + e.printStackTrace(); + return null; + } catch (NoSuchProviderException e) { + e.printStackTrace(); + return null; } - rsaKeyString = rsaKeyString.replaceFirst("-----BEGIN RSA PRIVATE KEY-----", "").replaceFirst("-----END RSA PRIVATE KEY-----", ""); - PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(rsaKeyString)); - key = (RSAPrivateKey) kf.generatePrivate(keySpec); - } catch (InvalidKeySpecException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return null; - } catch (NoSuchAlgorithmException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return null; - } catch (NullPointerException e) { - e.printStackTrace(); - return null; - } catch (NoSuchProviderException e) { - e.printStackTrace(); - return null; - } - return key; + return key; + } } private static String byteArrayToHex(byte[] input) { diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java index 9cba221a..12196aee 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java @@ -27,6 +27,7 @@ import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_UPD import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.base.models.Constants.RESTART_ON_UPDATE; +import static se.leap.bitmaskclient.base.models.Constants.SHARED_ENCRYPTED_PREFERENCES; import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.models.Constants.SHOW_EXPERIMENTAL; import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES; @@ -37,16 +38,22 @@ import static se.leap.bitmaskclient.base.models.Constants.USE_SNOWFLAKE; import android.content.Context; import android.content.SharedPreferences; import android.text.TextUtils; +import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; +import androidx.security.crypto.EncryptedSharedPreferences; +import androidx.security.crypto.MasterKey; import org.json.JSONException; import org.json.JSONObject; +import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +import java.security.GeneralSecurityException; import java.util.HashSet; +import java.util.Map; import java.util.Set; import de.blinkt.openvpn.VpnProfile; @@ -60,6 +67,26 @@ import se.leap.bitmaskclient.tor.TorStatusObservable; public class PreferenceHelper { + private static final String TAG = PreferenceHelper.class.getSimpleName(); + + public static SharedPreferences getSharedPreferences(Context context) { + try { + MasterKey masterKey = new MasterKey.Builder(context) + .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) + .build(); + + return EncryptedSharedPreferences.create( + context, + SHARED_ENCRYPTED_PREFERENCES, + masterKey, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM); + } catch (GeneralSecurityException | IOException e) { + e.printStackTrace(); + } + return context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + } + public static Provider getSavedProviderFromSharedPreferences(@NonNull SharedPreferences preferences) { Provider provider = new Provider(); try { @@ -97,7 +124,7 @@ public class PreferenceHelper { } public static void persistProviderAsync(Context context, Provider provider) { - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); storeProviderInPreferences(preferences, provider, true); } @@ -151,7 +178,7 @@ public class PreferenceHelper { * Sets the profile that is connected (to connect if the service restarts) */ public static void setLastUsedVpnProfile(Context context, VpnProfile connectedProfile) { - SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences prefs = getSharedPreferences(context); SharedPreferences.Editor prefsedit = prefs.edit(); prefsedit.putString(LAST_USED_PROFILE, connectedProfile.toJson()); prefsedit.apply(); @@ -161,7 +188,7 @@ public class PreferenceHelper { * Returns the profile that was last connected (to connect if the service restarts) */ public static VpnProfile getLastConnectedVpnProfile(Context context) { - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); String lastConnectedProfileJson = preferences.getString(LAST_USED_PROFILE, null); return VpnProfile.fromJson(lastConnectedProfileJson); } @@ -204,6 +231,8 @@ public class PreferenceHelper { apply(); } + // used in fatweb flavor + @SuppressWarnings("unused") public static void setLastAppUpdateCheck(Context context) { putLong(context, LAST_UPDATE_CHECK, System.currentTimeMillis()); } @@ -419,7 +448,7 @@ public class PreferenceHelper { if (context == null) { return null; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); return preferences.getStringSet(EXCLUDED_APPS, new HashSet<>()); } @@ -427,7 +456,7 @@ public class PreferenceHelper { if (context == null) { return defValue; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); return preferences.getLong(key, defValue); } @@ -435,7 +464,7 @@ public class PreferenceHelper { if (context == null) { return; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); preferences.edit().putLong(key, value).apply(); } @@ -443,7 +472,7 @@ public class PreferenceHelper { if (context == null) { return defValue; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); return preferences.getString(key, defValue); } @@ -452,7 +481,7 @@ public class PreferenceHelper { if (context == null) { return; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); preferences.edit().putString(key, value).commit(); } @@ -460,7 +489,7 @@ public class PreferenceHelper { if (context == null) { return; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); preferences.edit().putString(key, value).apply(); } @@ -468,7 +497,7 @@ public class PreferenceHelper { if (context == null) { return; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); preferences.edit().putStringSet(key, value).apply(); } @@ -477,7 +506,7 @@ public class PreferenceHelper { return false; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); return preferences.getBoolean(key, defValue); } @@ -486,7 +515,7 @@ public class PreferenceHelper { return; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); preferences.edit().putBoolean(key, value).apply(); } @@ -495,7 +524,41 @@ public class PreferenceHelper { return false; } - SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = getSharedPreferences(context); return preferences.contains(key); } + + public static void migrateToEncryptedPrefs(Context context) { + SharedPreferences encryptedPrefs = getSharedPreferences(context); + if (!(encryptedPrefs instanceof EncryptedSharedPreferences)) { + Log.e(TAG, "Failed to migrate shared preferences"); + return; + } + SharedPreferences.Editor encryptedEditor = encryptedPrefs.edit(); + SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + Map<String,?> keys = preferences.getAll(); + + for(Map.Entry<String,?> entry : keys.entrySet()){ + try { + Object value = entry.getValue(); + if (value instanceof String) { + encryptedEditor.putString(entry.getKey(), (String) value); + } else if (value instanceof Boolean) { + encryptedEditor.putBoolean(entry.getKey(), (Boolean) value); + } else if (value instanceof Integer) { + encryptedEditor.putInt(entry.getKey(), (Integer) value); + } else if (value instanceof Set<?>) { + encryptedEditor.putStringSet(entry.getKey(), (Set<String>) value); + } else if (value instanceof Long) { + encryptedEditor.putLong(entry.getKey(), (Long) value); + } else if (value instanceof Float) { + encryptedEditor.putFloat(entry.getKey(), (Float) value); + } + } catch (ClassCastException e) { + e.printStackTrace(); + } + } + encryptedEditor.commit(); + preferences.edit().clear().apply(); + } } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java index 5b082448..29714670 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -37,7 +37,6 @@ import static se.leap.bitmaskclient.base.models.Constants.EIP_RECEIVER; import static se.leap.bitmaskclient.base.models.Constants.EIP_RESTART_ON_BOOT; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PROFILE; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.utils.ConfigHelper.ensureNotOnMainThread; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferredCity; import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_INVALID_PROFILE; @@ -84,11 +83,9 @@ import de.blinkt.openvpn.core.IOpenVPNServiceInternal; import de.blinkt.openvpn.core.OpenVPNService; import de.blinkt.openvpn.core.Preferences; import de.blinkt.openvpn.core.VpnStatus; -import de.blinkt.openvpn.core.connection.Connection; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.OnBootReceiver; import se.leap.bitmaskclient.base.models.Provider; -import se.leap.bitmaskclient.base.models.Pair; import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.eip.GatewaysManager.GatewayOptions; @@ -147,7 +144,7 @@ public final class EIP extends JobIntentService implements Observer { super.onCreate(); eipStatus = EipStatus.getInstance(); eipStatus.addObserver(this); - preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + preferences = PreferenceHelper.getSharedPreferences(this); } @Override diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java index 85cdb06c..bb05810c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java @@ -73,6 +73,7 @@ import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConnectionStatus; import de.blinkt.openvpn.core.LogItem; import de.blinkt.openvpn.core.VpnStatus; +import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.appUpdate.DownloadServiceCommand; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.models.ProviderObservable; @@ -433,6 +434,9 @@ public class EipSetupObserver extends BroadcastReceiver implements VpnStatus.Sta @Override public void newLog(LogItem logItem) { if (logItem.getLogLevel() == VpnStatus.LogLevel.ERROR) { + if (BuildConfig.DEBUG) { + Log.e("ERROR", logItem.getString(appContext)); + } switch (logItem.getErrorType()) { case SHAPESHIFTER: VpnProfile profile = VpnStatus.getLastConnectedVpnProfile(); diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java index d114665b..5e05b7c1 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -22,7 +22,6 @@ import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN import static de.blinkt.openvpn.core.connection.Connection.TransportType.PT; import static se.leap.bitmaskclient.base.models.Constants.GATEWAYS; import static se.leap.bitmaskclient.base.models.Constants.HOST; -import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.base.models.Constants.SORTED_GATEWAYS; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningCert; @@ -124,6 +123,7 @@ public class GatewaysManager { GatewaySelector gatewaySelector; + public GatewaysManager(Context context) { this.context = context; configureFromCurrentProvider(); @@ -392,7 +392,6 @@ public class GatewaysManager { try { JSONObject eipDefinition = provider.getEipServiceJson(); JSONObject secrets = secretsConfigurationFromCurrentProvider(); - JSONArray gatewaysDefined = new JSONArray(); try { gatewaysDefined = eipDefinition.getJSONArray(GATEWAYS); @@ -488,10 +487,8 @@ public class GatewaysManager { private JSONObject secretsConfigurationFromCurrentProvider() { JSONObject result = new JSONObject(); Provider provider = ProviderObservable.getInstance().getCurrentProvider(); - try { result.put(Provider.CA_CERT, provider.getCaCert()); - result.put(PROVIDER_PRIVATE_KEY, provider.getPrivateKey()); result.put(PROVIDER_VPN_CERTIFICATE, provider.getVpnCertificate()); } catch (JSONException e) { e.printStackTrace(); diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java index 79876d50..d9da622c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java @@ -16,7 +16,12 @@ */ package se.leap.bitmaskclient.eip; -import android.annotation.TargetApi; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START_ALWAYS_ON_VPN; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START_BLOCKING_VPN; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_STOP_BLOCKING_VPN; +import static se.leap.bitmaskclient.base.models.Constants.EIP_IS_ALWAYS_ON; +import static se.leap.bitmaskclient.base.utils.ConfigHelper.getProviderFormattedString; + import android.app.Notification; import android.content.Intent; import android.content.SharedPreferences; @@ -35,13 +40,7 @@ import java.util.Observer; import de.blinkt.openvpn.core.ConnectionStatus; import de.blinkt.openvpn.core.VpnStatus; import se.leap.bitmaskclient.R; - -import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START_ALWAYS_ON_VPN; -import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START_BLOCKING_VPN; -import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_STOP_BLOCKING_VPN; -import static se.leap.bitmaskclient.base.models.Constants.EIP_IS_ALWAYS_ON; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.getProviderFormattedString; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; public class VoidVpnService extends VpnService implements Observer, VpnNotificationManager.VpnServiceCallback { @@ -85,7 +84,7 @@ public class VoidVpnService extends VpnService implements Observer, VpnNotificat thread = new Thread(new Runnable() { public void run() { establishBlockingVpn(); - SharedPreferences preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = PreferenceHelper.getSharedPreferences(VoidVpnService.this.getApplicationContext()); preferences.edit().putBoolean(EIP_IS_ALWAYS_ON, false).commit(); Log.d(TAG, "start blocking vpn profile - always on = false"); } @@ -97,7 +96,7 @@ public class VoidVpnService extends VpnService implements Observer, VpnNotificat thread = new Thread(new Runnable() { public void run() { establishBlockingVpn(); - SharedPreferences preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + SharedPreferences preferences = PreferenceHelper.getSharedPreferences(VoidVpnService.this.getApplicationContext()); preferences.edit().putBoolean(EIP_IS_ALWAYS_ON, true).commit(); requestVpnWithLastSelectedProfile(); Log.d(TAG, "start blocking vpn profile - always on = true"); diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java index 2c22d4f7..fa2ab352 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -490,13 +490,6 @@ public class VpnConfigGenerator { + newLine + "</ca>"; - String key = - "<key>" - + newLine - + secrets.getString(PROVIDER_PRIVATE_KEY) - + newLine - + "</key>"; - String openvpnCert = "<cert>" + newLine @@ -504,7 +497,7 @@ public class VpnConfigGenerator { + newLine + "</cert>"; - return ca + newLine + key + newLine + openvpnCert; + return ca + newLine + openvpnCert; } catch (JSONException e) { e.printStackTrace(); return ""; diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java index 86ce577b..0e7e1f4a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java @@ -19,7 +19,6 @@ package se.leap.bitmaskclient.providersetup; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; import android.net.ConnectivityManager; import android.net.NetworkCapabilities; import android.net.NetworkInfo; @@ -31,11 +30,9 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager; import java.util.concurrent.TimeoutException; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.providersetup.connectivity.OkHttpClientGenerator; import se.leap.bitmaskclient.tor.TorServiceCommand; -import se.leap.bitmaskclient.tor.TorServiceConnection; - -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; /** * Implements HTTP api methods (encapsulated in {{@link ProviderApiManager}}) @@ -180,9 +177,8 @@ public class ProviderAPI extends JobIntentService implements ProviderApiManagerB private ProviderApiManager initApiManager() { - SharedPreferences preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); OkHttpClientGenerator clientGenerator = new OkHttpClientGenerator(getResources()); - return new ProviderApiManager(preferences, getResources(), clientGenerator, this); + return new ProviderApiManager(PreferenceHelper.getSharedPreferences(this), getResources(), clientGenerator, this); } } diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java index 14308875..fdaef28b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java @@ -43,13 +43,12 @@ import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.base.models.Provider.CA_CERT; import static se.leap.bitmaskclient.base.models.Provider.GEOIP_URL; -import static se.leap.bitmaskclient.base.models.Provider.MOTD_URL; import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_API_IP; import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_IP; +import static se.leap.bitmaskclient.base.utils.ConfigHelper.RSAHelper.parseRsaKeyFromString; import static se.leap.bitmaskclient.base.utils.ConfigHelper.getDomainFromMainURL; import static se.leap.bitmaskclient.base.utils.ConfigHelper.getFingerprintFromCertificate; import static se.leap.bitmaskclient.base.utils.ConfigHelper.getProviderFormattedString; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.parseRsaKeyFromString; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.deleteProviderDetailsFromPreferences; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getFromPersistedProvider; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getLongFromPersistedProvider; diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java index 5cfefb2e..caba1436 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java @@ -1,7 +1,17 @@ package se.leap.bitmaskclient.providersetup.activities; +import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; +import static android.view.View.GONE; +import static android.view.View.VISIBLE; +import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; +import static se.leap.bitmaskclient.tor.TorStatusObservable.getBootstrapProgress; +import static se.leap.bitmaskclient.tor.TorStatusObservable.getLastLogs; +import static se.leap.bitmaskclient.tor.TorStatusObservable.getLastSnowflakeLog; +import static se.leap.bitmaskclient.tor.TorStatusObservable.getLastTorLog; +import static se.leap.bitmaskclient.tor.TorStatusObservable.getStringForCurrentStatus; + import android.content.SharedPreferences; -import android.graphics.PorterDuff; import android.graphics.Rect; import android.os.Build; import android.os.Bundle; @@ -20,7 +30,6 @@ import androidx.annotation.StringRes; import androidx.appcompat.widget.AppCompatTextView; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.Guideline; -import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -31,21 +40,10 @@ import java.util.Observer; import butterknife.BindView; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.models.Provider; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.base.views.ProviderHeaderView; import se.leap.bitmaskclient.tor.TorStatusObservable; -import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; -import static android.view.View.GONE; -import static android.view.View.VISIBLE; -import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE; -import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; -import static se.leap.bitmaskclient.tor.TorStatusObservable.getBootstrapProgress; -import static se.leap.bitmaskclient.tor.TorStatusObservable.getLastLogs; -import static se.leap.bitmaskclient.tor.TorStatusObservable.getLastSnowflakeLog; -import static se.leap.bitmaskclient.tor.TorStatusObservable.getLastTorLog; -import static se.leap.bitmaskclient.tor.TorStatusObservable.getStringForCurrentStatus; - /** * Base Activity for configuration wizard activities * @@ -135,7 +133,7 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity imple @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + preferences = PreferenceHelper.getSharedPreferences(this); provider = getIntent().getParcelableExtra(PROVIDER_KEY); } diff --git a/app/src/main/res/values/strings-icsopenvpn.xml b/app/src/main/res/values/strings-icsopenvpn.xml index dee6a42f..eab5e0c9 100755 --- a/app/src/main/res/values/strings-icsopenvpn.xml +++ b/app/src/main/res/values/strings-icsopenvpn.xml @@ -399,7 +399,7 @@ <string name="menu_use_inline_data">Use inline data</string> <string name="export_config_chooser_title">Export configuration file</string> <string name="missing_tlsauth">tls-auth file is missing</string> - <string name="missing_certificates">Missing user certificate or user certifcate key file</string> + <string name="missing_certificates">Missing user certificate or user certificate key file</string> <string name="missing_ca_certificate">Missing CA certificate</string> <string name="crl_title">Certifcate Revoke List (optional)</string> <string name="reread_log">Reread (%d) log items from log cache file</string> diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml new file mode 100644 index 00000000..fe61eb71 --- /dev/null +++ b/app/src/main/res/xml/data_extraction_rules.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<data-extraction-rules> + <cloud-backup> + <exclude domain="root" /> + <exclude domain="file" /> + <exclude domain="database" /> + <exclude domain="sharedpref" /> + <exclude domain="external" /> + </cloud-backup> + <device-transfer> + <exclude domain="root" /> + <exclude domain="file" /> + <exclude domain="database" /> + <exclude domain="sharedpref" /> + <exclude domain="external" /> + </device-transfer> +</data-extraction-rules> |