summaryrefslogtreecommitdiff
path: root/app/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main')
-rw-r--r--app/src/main/AndroidManifest.xml4
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/AboutActivity.java50
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java321
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Dashboard.java563
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java114
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/EipFragment.java518
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java36
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java634
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java32
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/PRNGFixes.java38
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Provider.java184
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java38
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java147
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderManager.java65
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java20
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/ProviderRendererBuilder.java26
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/SessionDialog.java169
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/User.java44
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java87
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/Constants.java7
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EIP.java151
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java111
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java114
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java52
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java73
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java44
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java70
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java54
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java157
-rw-r--r--app/src/main/res/layout-xlarge/dashboard.xml22
-rw-r--r--app/src/main/res/layout/dashboard.xml29
-rw-r--r--app/src/main/res/values/strings.xml10
32 files changed, 2061 insertions, 1923 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e11b57ef..cc31de43 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -17,8 +17,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="se.leap.bitmaskclient"
- android:versionCode="116"
- android:versionName="0.9.2" >
+ android:versionCode="120"
+ android:versionName="0.9.3" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
diff --git a/app/src/main/java/se/leap/bitmaskclient/AboutActivity.java b/app/src/main/java/se/leap/bitmaskclient/AboutActivity.java
index 6c4e517b..ce762fcc 100644
--- a/app/src/main/java/se/leap/bitmaskclient/AboutActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/AboutActivity.java
@@ -1,35 +1,35 @@
package se.leap.bitmaskclient;
-import android.app.Activity;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.Bundle;
-import android.widget.TextView;
-
-public class AboutActivity extends Activity {
-
+import android.app.*;
+import android.content.pm.*;
+import android.content.pm.PackageManager.*;
+import android.os.*;
+import android.widget.*;
+
+public class AboutActivity extends Activity {
+
final public static String TAG = "aboutFragment";
final public static int VIEWED = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.about);
- TextView ver = (TextView) findViewById(R.id.version);
-
- String version;
- String name="Openvpn";
- try {
- PackageInfo packageinfo = getPackageManager().getPackageInfo(getPackageName(), 0);
- version = packageinfo.versionName;
- name = getString(R.string.app);
- } catch (NameNotFoundException e) {
- version = "error fetching version";
- }
-
-
- ver.setText(getString(R.string.version_info,name,version));
- setResult(VIEWED);
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.about);
+ TextView ver = (TextView) findViewById(R.id.version);
+
+ String version;
+ String name = "Openvpn";
+ try {
+ PackageInfo packageinfo = getPackageManager().getPackageInfo(getPackageName(), 0);
+ version = packageinfo.versionName;
+ name = getString(R.string.app);
+ } catch (NameNotFoundException e) {
+ version = "error fetching version";
+ }
+
+
+ ver.setText(getString(R.string.version_info, name, version));
+ setResult(VIEWED);
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
index c0f0b0c3..4929f040 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java
@@ -1,6 +1,6 @@
/**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -16,179 +16,170 @@
*/
package se.leap.bitmaskclient;
-import android.util.Base64;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.security.KeyFactory;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.PKCS8EncodedKeySpec;
+import android.util.*;
+
+import org.json.*;
+
+import java.io.*;
+import java.math.*;
+import java.security.*;
+import java.security.cert.*;
+import java.security.interfaces.*;
+import java.security.spec.*;
/**
* Stores constants, and implements auxiliary methods used across all LEAP Android classes.
- *
+ *
* @author parmegv
* @author MeanderingCode
- *
*/
public class ConfigHelper {
private static KeyStore keystore_trusted;
final public static String NG_1024 =
- "eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c256576d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089dad15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e57ec68edbc3c05726cc02fd4cbf4976eaa9afd5138fe8376435b9fc61d2fc0eb06e3";
+ "eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c256576d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089dad15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e57ec68edbc3c05726cc02fd4cbf4976eaa9afd5138fe8376435b9fc61d2fc0eb06e3";
final public static BigInteger G = new BigInteger("2");
-
- public static boolean checkErroneousDownload(String downloaded_string) {
- try {
- if(new JSONObject(downloaded_string).has(ProviderAPI.ERRORS) || downloaded_string.isEmpty()) {
- return true;
- } else {
- return false;
- }
- } catch(JSONException e) {
- return false;
- }
- }
-
- /**
- * Treat the input as the MSB representation of a number,
- * and lop off leading zero elements. For efficiency, the
- * input is simply returned if no leading zeroes are found.
- *
- * @param in array to be trimmed
- */
- public static byte[] trim(byte[] in) {
- if(in.length == 0 || in[0] != 0)
- return in;
-
- int len = in.length;
- int i = 1;
- while(in[i] == 0 && i < len)
- ++i;
- byte[] ret = new byte[len - i];
- System.arraycopy(in, i, ret, 0, len - i);
- return ret;
- }
-
- public static X509Certificate parseX509CertificateFromString(String certificate_string) {
- java.security.cert.Certificate certificate = null;
- CertificateFactory cf;
- try {
- cf = CertificateFactory.getInstance("X.509");
-
- certificate_string = certificate_string.replaceFirst("-----BEGIN CERTIFICATE-----", "").replaceFirst("-----END CERTIFICATE-----", "").trim();
- byte[] cert_bytes = Base64.decode(certificate_string, Base64.DEFAULT);
- InputStream caInput = new ByteArrayInputStream(cert_bytes);
- try {
- certificate = cf.generateCertificate(caInput);
- System.out.println("ca=" + ((X509Certificate) certificate).getSubjectDN());
- } finally {
- caInput.close();
- }
- } catch (CertificateException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- return null;
- } catch (IllegalArgumentException e) {
- return null;
- }
-
- return (X509Certificate) certificate;
- }
-
- protected static RSAPrivateKey parseRsaKeyFromString(String RsaKeyString) {
- RSAPrivateKey key = null;
- try {
- KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
-
- RsaKeyString = RsaKeyString.replaceFirst("-----BEGIN RSA PRIVATE KEY-----", "").replaceFirst("-----END RSA PRIVATE KEY-----", "");
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec( Base64.decode(RsaKeyString, Base64.DEFAULT) );
- 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 (NoSuchProviderException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return null;
- }
-
- return key;
- }
-
- /**
- * Adds a new X509 certificate given its input stream and its provider name
- * @param provider used to store the certificate in the keystore
- * @param inputStream from which X509 certificate must be generated.
- */
- public static void addTrustedCertificate(String provider, InputStream inputStream) {
- CertificateFactory cf;
- try {
- cf = CertificateFactory.getInstance("X.509");
- X509Certificate cert =
- (X509Certificate)cf.generateCertificate(inputStream);
- keystore_trusted.setCertificateEntry(provider, cert);
- } catch (CertificateException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (KeyStoreException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- /**
- * Adds a new X509 certificate given in its string from and using its provider name
- * @param provider used to store the certificate in the keystore
- * @param certificate
- */
- public static void addTrustedCertificate(String provider, String certificate) {
-
- try {
- X509Certificate cert = ConfigHelper.parseX509CertificateFromString(certificate);
- if(keystore_trusted == null) {
- keystore_trusted = KeyStore.getInstance("BKS");
- keystore_trusted.load(null);
- }
- keystore_trusted.setCertificateEntry(provider, cert);
- } catch (KeyStoreException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (NoSuchAlgorithmException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (CertificateException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- /**
- * @return class wide keystore
- */
- public static KeyStore getKeystore() {
- return keystore_trusted;
- }
+
+ public static boolean checkErroneousDownload(String downloaded_string) {
+ try {
+ if (new JSONObject(downloaded_string).has(ProviderAPI.ERRORS) || downloaded_string.isEmpty()) {
+ return true;
+ } else {
+ return false;
+ }
+ } catch (JSONException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Treat the input as the MSB representation of a number,
+ * and lop off leading zero elements. For efficiency, the
+ * input is simply returned if no leading zeroes are found.
+ *
+ * @param in array to be trimmed
+ */
+ public static byte[] trim(byte[] in) {
+ if (in.length == 0 || in[0] != 0)
+ return in;
+
+ int len = in.length;
+ int i = 1;
+ while (in[i] == 0 && i < len)
+ ++i;
+ byte[] ret = new byte[len - i];
+ System.arraycopy(in, i, ret, 0, len - i);
+ return ret;
+ }
+
+ public static X509Certificate parseX509CertificateFromString(String certificate_string) {
+ java.security.cert.Certificate certificate = null;
+ CertificateFactory cf;
+ try {
+ cf = CertificateFactory.getInstance("X.509");
+
+ certificate_string = certificate_string.replaceFirst("-----BEGIN CERTIFICATE-----", "").replaceFirst("-----END CERTIFICATE-----", "").trim();
+ byte[] cert_bytes = Base64.decode(certificate_string, Base64.DEFAULT);
+ InputStream caInput = new ByteArrayInputStream(cert_bytes);
+ try {
+ certificate = cf.generateCertificate(caInput);
+ System.out.println("ca=" + ((X509Certificate) certificate).getSubjectDN());
+ } finally {
+ caInput.close();
+ }
+ } catch (CertificateException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ return null;
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+
+ return (X509Certificate) certificate;
+ }
+
+ protected static RSAPrivateKey parseRsaKeyFromString(String RsaKeyString) {
+ RSAPrivateKey key = null;
+ try {
+ KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
+
+ RsaKeyString = RsaKeyString.replaceFirst("-----BEGIN RSA PRIVATE KEY-----", "").replaceFirst("-----END RSA PRIVATE KEY-----", "");
+ PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(RsaKeyString, Base64.DEFAULT));
+ 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 (NoSuchProviderException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ }
+
+ return key;
+ }
+
+ /**
+ * Adds a new X509 certificate given its input stream and its provider name
+ *
+ * @param provider used to store the certificate in the keystore
+ * @param inputStream from which X509 certificate must be generated.
+ */
+ public static void addTrustedCertificate(String provider, InputStream inputStream) {
+ CertificateFactory cf;
+ try {
+ cf = CertificateFactory.getInstance("X.509");
+ X509Certificate cert =
+ (X509Certificate) cf.generateCertificate(inputStream);
+ keystore_trusted.setCertificateEntry(provider, cert);
+ } catch (CertificateException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (KeyStoreException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Adds a new X509 certificate given in its string from and using its provider name
+ *
+ * @param provider used to store the certificate in the keystore
+ * @param certificate
+ */
+ public static void addTrustedCertificate(String provider, String certificate) {
+
+ try {
+ X509Certificate cert = ConfigHelper.parseX509CertificateFromString(certificate);
+ if (keystore_trusted == null) {
+ keystore_trusted = KeyStore.getInstance("BKS");
+ keystore_trusted.load(null);
+ }
+ keystore_trusted.setCertificateEntry(provider, cert);
+ } catch (KeyStoreException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (NoSuchAlgorithmException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (CertificateException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @return class wide keystore
+ */
+ public static KeyStore getKeystore() {
+ return keystore_trusted;
+ }
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
index 6d368e11..ee64a1b3 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
@@ -1,6 +1,6 @@
/**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -16,18 +16,20 @@
*/
package se.leap.bitmaskclient;
-import android.annotation.SuppressLint;
+import android.annotation.*;
import android.app.*;
import android.content.*;
-import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManager.*;
import android.os.*;
-import android.util.Log;
+import android.util.*;
import android.view.*;
import android.widget.*;
-import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.*;
import org.json.*;
+
import java.net.*;
+import java.util.*;
import butterknife.*;
import de.blinkt.openvpn.activities.*;
@@ -36,11 +38,11 @@ import se.leap.bitmaskclient.eip.*;
/**
* The main user facing Activity of Bitmask Android, consisting of status, controls,
* and access to preferences.
- *
+ *
* @author Sean Leonard <meanderingcode@aetherislands.net>
* @author parmegv
*/
-public class Dashboard extends Activity implements SessionDialog.SessionDialogInterface, ProviderAPIResultReceiver.Receiver {
+public class Dashboard extends Activity implements SessionDialog.SessionDialogInterface, ProviderAPIResultReceiver.Receiver, Observer {
protected static final int CONFIGURE_LEAP = 0;
protected static final int SWITCH_PROVIDER = 1;
@@ -60,47 +62,65 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn
@InjectView(R.id.providerName)
TextView provider_name;
+ @InjectView(R.id.user_session_status)
+ TextView user_session_status_text_view;
+ @InjectView(R.id.user_session_status_progress)
+ ProgressBar user_session_status_progress_bar;
EipFragment eip_fragment;
private Provider provider;
- private static boolean authed_eip;
+ private UserSessionStatus user_session_status;
public ProviderAPIResultReceiver providerAPI_result_receiver;
private boolean switching_provider;
@Override
protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- app = this;
+ super.onCreate(savedInstanceState);
+
+ app = this;
+ user_session_status = UserSessionStatus.getInstance();
+ user_session_status.addObserver(this);
- PRNGFixes.apply();
+ PRNGFixes.apply();
- preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
- fragment_manager = new FragmentManagerEnhanced(getFragmentManager());
- handleVersion();
+ preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
+ fragment_manager = new FragmentManagerEnhanced(getFragmentManager());
+ handleVersion();
- provider = getSavedProvider(savedInstanceState);
+ restoreProvider(savedInstanceState);
if (provider == null || provider.getName().isEmpty())
- startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP);
- else
- buildDashboard(getIntent().getBooleanExtra(ON_BOOT, false));
+ startActivityForResult(new Intent(this, ConfigurationWizard.class), CONFIGURE_LEAP);
+ else {
+ buildDashboard(getIntent().getBooleanExtra(ON_BOOT, false));
+ restoreSessionStatus(savedInstanceState);
+ }
+ }
+
+ private void restoreProvider(Bundle savedInstanceState) {
+ if (savedInstanceState != null) {
+ if (savedInstanceState.containsKey(Provider.KEY))
+ provider = savedInstanceState.getParcelable(Provider.KEY);
+ }
+ if (provider == null && preferences.getBoolean(Constants.PROVIDER_CONFIGURED, false))
+ provider = getSavedProviderFromSharedPreferences();
+ }
+
+ private void restoreSessionStatus(Bundle savedInstanceState) {
+ if (savedInstanceState != null)
+ if (savedInstanceState.containsKey(UserSessionStatus.TAG)) {
+ UserSessionStatus.SessionStatus status = (UserSessionStatus.SessionStatus) savedInstanceState.getSerializable(UserSessionStatus.TAG);
+ user_session_status.updateStatus(status);
+ }
}
@Override
protected void onSaveInstanceState(@NotNull Bundle outState) {
- if(provider != null)
+ if (provider != null)
outState.putParcelable(Provider.KEY, provider);
- super.onSaveInstanceState(outState);
- }
-
- private Provider getSavedProvider(Bundle savedInstanceState) {
- Provider provider = null;
- if(savedInstanceState != null)
- provider = savedInstanceState.getParcelable(Provider.KEY);
- else if(preferences.getBoolean(Constants.PROVIDER_CONFIGURED, false))
- provider = getSavedProviderFromSharedPreferences();
+ if (user_session_status_text_view != null && user_session_status_text_view.getVisibility() == TextView.VISIBLE)
+ outState.putSerializable(UserSessionStatus.TAG, user_session_status.sessionStatus());
- return provider;
+ super.onSaveInstanceState(outState);
}
private Provider getSavedProviderFromSharedPreferences() {
@@ -108,9 +128,7 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn
try {
provider = new Provider(new URL(preferences.getString(Provider.MAIN_URL, "")));
provider.define(new JSONObject(preferences.getString(Provider.KEY, "")));
- } catch (MalformedURLException e) {
- e.printStackTrace();
- } catch (JSONException e) {
+ } catch (MalformedURLException | JSONException e) {
e.printStackTrace();
}
@@ -118,27 +136,27 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn
}
private void handleVersion() {
- try {
- int versionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode;
- int lastDetectedVersion = preferences.getInt(APP_VERSION, 0);
- preferences.edit().putInt(APP_VERSION, versionCode).apply();
-
- switch(versionCode) {
- case 91: // 0.6.0 without Bug #5999
- case 101: // 0.8.0
- if(!preferences.getString(Constants.KEY, "").isEmpty())
- eip_fragment.updateEipService();
- break;
- }
- } catch (NameNotFoundException e) {
- Log.d(TAG, "Handle version didn't find any " + getPackageName() + " package");
- }
+ try {
+ int versionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode;
+ int lastDetectedVersion = preferences.getInt(APP_VERSION, 0);
+ preferences.edit().putInt(APP_VERSION, versionCode).apply();
+
+ switch (versionCode) {
+ case 91: // 0.6.0 without Bug #5999
+ case 101: // 0.8.0
+ if (!preferences.getString(Constants.KEY, "").isEmpty())
+ eip_fragment.updateEipService();
+ break;
+ }
+ } catch (NameNotFoundException e) {
+ Log.d(TAG, "Handle version didn't find any " + getPackageName() + " package");
+ }
}
@Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data){
- if ( requestCode == CONFIGURE_LEAP || requestCode == SWITCH_PROVIDER) {
- if ( resultCode == RESULT_OK && data.hasExtra(Provider.KEY)) {
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == CONFIGURE_LEAP || requestCode == SWITCH_PROVIDER) {
+ if (resultCode == RESULT_OK && data.hasExtra(Provider.KEY)) {
provider = data.getParcelableExtra(Provider.KEY);
providerToPreferences(provider);
@@ -148,14 +166,13 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn
sessionDialog(Bundle.EMPTY);
}
- preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply();
- } else if (resultCode == RESULT_CANCELED && data.hasExtra(ACTION_QUIT)) {
+ } else if (resultCode == RESULT_CANCELED && data.hasExtra(ACTION_QUIT)) {
finish();
- } else
- configErrorDialog();
- } else if(requestCode == EIP.DISCONNECT) {
- EipStatus.getInstance().setConnectedOrDisconnected();
- }
+ } else
+ configErrorDialog();
+ } else if (requestCode == EIP.DISCONNECT) {
+ EipStatus.getInstance().setConnectedOrDisconnected();
+ }
}
@SuppressLint("CommitPrefEdits")
@@ -166,197 +183,237 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn
}
private void configErrorDialog() {
- AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getAppContext());
- alertBuilder.setTitle(getResources().getString(R.string.setup_error_title));
- alertBuilder
- .setMessage(getResources().getString(R.string.setup_error_text))
- .setCancelable(false)
- .setPositiveButton(getResources().getString(R.string.setup_error_configure_button), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- startActivityForResult(new Intent(getAppContext(),ConfigurationWizard.class),CONFIGURE_LEAP);
- }
- })
- .setNegativeButton(getResources().getString(R.string.setup_error_close_button), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- preferences.edit().remove(Provider.KEY).remove(Constants.PROVIDER_CONFIGURED).apply();
- finish();
- }
- })
- .show();
- }
-
+ AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getContext());
+ alertBuilder.setTitle(getResources().getString(R.string.setup_error_title));
+ alertBuilder
+ .setMessage(getResources().getString(R.string.setup_error_text))
+ .setCancelable(false)
+ .setPositiveButton(getResources().getString(R.string.setup_error_configure_button), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ startActivityForResult(new Intent(getContext(), ConfigurationWizard.class), CONFIGURE_LEAP);
+ }
+ })
+ .setNegativeButton(getResources().getString(R.string.setup_error_close_button), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ preferences.edit().remove(Provider.KEY).remove(Constants.PROVIDER_CONFIGURED).apply();
+ finish();
+ }
+ })
+ .show();
+ }
+
/**
* Inflates permanent UI elements of the View and contains logic for what
* service dependent UI elements to include.
*/
private void buildDashboard(boolean hide_and_turn_on_eip) {
- setContentView(R.layout.dashboard);
+ setContentView(R.layout.dashboard);
ButterKnife.inject(this);
- provider_name.setText(provider.getDomain());
- if ( provider.hasEIP()){
+ provider_name.setText(provider.getDomain());
+ if (provider.hasEIP()) {
fragment_manager.removePreviousFragment(EipFragment.TAG);
eip_fragment = new EipFragment();
- if (hide_and_turn_on_eip) {
- preferences.edit().remove(Dashboard.START_ON_BOOT).apply();
- Bundle arguments = new Bundle();
- arguments.putBoolean(EipFragment.START_ON_BOOT, true);
- if(eip_fragment != null) eip_fragment.setArguments(arguments);
- }
+ if (hide_and_turn_on_eip) {
+ preferences.edit().remove(Dashboard.START_ON_BOOT).apply();
+ Bundle arguments = new Bundle();
+ arguments.putBoolean(EipFragment.START_ON_BOOT, true);
+ if (eip_fragment != null) eip_fragment.setArguments(arguments);
+ }
fragment_manager.replace(R.id.servicesCollection, eip_fragment, EipFragment.TAG);
- if (hide_and_turn_on_eip) {
- onBackPressed();
- }
- }
+ if (hide_and_turn_on_eip) {
+ onBackPressed();
+ }
+ }
+ handleNewUserSessionStatus(user_session_status);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
- JSONObject provider_json;
- try {
- String provider_json_string = preferences.getString(Provider.KEY, "");
- if(!provider_json_string.isEmpty()) {
- provider_json = new JSONObject(provider_json_string);
- JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE);
- boolean authed_eip = !LeapSRPSession.getToken().isEmpty();
- boolean allow_registered_eip = service_description.getBoolean(Provider.ALLOW_REGISTRATION);
- preferences.edit().putBoolean(Constants.ALLOWED_REGISTERED, allow_registered_eip).apply();
-
- if(allow_registered_eip) {
- if(authed_eip) {
- menu.findItem(R.id.login_button).setVisible(false);
- menu.findItem(R.id.logout_button).setVisible(true);
- } else {
- menu.findItem(R.id.login_button).setVisible(true);
- menu.findItem(R.id.logout_button).setVisible(false);
- }
- menu.findItem(R.id.signup_button).setVisible(true);
- }
- }
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return true;
+ if (provider.allowsRegistration()) {
+ menu.findItem(R.id.signup_button).setVisible(true);
+
+ boolean logged_in = User.loggedIn();
+ menu.findItem(R.id.login_button).setVisible(!logged_in);
+ menu.findItem(R.id.logout_button).setVisible(logged_in);
+ }
+ return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.client_dashboard, menu);
- return true;
+ getMenuInflater().inflate(R.menu.client_dashboard, menu);
+ return true;
}
-
+
@Override
- public boolean onOptionsItemSelected(MenuItem item){
- Intent intent;
- switch (item.getItemId()){
- case R.id.about_leap:
- intent = new Intent(this, AboutActivity.class);
- startActivity(intent);
- return true;
- case R.id.log_window:
- Intent startLW = new Intent(getAppContext(), LogWindow.class);
- startLW.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
- startActivity(startLW);
- return true;
- case R.id.switch_provider:
- switching_provider = true;
- if (preferences.getBoolean(Constants.AUTHED_EIP, false)) logOut();
- else switchProvider();
- return true;
- case R.id.login_button:
- sessionDialog(Bundle.EMPTY);
- return true;
- case R.id.logout_button:
- logOut();
- return true;
- case R.id.signup_button:
- sessionDialog(Bundle.EMPTY);
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.about_leap:
+ showAbout();
+ return true;
+ case R.id.log_window:
+ showLog();
+ return true;
+ case R.id.switch_provider:
+ switching_provider = true;
+ if (LeapSRPSession.loggedIn()) logOut();
+ else switchProvider();
+ return true;
+ case R.id.login_button:
+ sessionDialog(Bundle.EMPTY);
+ return true;
+ case R.id.logout_button:
+ logOut();
+ return true;
+ case R.id.signup_button:
+ sessionDialog(Bundle.EMPTY);
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ public void showAbout() {
+ Intent intent = new Intent(this, AboutActivity.class);
+ startActivity(intent);
+ }
+
+ public void showLog() {
+ Intent startLW = new Intent(getContext(), LogWindow.class);
+ startActivity(startLW);
}
@Override
public void signUp(String username, String password) {
- Bundle parameters = bundleParameters(username, password);
- providerApiCommand(parameters, R.string.signingup_message, ProviderAPI.SRP_REGISTER);
+ User.setUserName(username);
+ Bundle parameters = bundlePassword(password);
+ providerApiCommand(parameters, 0, ProviderAPI.SIGN_UP);
}
@Override
public void logIn(String username, String password) {
- Bundle parameters = bundleParameters(username, password);
- providerApiCommand(parameters, R.string.authenticating_message, ProviderAPI.SRP_AUTH);
+ User.setUserName(username);
+ Bundle parameters = bundlePassword(password);
+ providerApiCommand(parameters, 0, ProviderAPI.LOG_IN);
}
-
+
public void logOut() {
- providerApiCommand(Bundle.EMPTY, R.string.logout_message, ProviderAPI.LOG_OUT);
+ providerApiCommand(Bundle.EMPTY, 0, ProviderAPI.LOG_OUT);
+ }
+
+ @Override
+ public void update(Observable observable, Object data) {
+ if (observable instanceof UserSessionStatus) {
+ UserSessionStatus status = (UserSessionStatus) observable;
+ handleNewUserSessionStatus(status);
+ }
+ }
+
+ private void handleNewUserSessionStatus(UserSessionStatus status) {
+ user_session_status = status;
+ if (provider.allowsRegistration()) {
+ if (user_session_status.inProgress())
+ showUserSessionProgressBar();
+ else
+ hideUserSessionProgressBar();
+ changeSessionStatusMessage(user_session_status.toString());
+ invalidateOptionsMenu();
+ }
+ }
+
+ private void changeSessionStatusMessage(final String message) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ user_session_status_text_view.setText(message);
+ }
+ });
+ }
+
+ private void showUserSessionProgressBar() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ user_session_status_progress_bar.setVisibility(ProgressBar.VISIBLE);
+ }
+ });
+ }
+
+ private void hideUserSessionProgressBar() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ user_session_status_progress_bar.setVisibility(ProgressBar.GONE);
+ }
+ });
}
protected void downloadVpnCertificate() {
- boolean is_authenticated = !LeapSRPSession.getToken().isEmpty();
+ boolean is_authenticated = LeapSRPSession.loggedIn();
boolean allowed_anon = preferences.getBoolean(Constants.ALLOWED_ANON, false);
- if(allowed_anon || is_authenticated)
+ if (allowed_anon || is_authenticated)
providerApiCommand(Bundle.EMPTY, R.string.downloading_certificate_message, ProviderAPI.DOWNLOAD_CERTIFICATE);
else
sessionDialog(Bundle.EMPTY);
}
- private Bundle bundleParameters(String username, String password) {
+ private Bundle bundlePassword(String password) {
Bundle parameters = new Bundle();
- if(!username.isEmpty())
- parameters.putString(SessionDialog.USERNAME, username);
- if(!password.isEmpty())
- parameters.putString(SessionDialog.PASSWORD, password);
- return parameters;
+ if (!password.isEmpty())
+ parameters.putString(SessionDialog.PASSWORD, password);
+ return parameters;
}
protected void providerApiCommand(Bundle parameters, int progressbar_message_resId, String providerApi_action) {
- if(eip_fragment != null && progressbar_message_resId != 0) {
+ if (eip_fragment != null && progressbar_message_resId != 0) {
eip_fragment.progress_bar.setVisibility(ProgressBar.VISIBLE);
setStatusMessage(progressbar_message_resId);
}
-
- Intent command = prepareProviderAPICommand(parameters, providerApi_action);
- startService(command);
+
+ Intent command = prepareProviderAPICommand(parameters, providerApi_action);
+ startService(command);
}
private Intent prepareProviderAPICommand(Bundle parameters, String action) {
- providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
- providerAPI_result_receiver.setReceiver(this);
-
- Intent command = new Intent(this, ProviderAPI.class);
-
- command.putExtra(ProviderAPI.PARAMETERS, parameters);
- command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver);
- command.setAction(action);
- return command;
+ providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
+ providerAPI_result_receiver.setReceiver(this);
+
+ Intent command = new Intent(this, ProviderAPI.class);
+
+ command.putExtra(ProviderAPI.PARAMETERS, parameters);
+ command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver);
+ command.setAction(action);
+ return command;
}
public void cancelLoginOrSignup() {
- EipStatus.getInstance().setConnectedOrDisconnected();
+ EipStatus.getInstance().setConnectedOrDisconnected();
}
-
+
public void sessionDialog(Bundle resultData) {
-
- FragmentTransaction transaction = fragment_manager.removePreviousFragment(SessionDialog.TAG);
- DialogFragment newFragment = new SessionDialog();
- if(resultData != null && !resultData.isEmpty()) {
- newFragment.setArguments(resultData);
- }
- newFragment.show(transaction, SessionDialog.TAG);
+ FragmentTransaction transaction = fragment_manager.removePreviousFragment(SessionDialog.TAG);
+
+ DialogFragment newFragment = new SessionDialog();
+ if (provider.getName().equalsIgnoreCase("riseup")) {
+ resultData = resultData == Bundle.EMPTY ? new Bundle() : resultData;
+ resultData.putBoolean(SessionDialog.ERRORS.RISEUP_WARNING.toString(), true);
+ }
+ if (resultData != null && !resultData.isEmpty()) {
+ newFragment.setArguments(resultData);
+ }
+ newFragment.show(transaction, SessionDialog.TAG);
}
private void switchProvider() {
- if (provider.hasEIP()) eip_fragment.askToStopEIP();
-
+ if (provider.hasEIP()) eip_fragment.stopEipIfPossible();
+
preferences.edit().clear().apply();
switching_provider = false;
startActivityForResult(new Intent(this, ConfigurationWizard.class), SWITCH_PROVIDER);
@@ -364,113 +421,43 @@ public class Dashboard extends Activity implements SessionDialog.SessionDialogIn
@Override
public void onReceiveResult(int resultCode, Bundle resultData) {
- Log.d(TAG, "onReceiveResult");
- if(resultCode == ProviderAPI.SUCCESSFUL_SIGNUP) {
- String username = resultData.getString(SessionDialog.USERNAME);
- String password = resultData.getString(SessionDialog.PASSWORD);
- logIn(username, password);
- } else if(resultCode == ProviderAPI.FAILED_SIGNUP) {
- updateViewHidingProgressBar(resultCode);
- sessionDialog(resultData);
- } else if(resultCode == ProviderAPI.SUCCESSFUL_LOGIN) {
- authed_eip = true;
- preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply();
-
- updateViewHidingProgressBar(resultCode);
- downloadVpnCertificate();
- } else if(resultCode == ProviderAPI.FAILED_LOGIN) {
- updateViewHidingProgressBar(resultCode);
- sessionDialog(resultData);
- } else if(resultCode == ProviderAPI.SUCCESSFUL_LOGOUT) {
- authed_eip = false;
- preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply();
-
- updateViewHidingProgressBar(resultCode);
- if(switching_provider) switchProvider();
- } else if(resultCode == ProviderAPI.LOGOUT_FAILED) {
- updateViewHidingProgressBar(resultCode);
- setResult(RESULT_CANCELED);
- } else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) {
- updateViewHidingProgressBar(resultCode);
- eip_fragment.updateEipService();
- setResult(RESULT_OK);
- } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) {
- updateViewHidingProgressBar(resultCode);
- setResult(RESULT_CANCELED);
- }
- else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE) {
- eip_fragment.updateEipService();
- setResult(RESULT_OK);
- } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE) {
- setResult(RESULT_CANCELED);
- }
- }
-
- private void updateViewHidingProgressBar(int resultCode) {
- changeStatusMessage(resultCode);
- hideProgressBar();
- invalidateOptionsMenu();
- }
-
- private void changeStatusMessage(final int previous_result_code) {
- ResultReceiver status_receiver = new ResultReceiver(new Handler()){
- protected void onReceiveResult(int resultCode, Bundle resultData){
- super.onReceiveResult(resultCode, resultData);
- String request = resultData.getString(Constants.REQUEST_TAG);
- if (request.equalsIgnoreCase(Constants.ACTION_IS_EIP_RUNNING)){
- if (resultCode == Activity.RESULT_OK){
- switch(previous_result_code){
- case ProviderAPI.SUCCESSFUL_LOGIN: setStatusMessage(R.string.succesful_authentication_message); break;
- case ProviderAPI.FAILED_LOGIN: setStatusMessage(R.string.authentication_failed_message); break;
- case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: setStatusMessage(R.string.authed_secured_status); break;
- case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: setStatusMessage(R.string.incorrectly_downloaded_certificate_message); break;
- case ProviderAPI.SUCCESSFUL_LOGOUT: setStatusMessage(R.string.logged_out_message); break;
- case ProviderAPI.LOGOUT_FAILED: setStatusMessage(R.string.log_out_failed_message); break;
-
- }
- }
- else if(resultCode == Activity.RESULT_CANCELED){
- switch(previous_result_code){
- case ProviderAPI.SUCCESSFUL_LOGIN: setStatusMessage(R.string.succesful_authentication_message); break;
- case ProviderAPI.FAILED_LOGIN: setStatusMessage(R.string.authentication_failed_message); break;
- case ProviderAPI.FAILED_SIGNUP: setStatusMessage(R.string.registration_failed_message); break;
- case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: break;
- case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: setStatusMessage(R.string.incorrectly_downloaded_certificate_message); break;
- case ProviderAPI.SUCCESSFUL_LOGOUT: setStatusMessage(R.string.logged_out_message); break;
- case ProviderAPI.LOGOUT_FAILED: setStatusMessage(R.string.log_out_failed_message); break;
- }
- }
- }
-
- }
- };
- eipIsRunning(status_receiver);
+ if (resultCode == ProviderAPI.SUCCESSFUL_SIGNUP) {
+ String username = resultData.getString(SessionDialog.USERNAME);
+ String password = resultData.getString(SessionDialog.PASSWORD);
+ logIn(username, password);
+ } else if (resultCode == ProviderAPI.FAILED_SIGNUP) {
+ sessionDialog(resultData);
+ } else if (resultCode == ProviderAPI.SUCCESSFUL_LOGIN) {
+ downloadVpnCertificate();
+ } else if (resultCode == ProviderAPI.FAILED_LOGIN) {
+ sessionDialog(resultData);
+ } else if (resultCode == ProviderAPI.SUCCESSFUL_LOGOUT) {
+ if (switching_provider) switchProvider();
+ } else if (resultCode == ProviderAPI.LOGOUT_FAILED) {
+ setResult(RESULT_CANCELED);
+ } else if (resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) {
+ eip_fragment.updateEipService();
+ eip_fragment.handleNewVpnCertificate();
+ setResult(RESULT_OK);
+ } else if (resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) {
+ setResult(RESULT_CANCELED);
+ } else if (resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE) {
+ eip_fragment.updateEipService();
+ setResult(RESULT_OK);
+ } else if (resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE) {
+ setResult(RESULT_CANCELED);
+ }
}
private void setStatusMessage(int string_resId) {
- if(eip_fragment != null && eip_fragment.status_message != null)
- eip_fragment.status_message.setText(string_resId);
+ if (eip_fragment != null && eip_fragment.status_message != null)
+ eip_fragment.status_message.setText(string_resId);
}
- private void eipIsRunning(ResultReceiver eip_receiver){
- // TODO validate "action"...how do we get the list of intent-filters for a class via Android API?
- Intent intent = new Intent(this, EIP.class);
- intent.setAction(Constants.ACTION_IS_EIP_RUNNING);
- intent.putExtra(Constants.RECEIVER_TAG, eip_receiver);
- startService(intent);
+ public static Context getContext() {
+ return app;
}
- private void hideProgressBar() {
- if(eip_fragment != null) {
- eip_fragment.progress_bar.setProgress(0);
- eip_fragment.progress_bar.setVisibility(ProgressBar.GONE);
- }
- }
-
- public static Context getAppContext() {
- return app;
- }
-
@Override
public void startActivityForResult(Intent intent, int requestCode) {
intent.putExtra(Dashboard.REQUEST_CODE, requestCode);
diff --git a/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java b/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java
index a44253c6..da32dbd4 100644
--- a/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java
@@ -1,6 +1,6 @@
/**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -16,76 +16,74 @@
*/
package se.leap.bitmaskclient;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.content.DialogInterface;
-import android.os.Bundle;
+import android.app.*;
+import android.content.*;
+import android.os.*;
/**
* Implements a dialog to show why a download failed.
- *
- * @author parmegv
*
+ * @author parmegv
*/
public class DownloadFailedDialog extends DialogFragment {
- public static String TAG = "downloaded_failed_dialog";
- private String reason_to_fail;
- /**
- * @return a new instance of this DialogFragment.
- */
- public static DialogFragment newInstance(String reason_to_fail) {
- DownloadFailedDialog dialog_fragment = new DownloadFailedDialog();
- dialog_fragment.reason_to_fail = reason_to_fail;
- return dialog_fragment;
- }
+ public static String TAG = "downloaded_failed_dialog";
+ private String reason_to_fail;
+
+ /**
+ * @return a new instance of this DialogFragment.
+ */
+ public static DialogFragment newInstance(String reason_to_fail) {
+ DownloadFailedDialog dialog_fragment = new DownloadFailedDialog();
+ dialog_fragment.reason_to_fail = reason_to_fail;
+ return dialog_fragment;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setMessage(reason_to_fail)
+ .setPositiveButton(R.string.retry, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dismiss();
+ interface_with_ConfigurationWizard.retrySetUpProvider();
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ interface_with_ConfigurationWizard.cancelSettingUpProvider();
+ dialog.dismiss();
+ }
+ });
- builder.setMessage(reason_to_fail)
- .setPositiveButton(R.string.retry, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- dismiss();
- interface_with_ConfigurationWizard.retrySetUpProvider();
- }
- })
- .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- interface_with_ConfigurationWizard.cancelSettingUpProvider();
- dialog.dismiss();
- }
- });
+ // Create the AlertDialog object and return it
+ return builder.create();
+ }
- // Create the AlertDialog object and return it
- return builder.create();
- }
+ public interface DownloadFailedDialogInterface {
+ public void retrySetUpProvider();
- public interface DownloadFailedDialogInterface {
- public void retrySetUpProvider();
- public void cancelSettingUpProvider();
- }
+ public void cancelSettingUpProvider();
+ }
- DownloadFailedDialogInterface interface_with_ConfigurationWizard;
+ DownloadFailedDialogInterface interface_with_ConfigurationWizard;
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- try {
- interface_with_ConfigurationWizard = (DownloadFailedDialogInterface) activity;
- } catch (ClassCastException e) {
- throw new ClassCastException(activity.toString()
- + " must implement NoticeDialogListener");
- }
- }
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ try {
+ interface_with_ConfigurationWizard = (DownloadFailedDialogInterface) activity;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(activity.toString()
+ + " must implement NoticeDialogListener");
+ }
+ }
- @Override
- public void onCancel(DialogInterface dialog) {
- interface_with_ConfigurationWizard.cancelSettingUpProvider();
- dialog.dismiss();
- }
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ interface_with_ConfigurationWizard.cancelSettingUpProvider();
+ dialog.dismiss();
+ }
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
index 588b137b..02eedd77 100644
--- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java
@@ -1,35 +1,38 @@
+/**
+ * Copyright (c) 2013 LEAP Encryption Access Project and contributers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
package se.leap.bitmaskclient;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Fragment;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ResultReceiver;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ProgressBar;
-import android.widget.Switch;
-import android.widget.TextView;
-
-import java.util.Observable;
-import java.util.Observer;
-
-import butterknife.ButterKnife;
-import butterknife.InjectView;
-import butterknife.OnCheckedChanged;
-import de.blinkt.openvpn.activities.DisconnectVPN;
-import se.leap.bitmaskclient.eip.Constants;
-import se.leap.bitmaskclient.eip.EIP;
-import se.leap.bitmaskclient.eip.EipStatus;
-import se.leap.bitmaskclient.eip.VoidVpnService;
+import android.app.*;
+import android.content.*;
+import android.os.*;
+import android.util.*;
+import android.view.*;
+import android.widget.*;
+
+import org.jetbrains.annotations.*;
+
+import java.util.*;
+
+import butterknife.*;
+import de.blinkt.openvpn.activities.*;
+import se.leap.bitmaskclient.eip.*;
public class EipFragment extends Fragment implements Observer {
-
+
public static String TAG = EipFragment.class.getSimpleName();
protected static final String IS_PENDING = TAG + ".is_pending";
@@ -50,316 +53,347 @@ public class EipFragment extends Fragment implements Observer {
private boolean is_starting_to_connect;
private boolean wants_to_connect;
- @Override
public void onAttach(Activity activity) {
- super.onAttach(activity);
+ super.onAttach(activity);
dashboard = (Dashboard) activity;
dashboard.providerApiCommand(Bundle.EMPTY, 0, ProviderAPI.DOWNLOAD_EIP_SERVICE);
}
-
+
@Override
public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- eip_status = EipStatus.getInstance();
- eip_status.addObserver(this);
- mEIPReceiver = new EIPReceiver(new Handler());
+ super.onCreate(savedInstanceState);
+ eip_status = EipStatus.getInstance();
+ eip_status.addObserver(this);
+ mEIPReceiver = new EIPReceiver(new Handler());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.eip_service_fragment, container, false);
+ View view = inflater.inflate(R.layout.eip_service_fragment, container, false);
ButterKnife.inject(this, view);
- if (eip_status.isConnecting())
- eip_switch.setVisibility(View.VISIBLE);
-
- Log.d(TAG, "onCreateView, eip_switch is checked? " + eip_switch.isChecked());
+ if (eip_status.isConnecting())
+ eip_switch.setVisibility(View.VISIBLE);
Bundle arguments = getArguments();
- if(arguments != null && arguments.containsKey(START_ON_BOOT) && arguments.getBoolean(START_ON_BOOT))
- startEipFromScratch();
+ if (arguments != null && arguments.containsKey(START_ON_BOOT) && arguments.getBoolean(START_ON_BOOT))
+ startEipFromScratch();
+ if (savedInstanceState != null) restoreState(savedInstanceState);
+
+ return view;
+ }
- if (savedInstanceState != null) {
+ private void restoreState(@NotNull Bundle savedInstanceState) {
+ if (savedInstanceState.getBoolean(IS_PENDING))
+ eip_status.setConnecting();
+ else if (savedInstanceState.getBoolean(IS_CONNECTED))
+ eip_status.setConnectedOrDisconnected();
+ else
status_message.setText(savedInstanceState.getString(STATUS_MESSAGE));
- if(savedInstanceState.getBoolean(IS_PENDING))
- eip_status.setConnecting();
- else if(savedInstanceState.getBoolean(IS_CONNECTED)) {
- eip_status.setConnectedOrDisconnected();
- }
- }
- return view;
}
@Override
public void onResume() {
- super.onResume();
- eipCommand(Constants.ACTION_CHECK_CERT_VALIDITY);
- handleNewState(eip_status);
+ super.onResume();
+ eipCommand(Constants.ACTION_CHECK_CERT_VALIDITY);
+ handleNewState(eip_status);
}
-
+
@Override
public void onSaveInstanceState(Bundle outState) {
- outState.putBoolean(IS_PENDING, eip_status.isConnecting());
- outState.putBoolean(IS_CONNECTED, eip_status.isConnected());
- Log.d(TAG, "status message onSaveInstanceState = " + status_message.getText().toString());
- outState.putString(STATUS_MESSAGE, status_message.getText().toString());
- super.onSaveInstanceState(outState);
+ outState.putBoolean(IS_PENDING, eip_status.isConnecting());
+ outState.putBoolean(IS_CONNECTED, eip_status.isConnected());
+ outState.putString(STATUS_MESSAGE, status_message.getText().toString());
+ super.onSaveInstanceState(outState);
}
protected void saveStatus() {
- boolean is_on = eip_switch.isChecked();
- Log.d(TAG, "saveStatus: is_on = " + is_on);
- Dashboard.preferences.edit().putBoolean(Dashboard.START_ON_BOOT, is_on).commit();
+ boolean is_on = eip_switch.isChecked();
+ Dashboard.preferences.edit().putBoolean(Dashboard.START_ON_BOOT, is_on).commit();
+ }
+
+ void handleNewVpnCertificate() {
+ handleSwitch(!eip_switch.isEnabled());
}
@OnCheckedChanged(R.id.eipSwitch)
void handleSwitch(boolean isChecked) {
- if(isChecked)
- handleSwitchOn();
- else
- handleSwitchOff();
-
- saveStatus();
+ if (isChecked)
+ handleSwitchOn();
+ else
+ handleSwitchOff();
+
+ saveStatus();
}
private void handleSwitchOn() {
- if(canStartEIP())
- startEipFromScratch();
- else if(canLogInToStartEIP()) {
- wants_to_connect = true;
- Bundle bundle = new Bundle();
- bundle.putBoolean(IS_PENDING, true);
- dashboard.sessionDialog(bundle);
- }
- }
-
+ if (canStartEIP())
+ startEipFromScratch();
+ else if (canLogInToStartEIP()) {
+ wants_to_connect = true;
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(IS_PENDING, true);
+ dashboard.sessionDialog(bundle);
+ }
+ }
+
private boolean canStartEIP() {
- boolean certificateExists = !Dashboard.preferences.getString(Constants.CERTIFICATE, "").isEmpty();
- boolean isAllowedAnon = Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false);
- return (isAllowedAnon || certificateExists) && !eip_status.isConnected() && !eip_status.isConnecting();
+ boolean certificateExists = !Dashboard.preferences.getString(Constants.CERTIFICATE, "").isEmpty();
+ boolean isAllowedAnon = Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false);
+ return (isAllowedAnon || certificateExists) && !eip_status.isConnected() && !eip_status.isConnecting();
}
-
+
private boolean canLogInToStartEIP() {
- boolean isAllowedRegistered = Dashboard.preferences.getBoolean(Constants.ALLOWED_REGISTERED, false);
- boolean isLoggedIn = !LeapSRPSession.getToken().isEmpty();
- Log.d(TAG, "Allow registered? " + isAllowedRegistered);
- Log.d(TAG, "Is logged in? " + isLoggedIn);
- return isAllowedRegistered && !isLoggedIn && !eip_status.isConnecting() && !eip_status.isConnected();
+ boolean isAllowedRegistered = Dashboard.preferences.getBoolean(Constants.ALLOWED_REGISTERED, false);
+ boolean isLoggedIn = !LeapSRPSession.getToken().isEmpty();
+ return isAllowedRegistered && !isLoggedIn && !eip_status.isConnecting() && !eip_status.isConnected();
}
private void handleSwitchOff() {
- if(eip_status.isConnecting()) {
- askPendingStartCancellation();
- } else if(eip_status.isConnected()) {
- askToStopEIP();
- }
- }
-
- private void askPendingStartCancellation() {
- AlertDialog.Builder alertBuilder = new AlertDialog.Builder(dashboard);
- alertBuilder.setTitle(dashboard.getString(R.string.eip_cancel_connect_title))
- .setMessage(dashboard.getString(R.string.eip_cancel_connect_text))
- .setPositiveButton((R.string.yes), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- askToStopEIP();
- }
- })
- .setNegativeButton(dashboard.getString(R.string.no), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- eip_switch.setChecked(true);
- }
- })
- .show();
+ if (eip_status.isConnecting()) {
+ askPendingStartCancellation();
+ } else if (eip_status.isConnected()) {
+ askToStopEIP();
+ } else
+ setDisconnectedUI();
+ }
+
+ private void askPendingStartCancellation() {
+ AlertDialog.Builder alertBuilder = new AlertDialog.Builder(dashboard);
+ alertBuilder.setTitle(dashboard.getString(R.string.eip_cancel_connect_title))
+ .setMessage(dashboard.getString(R.string.eip_cancel_connect_text))
+ .setPositiveButton((R.string.yes), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ askToStopEIP();
+ }
+ })
+ .setNegativeButton(dashboard.getString(R.string.no), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ eip_switch.setChecked(true);
+ }
+ })
+ .show();
}
public void startEipFromScratch() {
wants_to_connect = false;
is_starting_to_connect = true;
progress_bar.setVisibility(View.VISIBLE);
- eip_switch.setVisibility(View.VISIBLE);
- String status = dashboard.getString(R.string.eip_status_start_pending);
- status_message.setText(status);
-
- if(!eip_switch.isChecked()) {
- eip_switch.setChecked(true);
- }
+ eip_switch.setVisibility(View.VISIBLE);
+ String status = dashboard.getString(R.string.eip_status_start_pending);
+ status_message.setText(status);
+
+ if (!eip_switch.isChecked()) {
+ eip_switch.setChecked(true);
+ }
saveStatus();
- eipCommand(Constants.ACTION_START_EIP);
+ eipCommand(Constants.ACTION_START_EIP);
}
- private void stopEIP() {
- if(eip_status.isConnecting())
- VoidVpnService.stop();
- Intent disconnect_vpn = new Intent(dashboard, DisconnectVPN.class);
- dashboard.startActivityForResult(disconnect_vpn, EIP.DISCONNECT);
- eip_status.setDisconnecting();
+ private void stop() {
+ if (eip_status.isConnecting())
+ VoidVpnService.stop();
+ disconnect();
}
- protected void askToStopEIP() {
+ private void disconnect() {
+ Intent disconnect_vpn = new Intent(dashboard, DisconnectVPN.class);
+ dashboard.startActivityForResult(disconnect_vpn, EIP.DISCONNECT);
+ eip_status.setDisconnecting();
+ }
+
+ protected void stopEipIfPossible() {
+
hideProgressBar();
- String status = dashboard.getString(R.string.eip_state_not_connected);
- status_message.setText(status);
+ String message = dashboard.getString(R.string.eip_state_not_connected);
+ status_message.setText(message);
- eipCommand(Constants.ACTION_STOP_EIP);
+ eipCommand(Constants.ACTION_STOP_EIP);
+ }
+
+ private void askToStopEIP() {
+ AlertDialog.Builder alertBuilder = new AlertDialog.Builder(dashboard);
+ alertBuilder.setTitle(dashboard.getString(R.string.eip_cancel_connect_title))
+ .setMessage(dashboard.getString(R.string.eip_warning_browser_inconsistency))
+ .setPositiveButton((R.string.yes), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ stopEipIfPossible();
+ }
+ })
+ .setNegativeButton(dashboard.getString(R.string.no), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ eip_switch.setChecked(true);
+ }
+ })
+ .show();
}
protected void updateEipService() {
eipCommand(Constants.ACTION_UPDATE_EIP_SERVICE);
}
-
+
/**
* Send a command to EIP
- *
- * @param action A valid String constant from EIP class representing an Intent
- * filter for the EIP class
+ *
+ * @param action A valid String constant from EIP class representing an Intent
+ * filter for the EIP class
*/
- private void eipCommand(String action){
- // TODO validate "action"...how do we get the list of intent-filters for a class via Android API?
- Intent vpn_intent = new Intent(dashboard.getApplicationContext(), EIP.class);
- vpn_intent.setAction(action);
- vpn_intent.putExtra(Constants.RECEIVER_TAG, mEIPReceiver);
- dashboard.startService(vpn_intent);
- }
-
+ private void eipCommand(String action) {
+ // TODO validate "action"...how do we get the list of intent-filters for a class via Android API?
+ Intent vpn_intent = new Intent(dashboard.getApplicationContext(), EIP.class);
+ vpn_intent.setAction(action);
+ vpn_intent.putExtra(Constants.RECEIVER_TAG, mEIPReceiver);
+ dashboard.startService(vpn_intent);
+ }
+
@Override
- public void update (Observable observable, Object data) {
- if(observable instanceof EipStatus) {
- eip_status = (EipStatus) observable;
- final EipStatus eip_status = (EipStatus) observable;
- dashboard.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- handleNewState(eip_status);
- }
- });
- }
+ public void update(Observable observable, Object data) {
+ if (observable instanceof EipStatus) {
+ eip_status = (EipStatus) observable;
+ final EipStatus eip_status = (EipStatus) observable;
+ dashboard.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ handleNewState(eip_status);
+ }
+ });
+ }
}
private void handleNewState(EipStatus eip_status) {
- Log.d(TAG, "handleNewState: " + eip_status.toString());
- if(eip_status.wantsToDisconnect())
- setDisconnectedUI();
- else if(eip_status.isConnecting() || is_starting_to_connect)
- setInProgressUI(eip_status);
- else if (eip_status.isConnected())
- setConnectedUI();
- else if (eip_status.isDisconnected() && !eip_status.isConnecting())
- setDisconnectedUI();
+ if (eip_status.wantsToDisconnect())
+ setDisconnectedUI();
+ else if (eip_status.isConnecting() || is_starting_to_connect)
+ setInProgressUI(eip_status);
+ else if (eip_status.isConnected())
+ setConnectedUI();
+ else if (eip_status.isDisconnected() && !eip_status.isConnecting())
+ setDisconnectedUI();
}
private void setConnectedUI() {
- hideProgressBar();
- Log.d(TAG, "setConnectedUi? " + eip_status.isConnected());
- adjustSwitch();
- is_starting_to_connect = false;
- status_message.setText(dashboard.getString(R.string.eip_state_connected));
+ hideProgressBar();
+ adjustSwitch();
+ is_starting_to_connect = false;
+ status_message.setText(dashboard.getString(R.string.eip_state_connected));
}
- private void setDisconnectedUI(){
- hideProgressBar();
- adjustSwitch();
- status_message.setText(dashboard.getString(R.string.eip_state_not_connected));
+ private void setDisconnectedUI() {
+ hideProgressBar();
+ adjustSwitch();
+ if (eip_status.errorInLast(5, dashboard.getApplicationContext())
+ && !status_message.getText().toString().equalsIgnoreCase(dashboard.getString(R.string.eip_state_not_connected))) {
+ dashboard.showLog();
+ VoidVpnService.stop();
+ }
+ status_message.setText(dashboard.getString(R.string.eip_state_not_connected));
}
private void adjustSwitch() {
- if(eip_status.isConnected() || eip_status.isConnecting() || is_starting_to_connect) {
- Log.d(TAG, "adjustSwitch, isConnected || isConnecting, is checked");
- if(!eip_switch.isChecked()) {
- eip_switch.setChecked(true);
- }
- } else {
- Log.d(TAG, "adjustSwitch, !isConnected && !isConnecting? " + eip_status.toString());
+ if (eip_status.isConnected() || eip_status.isConnecting() || is_starting_to_connect) {
+ if (!eip_switch.isChecked()) {
+ eip_switch.setChecked(true);
+ }
+ } else {
- if(eip_switch.isChecked()) {
- eip_switch.setChecked(false);
- }
- }
+ if (eip_switch.isChecked()) {
+ eip_switch.setChecked(false);
+ }
+ }
}
private void setInProgressUI(EipStatus eip_status) {
- int localizedResId = eip_status.getLocalizedResId();
- String logmessage = eip_status.getLogMessage();
- String prefix = dashboard.getString(localizedResId);
+ int localizedResId = eip_status.getLocalizedResId();
+ String logmessage = eip_status.getLogMessage();
+ String prefix = dashboard.getString(localizedResId);
- status_message.setText(prefix + " " + logmessage);
+ showProgressBar();
+ status_message.setText(prefix + " " + logmessage);
is_starting_to_connect = false;
- adjustSwitch();
+ adjustSwitch();
}
private void updatingCertificateUI() {
- progress_bar.setVisibility(View.VISIBLE);
+ showProgressBar();
status_message.setText(getString(R.string.updating_certificate_message));
}
+ private void showProgressBar() {
+ if (progress_bar != null)
+ progress_bar.setVisibility(View.VISIBLE);
+ }
+
private void hideProgressBar() {
- if(progress_bar != null)
- progress_bar.setVisibility(View.GONE);
+ if (progress_bar != null)
+ progress_bar.setVisibility(View.GONE);
}
protected class EIPReceiver extends ResultReceiver {
- protected EIPReceiver(Handler handler){
- super(handler);
- }
-
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- super.onReceiveResult(resultCode, resultData);
-
- String request = resultData.getString(Constants.REQUEST_TAG);
-
- if (request.equals(Constants.ACTION_START_EIP)) {
- switch (resultCode){
- case Activity.RESULT_OK:
- break;
- case Activity.RESULT_CANCELED:
-
- break;
- }
- } else if (request.equals(Constants.ACTION_STOP_EIP)) {
- switch (resultCode){
- case Activity.RESULT_OK:
- stopEIP();
- break;
- case Activity.RESULT_CANCELED:
- break;
- }
- } else if (request.equals(Constants.EIP_NOTIFICATION)) {
- switch (resultCode){
- case Activity.RESULT_OK:
- break;
- case Activity.RESULT_CANCELED:
- break;
- }
- } else if (request.equals(Constants.ACTION_CHECK_CERT_VALIDITY)) {
- switch (resultCode) {
- case Activity.RESULT_OK:
- break;
- case Activity.RESULT_CANCELED:
- updatingCertificateUI();
- dashboard.downloadVpnCertificate();
- break;
- }
- } else if (request.equals(Constants.ACTION_UPDATE_EIP_SERVICE)) {
- switch (resultCode) {
- case Activity.RESULT_OK:
- if(wants_to_connect)
- startEipFromScratch();
- break;
- case Activity.RESULT_CANCELED:
- handleNewState(eip_status);
- break;
+ protected EIPReceiver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ super.onReceiveResult(resultCode, resultData);
+
+ String request = resultData.getString(Constants.REQUEST_TAG);
+
+ if (request.equals(Constants.ACTION_START_EIP)) {
+ switch (resultCode) {
+ case Activity.RESULT_OK:
+ break;
+ case Activity.RESULT_CANCELED:
+
+ break;
+ }
+ } else if (request.equals(Constants.ACTION_STOP_EIP)) {
+ switch (resultCode) {
+ case Activity.RESULT_OK:
+ stop();
+ break;
+ case Activity.RESULT_CANCELED:
+ break;
+ }
+ } else if (request.equals(Constants.EIP_NOTIFICATION)) {
+ switch (resultCode) {
+ case Activity.RESULT_OK:
+ break;
+ case Activity.RESULT_CANCELED:
+ break;
+ }
+ } else if (request.equals(Constants.ACTION_CHECK_CERT_VALIDITY)) {
+ switch (resultCode) {
+ case Activity.RESULT_OK:
+ break;
+ case Activity.RESULT_CANCELED:
+ updatingCertificateUI();
+ dashboard.downloadVpnCertificate();
+ break;
+ }
+ } else if (request.equals(Constants.ACTION_UPDATE_EIP_SERVICE)) {
+ switch (resultCode) {
+ case Activity.RESULT_OK:
+ if (wants_to_connect)
+ startEipFromScratch();
+ break;
+ case Activity.RESULT_CANCELED:
+ handleNewState(eip_status);
+ break;
+ }
}
}
- }
}
public static EIPReceiver getReceiver() {
- return mEIPReceiver;
+ return mEIPReceiver;
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java b/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java
index 49af9274..8ba7fa34 100644
--- a/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java
+++ b/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java
@@ -1,6 +1,6 @@
/**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -16,33 +16,31 @@
*/
package se.leap.bitmaskclient;
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.app.FragmentTransaction;
+import android.app.*;
public class FragmentManagerEnhanced {
private FragmentManager generic_fragment_manager;
-
+
public FragmentManagerEnhanced(FragmentManager generic_fragment_manager) {
- this.generic_fragment_manager = generic_fragment_manager;
+ this.generic_fragment_manager = generic_fragment_manager;
}
-
+
public FragmentTransaction removePreviousFragment(String tag) {
- FragmentTransaction transaction = generic_fragment_manager.beginTransaction();
- Fragment previous_fragment = generic_fragment_manager.findFragmentByTag(tag);
- if (previous_fragment != null) {
- transaction.remove(previous_fragment);
- }
- transaction.addToBackStack(null);
-
- return transaction;
+ FragmentTransaction transaction = generic_fragment_manager.beginTransaction();
+ Fragment previous_fragment = generic_fragment_manager.findFragmentByTag(tag);
+ if (previous_fragment != null) {
+ transaction.remove(previous_fragment);
+ }
+ transaction.addToBackStack(null);
+
+ return transaction;
}
public void replace(int containerViewId, Fragment fragment, String tag) {
- FragmentTransaction transaction = generic_fragment_manager.beginTransaction();
-
- transaction.replace(containerViewId, fragment, tag).commit();
+ FragmentTransaction transaction = generic_fragment_manager.beginTransaction();
+
+ transaction.replace(containerViewId, fragment, tag).commit();
}
public FragmentTransaction beginTransaction() {
@@ -50,6 +48,6 @@ public class FragmentManagerEnhanced {
}
public Fragment findFragmentByTag(String tag) {
- return generic_fragment_manager.findFragmentByTag(tag);
+ return generic_fragment_manager.findFragmentByTag(tag);
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java
index 989dc395..b961350e 100644
--- a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java
+++ b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java
@@ -1,6 +1,6 @@
/**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -14,338 +14,348 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
- package se.leap.bitmaskclient;
+package se.leap.bitmaskclient;
-import org.jboss.security.srp.SRPParameters;
+import org.jboss.security.srp.*;
-import java.io.UnsupportedEncodingException;
-import java.math.BigInteger;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.util.Arrays;
+import java.io.*;
+import java.math.*;
+import java.security.*;
+import java.util.*;
/**
* Implements all SRP algorithm logic.
- *
+ * <p/>
* It's derived from JBoss implementation, with adjustments to make it work with LEAP platform.
- *
- * @author parmegv
*
+ * @author parmegv
*/
public class LeapSRPSession {
-
- private static String token = "";
-
- final public static String SALT = "salt";
- final public static String M1 = "M1";
- final public static String M2 = "M2";
- final public static String TOKEN = "token";
- final public static String AUTHORIZATION_HEADER= "Authorization";
- final public static String TAG= "Leap SRP session class tag";
-
- private SRPParameters params;
- private String username;
- private String password;
- private BigInteger N;
- private byte[] N_bytes;
- private BigInteger g;
- private BigInteger x;
- private BigInteger v;
- private BigInteger a;
- private BigInteger A;
- private byte[] K;
- private SecureRandom pseudoRng;
- /** The M1 = H(H(N) xor H(g) | H(U) | s | A | B | K) hash */
- private MessageDigest clientHash;
- /** The M2 = H(A | M | K) hash */
- private MessageDigest serverHash;
-
- private static int A_LEN;
-
-
- /** Creates a new SRP server session object from the username, password
- verifier,
- @param username, the user ID
- @param password, the user clear text password
- @param params, the SRP parameters for the session
- */
- public LeapSRPSession(String username, String password)
- {
- this(username, password, null);
- }
-
- /** Creates a new SRP server session object from the username, password
- verifier,
- @param username, the user ID
- @param password, the user clear text password
- @param params, the SRP parameters for the session
- @param abytes, the random exponent used in the A public key
- */
- public LeapSRPSession(String username, String password, byte[] abytes) {
-
- params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), ConfigHelper.G.toByteArray(), BigInteger.ZERO.toByteArray(), "SHA-256");
- this.g = new BigInteger(1, params.g);
- N_bytes = ConfigHelper.trim(params.N);
- this.N = new BigInteger(1, N_bytes);
- this.username = username;
- this.password = password;
-
- try {
- pseudoRng = SecureRandom.getInstance("SHA1PRNG");
- } catch (NoSuchAlgorithmException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- if( abytes != null ) {
- A_LEN = 8*abytes.length;
- /* TODO Why did they put this condition?
- if( 8*abytes.length != A_LEN )
+
+ private static String token = "";
+
+ final public static String SALT = "salt";
+ final public static String M1 = "M1";
+ final public static String M2 = "M2";
+ final public static String TOKEN = "token";
+ final public static String AUTHORIZATION_HEADER = "Authorization";
+ final public static String TAG = "Leap SRP session class tag";
+
+ private User user;
+ private SRPParameters params;
+ private String username;
+ private String password;
+ private BigInteger N;
+ private byte[] N_bytes;
+ private BigInteger g;
+ private BigInteger x;
+ private BigInteger v;
+ private BigInteger a;
+ private BigInteger A;
+ private byte[] K;
+ private SecureRandom pseudoRng;
+ /**
+ * The M1 = H(H(N) xor H(g) | H(U) | s | A | B | K) hash
+ */
+ private MessageDigest clientHash;
+ /**
+ * The M2 = H(A | M | K) hash
+ */
+ private MessageDigest serverHash;
+
+ private static int A_LEN;
+
+
+ /**
+ * Creates a new SRP server session object from the username, password
+ * verifier,
+ *
+ * @param username, the user ID
+ * @param password, the user clear text password
+ * @param params, the SRP parameters for the session
+ */
+ public LeapSRPSession(String username, String password) {
+ this(username, password, null);
+ }
+
+ /**
+ * Creates a new SRP server session object from the username, password
+ * verifier,
+ *
+ * @param username, the user ID
+ * @param password, the user clear text password
+ * @param params, the SRP parameters for the session
+ * @param abytes, the random exponent used in the A public key
+ */
+ public LeapSRPSession(String username, String password, byte[] abytes) {
+
+ params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), ConfigHelper.G.toByteArray(), BigInteger.ZERO.toByteArray(), "SHA-256");
+ this.g = new BigInteger(1, params.g);
+ N_bytes = ConfigHelper.trim(params.N);
+ this.N = new BigInteger(1, N_bytes);
+ this.username = username;
+ this.password = password;
+
+ try {
+ pseudoRng = SecureRandom.getInstance("SHA1PRNG");
+ } catch (NoSuchAlgorithmException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ if (abytes != null) {
+ A_LEN = 8 * abytes.length;
+ /* TODO Why did they put this condition?
+ if( 8*abytes.length != A_LEN )
throw new IllegalArgumentException("The abytes param must be "
+(A_LEN/8)+" in length, abytes.length="+abytes.length);
*/
- this.a = new BigInteger(abytes);
- }
- else
- A_LEN = 64;
-
- serverHash = newDigest();
- clientHash = newDigest();
- }
-
- /**
- * Calculates the parameter x of the SRP-6a algorithm.
- * @param username
- * @param password
- * @param salt the salt of the user
- * @return x
- */
- public byte[] calculatePasswordHash(String username, String password, byte[] salt)
- {
- //password = password.replaceAll("\\\\", "\\\\\\\\");
- // Calculate x = H(s | H(U | ':' | password))
- MessageDigest x_digest = newDigest();
- // Try to convert the username to a byte[] using ISO-8859-1
- byte[] user = null;
- byte[] password_bytes = null;
- byte[] colon = {};
- String encoding = "ISO-8859-1";
- try {
- user = ConfigHelper.trim(username.getBytes(encoding));
- colon = ConfigHelper.trim(":".getBytes(encoding));
- password_bytes = ConfigHelper.trim(password.getBytes(encoding));
- }
- catch(UnsupportedEncodingException e) {
- // Use the default platform encoding
- user = ConfigHelper.trim(username.getBytes());
- colon = ConfigHelper.trim(":".getBytes());
- password_bytes = ConfigHelper.trim(password.getBytes());
- }
-
- // Build the hash
- x_digest.update(user);
- x_digest.update(colon);
- x_digest.update(password_bytes);
- byte[] h = x_digest.digest();
-
- x_digest.reset();
- x_digest.update(salt);
- x_digest.update(h);
- byte[] x_digest_bytes = x_digest.digest();
-
- return x_digest_bytes;
- }
+ this.a = new BigInteger(abytes);
+ } else
+ A_LEN = 64;
+
+ serverHash = newDigest();
+ clientHash = newDigest();
+ }
+
+ /**
+ * Calculates the parameter x of the SRP-6a algorithm.
+ *
+ * @param username
+ * @param password
+ * @param salt the salt of the user
+ * @return x
+ */
+ public byte[] calculatePasswordHash(String username, String password, byte[] salt) {
+ //password = password.replaceAll("\\\\", "\\\\\\\\");
+ // Calculate x = H(s | H(U | ':' | password))
+ MessageDigest x_digest = newDigest();
+ // Try to convert the username to a byte[] using ISO-8859-1
+ byte[] user = null;
+ byte[] password_bytes = null;
+ byte[] colon = {};
+ String encoding = "ISO-8859-1";
+ try {
+ user = ConfigHelper.trim(username.getBytes(encoding));
+ colon = ConfigHelper.trim(":".getBytes(encoding));
+ password_bytes = ConfigHelper.trim(password.getBytes(encoding));
+ } catch (UnsupportedEncodingException e) {
+ // Use the default platform encoding
+ user = ConfigHelper.trim(username.getBytes());
+ colon = ConfigHelper.trim(":".getBytes());
+ password_bytes = ConfigHelper.trim(password.getBytes());
+ }
+
+ // Build the hash
+ x_digest.update(user);
+ x_digest.update(colon);
+ x_digest.update(password_bytes);
+ byte[] h = x_digest.digest();
+
+ x_digest.reset();
+ x_digest.update(salt);
+ x_digest.update(h);
+ byte[] x_digest_bytes = x_digest.digest();
+
+ return x_digest_bytes;
+ }
public byte[] calculateNewSalt() {
- try {
- BigInteger salt = new BigInteger(64, SecureRandom.getInstance("SHA1PRNG"));
- return ConfigHelper.trim(salt.toByteArray());
- } catch(NoSuchAlgorithmException e) {
- e.printStackTrace();
- }
- return null;
+ try {
+ BigInteger salt = new BigInteger(64, SecureRandom.getInstance("SHA1PRNG"));
+ return ConfigHelper.trim(salt.toByteArray());
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ return null;
}
- /**
- * Calculates the parameter V of the SRP-6a algorithm.
- * @return the value of V
- */
+
+ /**
+ * Calculates the parameter V of the SRP-6a algorithm.
+ *
+ * @return the value of V
+ */
public BigInteger calculateV(String username, String password, byte[] salt) {
- byte[] x_bytes = calculatePasswordHash(username, password, ConfigHelper.trim(salt));
- x = new BigInteger(1, x_bytes);
- BigInteger v = g.modPow(x, N); // g^x % N
- return v;
- }
-
- /**
- * Calculates the trimmed xor from two BigInteger numbers
- * @param b1 the positive source to build first BigInteger
- * @param b2 the positive source to build second BigInteger
- * @param length
- * @return
- */
- public byte[] xor(byte[] b1, byte[] b2)
- {
- //TODO Check if length matters in the order, when b2 is smaller than b1 or viceversa
- byte[] xor_digest = new BigInteger(1, b1).xor(new BigInteger(1, b2)).toByteArray();
- return ConfigHelper.trim(xor_digest);
- }
-
- /**
- * @returns The exponential residue (parameter A) to be sent to the server.
- */
- public byte[] exponential() {
- byte[] Abytes = null;
- if(A == null) {
+ byte[] x_bytes = calculatePasswordHash(username, password, ConfigHelper.trim(salt));
+ x = new BigInteger(1, x_bytes);
+ BigInteger v = g.modPow(x, N); // g^x % N
+ return v;
+ }
+
+ /**
+ * Calculates the trimmed xor from two BigInteger numbers
+ *
+ * @param b1 the positive source to build first BigInteger
+ * @param b2 the positive source to build second BigInteger
+ * @param length
+ * @return
+ */
+ public byte[] xor(byte[] b1, byte[] b2) {
+ //TODO Check if length matters in the order, when b2 is smaller than b1 or viceversa
+ byte[] xor_digest = new BigInteger(1, b1).xor(new BigInteger(1, b2)).toByteArray();
+ return ConfigHelper.trim(xor_digest);
+ }
+
+ /**
+ * @returns The exponential residue (parameter A) to be sent to the server.
+ */
+ public byte[] exponential() {
+ byte[] Abytes = null;
+ if (A == null) {
/* If the random component of A has not been specified use a random
number */
- if( a == null ) {
- BigInteger one = BigInteger.ONE;
- do {
- a = new BigInteger(A_LEN, pseudoRng);
- } while(a.compareTo(one) <= 0);
- }
- A = g.modPow(a, N);
- Abytes = ConfigHelper.trim(A.toByteArray());
- }
- return Abytes;
- }
-
- /**
- * Calculates the parameter M1, to be sent to the SRP server.
- * It also updates hashes of client and server for further calculations in other methods.
- * It uses a predefined k.
- * @param salt_bytes
- * @param Bbytes the parameter received from the server, in bytes
- * @return the parameter M1
- * @throws NoSuchAlgorithmException
- */
+ if (a == null) {
+ BigInteger one = BigInteger.ONE;
+ do {
+ a = new BigInteger(A_LEN, pseudoRng);
+ } while (a.compareTo(one) <= 0);
+ }
+ A = g.modPow(a, N);
+ Abytes = ConfigHelper.trim(A.toByteArray());
+ }
+ return Abytes;
+ }
+
+ /**
+ * Calculates the parameter M1, to be sent to the SRP server.
+ * It also updates hashes of client and server for further calculations in other methods.
+ * It uses a predefined k.
+ *
+ * @param salt_bytes
+ * @param Bbytes the parameter received from the server, in bytes
+ * @return the parameter M1
+ * @throws NoSuchAlgorithmException
+ */
public byte[] response(byte[] salt_bytes, byte[] Bbytes) {
- // Calculate x = H(s | H(U | ':' | password))
- byte[] M1 = null;
- if(new BigInteger(1, Bbytes).mod(new BigInteger(1, N_bytes)) != BigInteger.ZERO) {
- this.v = calculateV(username, password, salt_bytes);
- // H(N)
- byte[] digest_of_n = newDigest().digest(N_bytes);
-
- // H(g)
- byte[] digest_of_g = newDigest().digest(params.g);
-
- // clientHash = H(N) xor H(g)
- byte[] xor_digest = xor(digest_of_n, digest_of_g);
- clientHash.update(xor_digest);
-
- // clientHash = H(N) xor H(g) | H(U)
- byte[] username_digest = newDigest().digest(ConfigHelper.trim(username.getBytes()));
- username_digest = ConfigHelper.trim(username_digest);
- clientHash.update(username_digest);
-
- // clientHash = H(N) xor H(g) | H(U) | s
- clientHash.update(ConfigHelper.trim(salt_bytes));
-
- K = null;
-
- // clientHash = H(N) xor H(g) | H(U) | A
- byte[] Abytes = ConfigHelper.trim(A.toByteArray());
- clientHash.update(Abytes);
-
- // clientHash = H(N) xor H(g) | H(U) | s | A | B
- Bbytes = ConfigHelper.trim(Bbytes);
- clientHash.update(Bbytes);
-
- // Calculate S = (B - kg^x) ^ (a + u * x) % N
- BigInteger S = calculateS(Bbytes);
- byte[] S_bytes = ConfigHelper.trim(S.toByteArray());
-
- // K = SessionHash(S)
- MessageDigest sessionDigest = newDigest();
- K = ConfigHelper.trim(sessionDigest.digest(S_bytes));
-
- // clientHash = H(N) xor H(g) | H(U) | A | B | K
- clientHash.update(K);
-
- M1 = ConfigHelper.trim(clientHash.digest());
-
- // serverHash = Astr + M + K
- serverHash.update(Abytes);
- serverHash.update(M1);
- serverHash.update(K);
-
- }
- return M1;
- }
-
- /**
- * It calculates the parameter S used by response() to obtain session hash K.
- * @param Bbytes the parameter received from the server, in bytes
- * @return the parameter S
- */
- private BigInteger calculateS(byte[] Bbytes) {
- byte[] Abytes = ConfigHelper.trim(A.toByteArray());
- Bbytes = ConfigHelper.trim(Bbytes);
- byte[] u_bytes = getU(Abytes, Bbytes);
-
- BigInteger B = new BigInteger(1, Bbytes);
- BigInteger u = new BigInteger(1, u_bytes);
- String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0";
- BigInteger k = new BigInteger(k_string, 16);
- BigInteger B_minus_v = B.subtract(k.multiply(v));
- BigInteger a_ux = a.add(u.multiply(x));
- BigInteger S = B_minus_v.modPow(a_ux, N);
- return S;
- }
-
- /**
- * It calculates the parameter u used by calculateS to obtain S.
- * @param Abytes the exponential residue sent to the server
- * @param Bbytes the parameter received from the server, in bytes
- * @return
- */
- public byte[] getU(byte[] Abytes, byte[] Bbytes) {
- MessageDigest u_digest = newDigest();
- u_digest.update(ConfigHelper.trim(Abytes));
- u_digest.update(ConfigHelper.trim(Bbytes));
- byte[] u_digest_bytes = u_digest.digest();
- return ConfigHelper.trim(new BigInteger(1, u_digest_bytes).toByteArray());
- }
-
- /**
- * @param M2 The server's response to the client's challenge
- * @returns True if and only if the server's response was correct.
- */
- public boolean verify(byte[] M2)
- {
- // M2 = H(A | M1 | K)
- M2 = ConfigHelper.trim(M2);
- byte[] myM2 = ConfigHelper.trim(serverHash.digest());
- boolean valid = Arrays.equals(M2, myM2);
- return valid;
- }
-
- protected static void setToken(String token) {
- LeapSRPSession.token = token;
- }
-
- protected static String getToken() {
- return token;
- }
-
- /**
- * @return a new SHA-256 digest.
- */
- public MessageDigest newDigest()
- {
- MessageDigest md = null;
- try {
- md = MessageDigest.getInstance("SHA-256");
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- }
- return md;
- }
+ // Calculate x = H(s | H(U | ':' | password))
+ byte[] M1 = null;
+ if (new BigInteger(1, Bbytes).mod(new BigInteger(1, N_bytes)) != BigInteger.ZERO) {
+ this.v = calculateV(username, password, salt_bytes);
+ // H(N)
+ byte[] digest_of_n = newDigest().digest(N_bytes);
+
+ // H(g)
+ byte[] digest_of_g = newDigest().digest(params.g);
+
+ // clientHash = H(N) xor H(g)
+ byte[] xor_digest = xor(digest_of_n, digest_of_g);
+ clientHash.update(xor_digest);
+
+ // clientHash = H(N) xor H(g) | H(U)
+ byte[] username_digest = newDigest().digest(ConfigHelper.trim(username.getBytes()));
+ username_digest = ConfigHelper.trim(username_digest);
+ clientHash.update(username_digest);
+
+ // clientHash = H(N) xor H(g) | H(U) | s
+ clientHash.update(ConfigHelper.trim(salt_bytes));
+
+ K = null;
+
+ // clientHash = H(N) xor H(g) | H(U) | A
+ byte[] Abytes = ConfigHelper.trim(A.toByteArray());
+ clientHash.update(Abytes);
+
+ // clientHash = H(N) xor H(g) | H(U) | s | A | B
+ Bbytes = ConfigHelper.trim(Bbytes);
+ clientHash.update(Bbytes);
+
+ // Calculate S = (B - kg^x) ^ (a + u * x) % N
+ BigInteger S = calculateS(Bbytes);
+ byte[] S_bytes = ConfigHelper.trim(S.toByteArray());
+
+ // K = SessionHash(S)
+ MessageDigest sessionDigest = newDigest();
+ K = ConfigHelper.trim(sessionDigest.digest(S_bytes));
+
+ // clientHash = H(N) xor H(g) | H(U) | A | B | K
+ clientHash.update(K);
+
+ M1 = ConfigHelper.trim(clientHash.digest());
+
+ // serverHash = Astr + M + K
+ serverHash.update(Abytes);
+ serverHash.update(M1);
+ serverHash.update(K);
+
+ }
+ return M1;
+ }
+
+ /**
+ * It calculates the parameter S used by response() to obtain session hash K.
+ *
+ * @param Bbytes the parameter received from the server, in bytes
+ * @return the parameter S
+ */
+ private BigInteger calculateS(byte[] Bbytes) {
+ byte[] Abytes = ConfigHelper.trim(A.toByteArray());
+ Bbytes = ConfigHelper.trim(Bbytes);
+ byte[] u_bytes = getU(Abytes, Bbytes);
+
+ BigInteger B = new BigInteger(1, Bbytes);
+ BigInteger u = new BigInteger(1, u_bytes);
+ String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0";
+ BigInteger k = new BigInteger(k_string, 16);
+ BigInteger B_minus_v = B.subtract(k.multiply(v));
+ BigInteger a_ux = a.add(u.multiply(x));
+ BigInteger S = B_minus_v.modPow(a_ux, N);
+ return S;
+ }
+
+ /**
+ * It calculates the parameter u used by calculateS to obtain S.
+ *
+ * @param Abytes the exponential residue sent to the server
+ * @param Bbytes the parameter received from the server, in bytes
+ * @return
+ */
+ public byte[] getU(byte[] Abytes, byte[] Bbytes) {
+ MessageDigest u_digest = newDigest();
+ u_digest.update(ConfigHelper.trim(Abytes));
+ u_digest.update(ConfigHelper.trim(Bbytes));
+ byte[] u_digest_bytes = u_digest.digest();
+ return ConfigHelper.trim(new BigInteger(1, u_digest_bytes).toByteArray());
+ }
+
+ /**
+ * @param M2 The server's response to the client's challenge
+ * @returns True if and only if the server's response was correct.
+ */
+ public boolean verify(byte[] M2) {
+ // M2 = H(A | M1 | K)
+ M2 = ConfigHelper.trim(M2);
+ byte[] myM2 = ConfigHelper.trim(serverHash.digest());
+ boolean valid = Arrays.equals(M2, myM2);
+ return valid;
+ }
+
+ protected static void setToken(String token) {
+ LeapSRPSession.token = token;
+ }
+
+ protected static String getToken() {
+ return token;
+ }
+
+ protected static boolean loggedIn() {
+ return !token.isEmpty();
+ }
+
+ /**
+ * @return a new SHA-256 digest.
+ */
+ public MessageDigest newDigest() {
+ MessageDigest md = null;
+ try {
+ md = MessageDigest.getInstance("SHA-256");
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ return md;
+ }
public byte[] getK() {
- return K;
+ return K;
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java
index 96b87085..9171e816 100644
--- a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java
+++ b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java
@@ -1,31 +1,25 @@
package se.leap.bitmaskclient;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.util.Log;
+import android.content.*;
-import se.leap.bitmaskclient.eip.Constants;
+import se.leap.bitmaskclient.eip.*;
public class OnBootReceiver extends BroadcastReceiver {
SharedPreferences preferences;
-
+
// Debug: am broadcast -a android.intent.action.BOOT_COMPLETED
@Override
public void onReceive(Context context, Intent intent) {
- preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Context.MODE_PRIVATE);
- boolean provider_configured = !preferences.getString(Provider.KEY, "").isEmpty();
- boolean start_on_boot = preferences.getBoolean(Dashboard.START_ON_BOOT, false);
- Log.d("OnBootReceiver", "Provider configured " + String.valueOf(provider_configured));
- Log.d("OnBootReceiver", "Start on boot " + String.valueOf(start_on_boot));
- if(provider_configured && start_on_boot) {
- Intent dashboard_intent = new Intent(context, Dashboard.class);
- dashboard_intent.setAction(Constants.ACTION_START_EIP);
- dashboard_intent.putExtra(Dashboard.ON_BOOT, true);
- dashboard_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(dashboard_intent);
- }
+ preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Context.MODE_PRIVATE);
+ boolean provider_configured = !preferences.getString(Provider.KEY, "").isEmpty();
+ boolean start_on_boot = preferences.getBoolean(Dashboard.START_ON_BOOT, false);
+ if (provider_configured && start_on_boot) {
+ Intent dashboard_intent = new Intent(context, Dashboard.class);
+ dashboard_intent.setAction(Constants.ACTION_START_EIP);
+ dashboard_intent.putExtra(Dashboard.ON_BOOT, true);
+ dashboard_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(dashboard_intent);
+ }
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/PRNGFixes.java b/app/src/main/java/se/leap/bitmaskclient/PRNGFixes.java
index a046f01f..9e523751 100644
--- a/app/src/main/java/se/leap/bitmaskclient/PRNGFixes.java
+++ b/app/src/main/java/se/leap/bitmaskclient/PRNGFixes.java
@@ -12,28 +12,17 @@ package se.leap.bitmaskclient;
* Source: http://android-developers.blogspot.de/2013/08/some-securerandom-thoughts.html
*/
-import android.os.Build;
+import android.os.*;
import android.os.Process;
-import android.util.Log;
-
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.security.NoSuchAlgorithmException;
+import android.util.*;
+
+import java.io.*;
+import java.security.*;
import java.security.Provider;
-import java.security.SecureRandom;
-import java.security.SecureRandomSpi;
-import java.security.Security;
/**
* Fixes for the output of the default PRNG having low entropy.
- *
+ * <p/>
* The fixes need to be applied via {@link #apply()} before any use of Java
* Cryptography Architecture primitives. A good place to invoke them is in the
* application's {@code onCreate}.
@@ -43,10 +32,13 @@ public final class PRNGFixes {
private static final int VERSION_CODE_JELLY_BEAN = 16;
private static final int VERSION_CODE_JELLY_BEAN_MR2 = 18;
private static final byte[] BUILD_FINGERPRINT_AND_DEVICE_SERIAL =
- getBuildFingerprintAndDeviceSerial();
+ getBuildFingerprintAndDeviceSerial();
- /** Hidden constructor to prevent instantiation. */
- private PRNGFixes() {}
+ /**
+ * Hidden constructor to prevent instantiation.
+ */
+ private PRNGFixes() {
+ }
/**
* Applies all fixes.
@@ -113,7 +105,7 @@ public final class PRNGFixes {
if ((secureRandomProviders == null)
|| (secureRandomProviders.length < 1)
|| (!LinuxPRNGSecureRandomProvider.class.equals(
- secureRandomProviders[0].getClass()))) {
+ secureRandomProviders[0].getClass()))) {
Security.insertProviderAt(new LinuxPRNGSecureRandomProvider(), 1);
}
@@ -138,7 +130,7 @@ public final class PRNGFixes {
rng2.getProvider().getClass())) {
throw new SecurityException(
"SecureRandom.getInstance(\"SHA1PRNG\") backed by wrong"
- + " Provider: " + rng2.getProvider().getClass());
+ + " Provider: " + rng2.getProvider().getClass());
}
}
@@ -152,7 +144,7 @@ public final class PRNGFixes {
super("LinuxPRNG",
1.0,
"A Linux-specific random number provider that uses"
- + " /dev/urandom");
+ + " /dev/urandom");
// Although /dev/urandom is not a SHA-1 PRNG, some apps
// explicitly request a SHA1PRNG SecureRandom and we thus need to
// prevent them from getting the default implementation whose output
diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java
index d7ff6633..ee06a586 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Provider.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java
@@ -1,6 +1,6 @@
/**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -16,66 +16,56 @@
*/
package se.leap.bitmaskclient;
-import android.app.Activity;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Parcel;
-import android.os.Parcelable;
+import android.os.*;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
+import org.json.*;
-import java.io.File;
-import java.io.Serializable;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.Locale;
+import java.io.*;
+import java.net.*;
+import java.util.*;
/**
* @author Sean Leonard <meanderingcode@aetherislands.net>
* @author Parménides GV <parmegv@sdf.org>
- *
*/
public final class Provider implements Parcelable {
- private JSONObject definition; // Represents our Provider's provider.json
+ private JSONObject definition; // Represents our Provider's provider.json
private URL main_url;
final public static String
- API_URL = "api_uri",
- API_VERSION = "api_version",
- ALLOW_REGISTRATION = "allow_registration",
- API_RETURN_SERIAL = "serial",
- SERVICE = "service",
- KEY = "provider",
- CA_CERT = "ca_cert",
- CA_CERT_URI = "ca_cert_uri",
- CA_CERT_FINGERPRINT = "ca_cert_fingerprint",
- NAME = "name",
- DESCRIPTION = "description",
- DOMAIN = "domain",
- MAIN_URL = "main_url",
- DOT_JSON_URL = "provider_json_url"
- ;
-
- // Array of what API versions we understand
- protected static final String[] API_VERSIONS = {"1"}; // I assume we might encounter arbitrary version "numbers"
- // Some API pieces we want to know about
- private static final String API_TERM_SERVICES = "services";
- private static final String API_TERM_NAME = "name";
- private static final String API_TERM_DOMAIN = "domain";
- private static final String API_TERM_DEFAULT_LANGUAGE = "default_language";
- protected static final String[] API_EIP_TYPES = {"openvpn"};
-
- public Provider(URL main_url) {
+ API_URL = "api_uri",
+ API_VERSION = "api_version",
+ ALLOW_REGISTRATION = "allow_registration",
+ API_RETURN_SERIAL = "serial",
+ SERVICE = "service",
+ KEY = "provider",
+ CA_CERT = "ca_cert",
+ CA_CERT_URI = "ca_cert_uri",
+ CA_CERT_FINGERPRINT = "ca_cert_fingerprint",
+ NAME = "name",
+ DESCRIPTION = "description",
+ DOMAIN = "domain",
+ MAIN_URL = "main_url",
+ DOT_JSON_URL = "provider_json_url";
+
+ // Array of what API versions we understand
+ protected static final String[] API_VERSIONS = {"1"}; // I assume we might encounter arbitrary version "numbers"
+ // Some API pieces we want to know about
+ private static final String API_TERM_SERVICES = "services";
+ private static final String API_TERM_NAME = "name";
+ private static final String API_TERM_DOMAIN = "domain";
+ private static final String API_TERM_DEFAULT_LANGUAGE = "default_language";
+ protected static final String[] API_EIP_TYPES = {"openvpn"};
+
+ public Provider(URL main_url) {
this.main_url = main_url;
}
public Provider(File provider_file) {
}
+
public static final Parcelable.Creator<Provider> CREATOR
= new Parcelable.Creator<Provider>() {
public Provider createFromParcel(Parcel in) {
@@ -91,7 +81,7 @@ public final class Provider implements Parcelable {
try {
main_url = new URL(in.readString());
String definition_string = in.readString();
- if(definition_string != null)
+ if (definition_string != null)
definition = new JSONObject((definition_string));
} catch (MalformedURLException e) {
e.printStackTrace();
@@ -104,60 +94,62 @@ public final class Provider implements Parcelable {
definition = provider_json;
}
- protected JSONObject definition() { return definition; }
+ protected JSONObject definition() {
+ return definition;
+ }
- protected String getDomain(){
- return main_url.getHost();
- }
+ protected String getDomain() {
+ return main_url.getHost();
+ }
protected URL mainUrl() {
return main_url;
}
-
- protected String getName(){
- // Should we pass the locale in, or query the system here?
- String lang = Locale.getDefault().getLanguage();
- String name = "";
- try {
- if(definition != null)
- name = definition.getJSONObject(API_TERM_NAME).getString(lang);
+
+ protected String getName() {
+ // Should we pass the locale in, or query the system here?
+ String lang = Locale.getDefault().getLanguage();
+ String name = "";
+ try {
+ if (definition != null)
+ name = definition.getJSONObject(API_TERM_NAME).getString(lang);
else throw new JSONException("Provider not defined");
- } catch (JSONException e) {
- if(main_url != null) {
+ } catch (JSONException e) {
+ if (main_url != null) {
String host = main_url.getHost();
name = host.substring(0, host.indexOf("."));
}
- }
-
- return name;
- }
-
- protected String getDescription(){
- String lang = Locale.getDefault().getLanguage();
- String desc = null;
- try {
- desc = definition.getJSONObject("description").getString(lang);
- } catch (JSONException e) {
- // TODO: handle exception!!
- try {
- desc = definition.getJSONObject("description").getString( definition.getString("default_language") );
- } catch (JSONException e2) {
- // TODO: i can't believe you're doing it again!
- }
- }
-
- return desc;
- }
-
- protected boolean hasEIP() {
- try {
+ }
+
+ return name;
+ }
+
+ protected String getDescription() {
+ String lang = Locale.getDefault().getLanguage();
+ String desc = null;
+ try {
+ desc = definition.getJSONObject("description").getString(lang);
+ } catch (JSONException e) {
+ // TODO: handle exception!!
+ try {
+ desc = definition.getJSONObject("description").getString(definition.getString("default_language"));
+ } catch (JSONException e2) {
+ // TODO: i can't believe you're doing it again!
+ }
+ }
+
+ return desc;
+ }
+
+ protected boolean hasEIP() {
+ try {
JSONArray services = definition.getJSONArray(API_TERM_SERVICES); // returns ["openvpn"]
- for (int i=0;i<API_EIP_TYPES.length+1;i++){
+ for (int i = 0; i < API_EIP_TYPES.length + 1; i++) {
try {
// Walk the EIP types array looking for matches in provider's service definitions
- if ( Arrays.asList(API_EIP_TYPES).contains( services.getString(i) ) )
+ if (Arrays.asList(API_EIP_TYPES).contains(services.getString(i)))
return true;
- } catch (NullPointerException e){
+ } catch (NullPointerException e) {
e.printStackTrace();
return false;
} catch (JSONException e) {
@@ -166,11 +158,19 @@ public final class Provider implements Parcelable {
return false;
}
}
- } catch (Exception e) {
- // TODO: handle exception
- }
- return false;
- }
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ return false;
+ }
+
+ public boolean allowsRegistration() {
+ try {
+ return definition.getJSONObject(Provider.SERVICE).getBoolean(Provider.ALLOW_REGISTRATION);
+ } catch (JSONException e) {
+ return false;
+ }
+ }
@Override
public int describeContents() {
@@ -180,13 +180,13 @@ public final class Provider implements Parcelable {
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(main_url.toString());
- if(definition != null)
+ if (definition != null)
parcel.writeString(definition.toString());
}
@Override
public boolean equals(Object o) {
- if(o instanceof Provider) {
+ if (o instanceof Provider) {
Provider p = (Provider) o;
return p.mainUrl().getHost().equals(mainUrl().getHost());
} else return false;
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java b/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java
index 7e4e95d3..533e5caf 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java
@@ -1,6 +1,6 @@
/**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -16,32 +16,30 @@
*/
package se.leap.bitmaskclient;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ResultReceiver;
+import android.os.*;
/**
- * Implements the ResultReceiver needed by Activities using ProviderAPI to receive the results of its operations.
- * @author parmegv
+ * Implements the ResultReceiver needed by Activities using ProviderAPI to receive the results of its operations.
*
+ * @author parmegv
*/
public class ProviderAPIResultReceiver extends ResultReceiver {
- private Receiver mReceiver;
-
- public ProviderAPIResultReceiver(Handler handler) {
- super(handler);
- // TODO Auto-generated constructor stub
- }
-
- public void setReceiver(Receiver receiver) {
+ private Receiver mReceiver;
+
+ public ProviderAPIResultReceiver(Handler handler) {
+ super(handler);
+ // TODO Auto-generated constructor stub
+ }
+
+ public void setReceiver(Receiver receiver) {
mReceiver = receiver;
}
- /**
- * Interface to enable ProviderAPIResultReceiver to receive results from the ProviderAPI IntentService.
- * @author parmegv
- *
- */
+ /**
+ * Interface to enable ProviderAPIResultReceiver to receive results from the ProviderAPI IntentService.
+ *
+ * @author parmegv
+ */
public interface Receiver {
public void onReceiveResult(int resultCode, Bundle resultData);
}
@@ -52,5 +50,5 @@ public class ProviderAPIResultReceiver extends ResultReceiver {
mReceiver.onReceiveResult(resultCode, resultData);
}
}
-
+
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java b/app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java
index c63e2edb..4a34caa0 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java
@@ -1,44 +1,35 @@
package se.leap.bitmaskclient;
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.TwoLineListItem;
+import android.view.*;
-import com.pedrogomez.renderers.AdapteeCollection;
-import com.pedrogomez.renderers.RendererAdapter;
-import com.pedrogomez.renderers.RendererBuilder;
+import com.pedrogomez.renderers.*;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
public class ProviderListAdapter extends RendererAdapter<Provider> {
- private static boolean[] hidden = null;
-
- public void hide(int position) {
- hidden[getRealPosition(position)] = true;
- notifyDataSetChanged();
- notifyDataSetInvalidated();
- }
-
- public void unHide(int position) {
- hidden[getRealPosition(position)] = false;
- notifyDataSetChanged();
- notifyDataSetInvalidated();
- }
+ private static boolean[] hidden = null;
+
+ public void hide(int position) {
+ hidden[getRealPosition(position)] = true;
+ notifyDataSetChanged();
+ notifyDataSetInvalidated();
+ }
+
+ public void unHide(int position) {
+ hidden[getRealPosition(position)] = false;
+ notifyDataSetChanged();
+ notifyDataSetInvalidated();
+ }
public void showAllProviders() {
- for(int i = 0; i < hidden.length; i++)
+ for (int i = 0; i < hidden.length; i++)
hidden[i] = false;
notifyDataSetChanged();
notifyDataSetInvalidated();
}
-
+
public void hideAllBut(int position) {
- for (int i = 0; i < hidden.length; i++) {
+ for (int i = 0; i < hidden.length; i++) {
if (i != position)
hidden[i] = true;
else
@@ -47,64 +38,66 @@ public class ProviderListAdapter extends RendererAdapter<Provider> {
notifyDataSetChanged();
notifyDataSetInvalidated();
}
-
- private int getRealPosition(int position) {
- int hElements = getHiddenCountUpTo(position);
- int diff = 0;
- for(int i=0;i<hElements;i++) {
- diff++;
- if(hidden[position+diff])
- i--;
- }
- return (position + diff);
- }
- private int getHiddenCount() {
- int count = 0;
- for(int i=0;i<hidden.length;i++)
- if(hidden[i])
- count++;
- return count;
- }
- private int getHiddenCountUpTo(int location) {
- int count = 0;
- for(int i=0;i<=location;i++) {
- if(hidden[i])
- count++;
- }
- return count;
- }
-
- @Override
- public int getCount() {
- return (hidden.length - getHiddenCount());
- }
+
+ private int getRealPosition(int position) {
+ int hElements = getHiddenCountUpTo(position);
+ int diff = 0;
+ for (int i = 0; i < hElements; i++) {
+ diff++;
+ if (hidden[position + diff])
+ i--;
+ }
+ return (position + diff);
+ }
+
+ private int getHiddenCount() {
+ int count = 0;
+ for (int i = 0; i < hidden.length; i++)
+ if (hidden[i])
+ count++;
+ return count;
+ }
+
+ private int getHiddenCountUpTo(int location) {
+ int count = 0;
+ for (int i = 0; i <= location; i++) {
+ if (hidden[i])
+ count++;
+ }
+ return count;
+ }
+
+ @Override
+ public int getCount() {
+ return (hidden.length - getHiddenCount());
+ }
public ProviderListAdapter(LayoutInflater layoutInflater, RendererBuilder rendererBuilder,
AdapteeCollection<Provider> collection) {
- super(layoutInflater, rendererBuilder, collection);
- hidden = new boolean[collection.size()];
- for (int i = 0; i < collection.size(); i++)
- hidden[i] = false;
+ super(layoutInflater, rendererBuilder, collection);
+ hidden = new boolean[collection.size()];
+ for (int i = 0; i < collection.size(); i++)
+ hidden[i] = false;
}
-
- @Override
- public void add(Provider item) {
- super.add(item);
- if(getCollection().size() > hidden.length) {
+
+ @Override
+ public void add(Provider item) {
+ super.add(item);
+ if (getCollection().size() > hidden.length) {
boolean[] new_hidden = new boolean[hidden.length + 1];
System.arraycopy(hidden, 0, new_hidden, 0, hidden.length);
new_hidden[hidden.length] = false;
hidden = new_hidden;
}
- }
-
- @Override
- public void remove(Provider item) {
- super.remove(item);
- boolean[] new_hidden = new boolean[hidden.length-1];
- System.arraycopy(hidden, 0, new_hidden, 0, hidden.length-1);
- hidden = new_hidden;
- }
+ }
+
+ @Override
+ public void remove(Provider item) {
+ super.remove(item);
+ boolean[] new_hidden = new boolean[hidden.length - 1];
+ System.arraycopy(hidden, 0, new_hidden, 0, hidden.length - 1);
+ hidden = new_hidden;
+ }
protected int indexOf(Provider item) {
int index = 0;
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java
index 69bd7c1e..40fe8b5a 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java
@@ -1,25 +1,14 @@
package se.leap.bitmaskclient;
-import android.content.res.AssetManager;
-
-import com.pedrogomez.renderers.AdapteeCollection;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
+import android.content.res.*;
+
+import com.pedrogomez.renderers.*;
+
+import org.json.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
/**
* Created by parmegv on 4/12/14.
@@ -36,7 +25,7 @@ public class ProviderManager implements AdapteeCollection<Provider> {
final protected static String URLS = "urls";
public static ProviderManager getInstance(AssetManager assets_manager, File external_files_dir) {
- if(instance == null)
+ if (instance == null)
instance = new ProviderManager(assets_manager);
instance.addCustomProviders(external_files_dir);
@@ -59,10 +48,10 @@ public class ProviderManager implements AdapteeCollection<Provider> {
private Set<Provider> providersFromAssets(String directory, String[] relative_file_paths) {
Set<Provider> providers = new HashSet<Provider>();
try {
- for(String file : relative_file_paths) {
- String main_url = extractMainUrlFromInputStream(assets_manager.open(directory + "/" + file));
+ for (String file : relative_file_paths) {
+ String main_url = extractMainUrlFromInputStream(assets_manager.open(directory + "/" + file));
providers.add(new Provider(new URL(main_url)));
- }
+ }
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
@@ -82,7 +71,7 @@ public class ProviderManager implements AdapteeCollection<Provider> {
private Set<Provider> providersFromFiles(String[] files) {
Set<Provider> providers = new HashSet<Provider>();
try {
- for(String file : files) {
+ for (String file : files) {
String main_url = extractMainUrlFromInputStream(new FileInputStream(external_files_dir.getAbsolutePath() + "/" + file));
providers.add(new Provider(new URL(main_url)));
}
@@ -100,7 +89,7 @@ public class ProviderManager implements AdapteeCollection<Provider> {
byte[] bytes = new byte[0];
try {
bytes = new byte[input_stream_file_contents.available()];
- if(input_stream_file_contents.read(bytes) > 0) {
+ if (input_stream_file_contents.read(bytes) > 0) {
JSONObject file_contents = new JSONObject(new String(bytes));
main_url = file_contents.getString(Provider.MAIN_URL);
}
@@ -127,7 +116,7 @@ public class ProviderManager implements AdapteeCollection<Provider> {
@Override
public Provider get(int index) {
Iterator<Provider> iterator = providers().iterator();
- while(iterator.hasNext() && index > 0) {
+ while (iterator.hasNext() && index > 0) {
iterator.next();
index--;
}
@@ -136,7 +125,7 @@ public class ProviderManager implements AdapteeCollection<Provider> {
@Override
public void add(Provider element) {
- if(!default_providers.contains(element))
+ if (!default_providers.contains(element))
custom_providers.add(element);
}
@@ -163,17 +152,17 @@ public class ProviderManager implements AdapteeCollection<Provider> {
}
protected void saveCustomProvidersToFile() {
- try {
- for (Provider provider : custom_providers) {
+ try {
+ for (Provider provider : custom_providers) {
File provider_file = new File(external_files_dir, provider.getName() + ".json");
- if(!provider_file.exists()) {
- FileWriter writer = new FileWriter(provider_file);
- writer.write(provider.toJson().toString());
- writer.close();
+ if (!provider_file.exists()) {
+ FileWriter writer = new FileWriter(provider_file);
+ writer.write(provider.toJson().toString());
+ writer.close();
+ }
}
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java b/app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java
index 6e194e84..4a5d0db1 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderRenderer.java
@@ -1,18 +1,12 @@
package se.leap.bitmaskclient;
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.pedrogomez.renderers.Renderer;
-
-import butterknife.ButterKnife;
-import butterknife.InjectView;
-import butterknife.OnItemClick;
-import butterknife.OnItemSelected;
+import android.content.*;
+import android.view.*;
+import android.widget.*;
+
+import com.pedrogomez.renderers.*;
+
+import butterknife.*;
/**
* Created by parmegv on 4/12/14.
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderRendererBuilder.java b/app/src/main/java/se/leap/bitmaskclient/ProviderRendererBuilder.java
index 7366e68e..5a6e857d 100644
--- a/app/src/main/java/se/leap/bitmaskclient/ProviderRendererBuilder.java
+++ b/app/src/main/java/se/leap/bitmaskclient/ProviderRendererBuilder.java
@@ -1,25 +1,19 @@
package se.leap.bitmaskclient;
-import android.content.Context;
+import com.pedrogomez.renderers.*;
-import com.pedrogomez.renderers.Renderer;
-import com.pedrogomez.renderers.RendererBuilder;
-
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-import javax.inject.Inject;
+import java.util.*;
/**
* Created by parmegv on 4/12/14.
*/
- public class ProviderRendererBuilder extends RendererBuilder<Provider> {
- public ProviderRendererBuilder(Collection<Renderer<Provider>> prototypes) {
- super(prototypes);
- }
- @Override
- protected Class getPrototypeClass(Provider content) {
- return ProviderRenderer.class;
+public class ProviderRendererBuilder extends RendererBuilder<Provider> {
+ public ProviderRendererBuilder(Collection<Renderer<Provider>> prototypes) {
+ super(prototypes);
+ }
+
+ @Override
+ protected Class getPrototypeClass(Provider content) {
+ return ProviderRenderer.class;
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java b/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java
index 9025564b..e92c6b7b 100644
--- a/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/SessionDialog.java
@@ -1,6 +1,6 @@
/**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -14,42 +14,38 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
- package se.leap.bitmaskclient;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.DialogFragment;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.EditText;
-import android.widget.TextView;
+package se.leap.bitmaskclient;
-import org.jetbrains.annotations.NotNull;
+import android.app.*;
+import android.content.*;
+import android.os.*;
+import android.view.*;
+import android.widget.*;
-import butterknife.ButterKnife;
-import butterknife.InjectView;
+import butterknife.*;
/**
* Implements the log in dialog, currently without progress dialog.
- *
+ * <p/>
* It returns to the previous fragment when finished, and sends username and password to the authenticate method.
- *
- * It also notifies the user if the password is not valid.
- *
- * @author parmegv
+ * <p/>
+ * It also notifies the user if the password is not valid.
*
+ * @author parmegv
*/
-public class SessionDialog extends DialogFragment{
+public class SessionDialog extends DialogFragment {
+
-
final public static String TAG = SessionDialog.class.getSimpleName();
final public static String USERNAME = "username";
final public static String PASSWORD = "password";
- final public static String USERNAME_MISSING = "username missing";
- final public static String PASSWORD_INVALID_LENGTH = "password_invalid_length";
+
+ public static enum ERRORS {
+ USERNAME_MISSING,
+ PASSWORD_INVALID_LENGTH,
+ RISEUP_WARNING
+ }
@InjectView(R.id.user_message)
TextView user_message;
@@ -63,63 +59,67 @@ public class SessionDialog extends DialogFragment{
public SessionDialog() {
setArguments(Bundle.EMPTY);
}
-
- public AlertDialog onCreateDialog(Bundle savedInstanceState) {
-
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- LayoutInflater inflater = getActivity().getLayoutInflater();
- View view = inflater.inflate(R.layout.session_dialog, null);
- ButterKnife.inject(this, view);
-
- Bundle arguments = getArguments();
- if (arguments != Bundle.EMPTY) {
+
+ public AlertDialog onCreateDialog(Bundle savedInstanceState) {
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ LayoutInflater inflater = getActivity().getLayoutInflater();
+ View view = inflater.inflate(R.layout.session_dialog, null);
+ ButterKnife.inject(this, view);
+
+ Bundle arguments = getArguments();
+ if (arguments != Bundle.EMPTY) {
setUp(arguments);
- }
-
- builder.setView(view)
- .setPositiveButton(R.string.login_button, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- String username = getEnteredUsername();
- String password = getEnteredPassword();
- dialog.dismiss();
- interface_with_Dashboard.logIn(username, password);
- }
- })
- .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- dialog.cancel();
- interface_with_Dashboard.cancelLoginOrSignup();
- }
- })
- .setNeutralButton(R.string.signup_button, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- String username = getEnteredUsername();
- String password = getEnteredPassword();
- dialog.dismiss();
- interface_with_Dashboard.signUp(username, password);
- }
- });
-
- return builder.create();
- }
+ }
+
+ builder.setView(view)
+ .setPositiveButton(R.string.login_button, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ String username = getEnteredUsername();
+ String password = getEnteredPassword();
+ dialog.dismiss();
+ interface_with_Dashboard.logIn(username, password);
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.cancel();
+ interface_with_Dashboard.cancelLoginOrSignup();
+ }
+ })
+ .setNeutralButton(R.string.signup_button, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ String username = getEnteredUsername();
+ String password = getEnteredPassword();
+ dialog.dismiss();
+ interface_with_Dashboard.signUp(username, password);
+ }
+ });
+
+ return builder.create();
+ }
private void setUp(Bundle arguments) {
is_eip_pending = arguments.getBoolean(EipFragment.IS_PENDING, false);
- if (arguments.containsKey(PASSWORD_INVALID_LENGTH))
+ if (arguments.containsKey(ERRORS.PASSWORD_INVALID_LENGTH.toString()))
password_field.setError(getString(R.string.error_not_valid_password_user_message));
+ else if (arguments.containsKey(ERRORS.RISEUP_WARNING.toString())) {
+ user_message.setVisibility(TextView.VISIBLE);
+ user_message.setText(R.string.login_riseup_warning);
+ }
if (arguments.containsKey(USERNAME)) {
String username = arguments.getString(USERNAME);
username_field.setText(username);
}
- if (arguments.containsKey(USERNAME_MISSING)) {
+ if (arguments.containsKey(ERRORS.USERNAME_MISSING.toString())) {
username_field.setError(getString(R.string.username_ask));
}
- if(arguments.containsKey(getString(R.string.user_message)))
+ if (arguments.containsKey(getString(R.string.user_message)))
user_message.setText(arguments.getString(getString(R.string.user_message)));
- else
+ else if (user_message.getVisibility() != TextView.VISIBLE)
user_message.setVisibility(View.GONE);
- if(!username_field.getText().toString().isEmpty() && password_field.isFocusable())
+ if (!username_field.getText().toString().isEmpty() && password_field.isFocusable())
password_field.requestFocus();
}
@@ -132,26 +132,27 @@ public class SessionDialog extends DialogFragment{
return password_field.getText().toString();
}
-
- /**
- * Interface used to communicate SessionDialog with Dashboard.
- *
- * @author parmegv
- *
- */
- public interface SessionDialogInterface {
- public void logIn(String username, String password);
- public void signUp(String username, String password);
- public void cancelLoginOrSignup();
+
+ /**
+ * Interface used to communicate SessionDialog with Dashboard.
+ *
+ * @author parmegv
+ */
+ public interface SessionDialogInterface {
+ public void logIn(String username, String password);
+
+ public void signUp(String username, String password);
+
+ public void cancelLoginOrSignup();
}
- SessionDialogInterface interface_with_Dashboard;
-
+ SessionDialogInterface interface_with_Dashboard;
+
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
- interface_with_Dashboard = (SessionDialogInterface) activity;
+ interface_with_Dashboard = (SessionDialogInterface) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement LogInDialogListener");
@@ -160,8 +161,8 @@ public class SessionDialog extends DialogFragment{
@Override
public void onCancel(DialogInterface dialog) {
- super.onCancel(dialog);
- if(is_eip_pending)
- interface_with_Dashboard.cancelLoginOrSignup();
+ super.onCancel(dialog);
+ if (is_eip_pending)
+ interface_with_Dashboard.cancelLoginOrSignup();
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/User.java b/app/src/main/java/se/leap/bitmaskclient/User.java
new file mode 100644
index 00000000..4bbd9a91
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/User.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2013 LEAP Encryption Access Project and contributers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package se.leap.bitmaskclient;
+
+public class User {
+ private static String user_name = "You";
+ private static User user;
+
+ public static User getInstance() {
+ if (user == null) {
+ user = new User();
+ }
+ return user;
+ }
+
+ public static void setUserName(String user_name) {
+ User.user_name = user_name;
+ }
+
+ private User() {
+ }
+
+ public static String userName() {
+ return user_name;
+ }
+
+ public static boolean loggedIn() {
+ return LeapSRPSession.loggedIn();
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java b/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java
new file mode 100644
index 00000000..e43c8a25
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/UserSessionStatus.java
@@ -0,0 +1,87 @@
+/**
+ * Copyright (c) 2013 LEAP Encryption Access Project and contributers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package se.leap.bitmaskclient;
+
+import android.os.*;
+
+import java.util.*;
+
+public class UserSessionStatus extends Observable {
+ public static String TAG = UserSessionStatus.class.getSimpleName();
+ private static UserSessionStatus current_status;
+
+ public enum SessionStatus {
+ LOGGED_IN,
+ LOGGED_OUT,
+ NOT_LOGGED_IN,
+ DIDNT_LOG_OUT,
+ LOGGING_IN,
+ LOGGING_OUT,
+ SIGNING_UP
+ }
+
+ private static SessionStatus session_status = SessionStatus.NOT_LOGGED_IN;
+
+ public static UserSessionStatus getInstance() {
+ if (current_status == null) {
+ current_status = new UserSessionStatus();
+ }
+ return current_status;
+ }
+
+ private UserSessionStatus() {
+ }
+
+ private void sessionStatus(SessionStatus session_status) {
+ this.session_status = session_status;
+ }
+
+ public SessionStatus sessionStatus() {
+ return session_status;
+ }
+
+ public boolean inProgress() {
+ return session_status == SessionStatus.LOGGING_IN
+ || session_status == SessionStatus.LOGGING_OUT;
+ }
+
+ public static void updateStatus(SessionStatus session_status) {
+ current_status = getInstance();
+ current_status.sessionStatus(session_status);
+ current_status.setChanged();
+ current_status.notifyObservers();
+ }
+
+ @Override
+ public String toString() {
+ String username = User.userName();
+
+ return username + " " + conjugateToBe(username) + " "
+ + session_status.toString().toLowerCase().replaceAll("_", " ");
+ }
+
+ private String conjugateToBe(String subject) {
+ String conjugation = "";
+ if(subject.equalsIgnoreCase("I"))
+ conjugation = "am";
+ else if(subject.equalsIgnoreCase("you") || subject.equalsIgnoreCase("we")|| subject.equalsIgnoreCase("they"))
+ conjugation = "are";
+ else conjugation = "is";
+
+ return conjugation;
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java
index 12c2e015..39ad7c08 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java
@@ -1,6 +1,6 @@
/**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -17,17 +17,14 @@
package se.leap.bitmaskclient.eip;
/**
- *
* Constants for intent passing, shared preferences
*
* @author Parménides GV <parmegv@sdf.org>
- *
*/
public interface Constants {
public final static String TAG = Constants.class.getSimpleName();
-
- public final static String AUTHED_EIP = TAG + ".AUTHED_EIP";
+
public final static String ACTION_CHECK_CERT_VALIDITY = TAG + ".CHECK_CERT_VALIDITY";
public final static String ACTION_START_EIP = TAG + ".START_EIP";
public final static String ACTION_STOP_EIP = TAG + ".STOP_EIP";
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 3b72a486..beed7948 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
@@ -1,6 +1,6 @@
/**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -19,7 +19,6 @@ package se.leap.bitmaskclient.eip;
import android.app.*;
import android.content.*;
import android.os.*;
-import android.util.Log;
import org.json.*;
@@ -34,7 +33,7 @@ import static se.leap.bitmaskclient.eip.Constants.*;
* this IntentService.
* Contains logic for parsing eip-service.json from the provider, configuring and selecting
* gateways, and controlling {@link de.blinkt.openvpn.core.OpenVPNService} connections.
- *
+ *
* @author Sean Leonard <meanderingcode@aetherislands.net>
* @author Parménides GV <parmegv@sdf.org>
*/
@@ -44,64 +43,64 @@ public final class EIP extends IntentService {
public final static String SERVICE_API_PATH = "config/eip-service.json";
public static final int DISCONNECT = 15;
-
+
private static Context context;
private static ResultReceiver mReceiver;
private static SharedPreferences preferences;
-
+
private static JSONObject eip_definition;
private static GatewaysManager gateways_manager = new GatewaysManager();
private static Gateway gateway;
-
- public EIP(){
- super(TAG);
+
+ public EIP() {
+ super(TAG);
}
-
+
@Override
public void onCreate() {
- super.onCreate();
-
- context = getApplicationContext();
+ super.onCreate();
+
+ context = getApplicationContext();
preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE);
- eip_definition = eipDefinitionFromPreferences();
- if(gateways_manager.isEmpty())
+ eip_definition = eipDefinitionFromPreferences();
+ if (gateways_manager.isEmpty())
gatewaysFromPreferences();
}
@Override
protected void onHandleIntent(Intent intent) {
- String action = intent.getAction();
- mReceiver = intent.getParcelableExtra(RECEIVER_TAG);
-
- if ( action.equals(ACTION_START_EIP))
- startEIP();
- else if (action.equals(ACTION_STOP_EIP))
- stopEIP();
- else if (action.equals(ACTION_IS_EIP_RUNNING))
- isRunning();
+ String action = intent.getAction();
+ mReceiver = intent.getParcelableExtra(RECEIVER_TAG);
+
+ if (action.equals(ACTION_START_EIP))
+ startEIP();
+ else if (action.equals(ACTION_STOP_EIP))
+ stopEIP();
+ else if (action.equals(ACTION_IS_EIP_RUNNING))
+ isRunning();
else if (action.equals(ACTION_UPDATE_EIP_SERVICE))
- updateEIPService();
- else if (action.equals(ACTION_CHECK_CERT_VALIDITY))
- checkCertValidity();
+ updateEIPService();
+ else if (action.equals(ACTION_CHECK_CERT_VALIDITY))
+ checkCertValidity();
}
-
+
/**
* Initiates an EIP connection by selecting a gateway and preparing and sending an
* Intent to {@link de.blinkt.openvpn.LaunchVPN}.
* It also sets up early routes.
*/
private void startEIP() {
- if(gateways_manager.isEmpty())
- updateEIPService();
+ if (gateways_manager.isEmpty())
+ updateEIPService();
earlyRoutes();
- gateway = gateways_manager.select();
- if(gateway != null && gateway.getProfile() != null) {
- mReceiver = EipFragment.getReceiver();
- launchActiveGateway();
- tellToReceiver(ACTION_START_EIP, Activity.RESULT_OK);
- } else
- tellToReceiver(ACTION_START_EIP, Activity.RESULT_CANCELED);
+ gateway = gateways_manager.select();
+ if (gateway != null && gateway.getProfile() != null) {
+ mReceiver = EipFragment.getReceiver();
+ launchActiveGateway();
+ tellToReceiver(ACTION_START_EIP, Activity.RESULT_OK);
+ } else
+ tellToReceiver(ACTION_START_EIP, Activity.RESULT_CANCELED);
}
/**
@@ -109,40 +108,40 @@ public final class EIP extends IntentService {
* VpnService is started properly.
*/
private void earlyRoutes() {
- Intent void_vpn_launcher = new Intent(context, VoidVpnLauncher.class);
- void_vpn_launcher.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(void_vpn_launcher);
+ Intent void_vpn_launcher = new Intent(context, VoidVpnLauncher.class);
+ void_vpn_launcher.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(void_vpn_launcher);
}
-
+
private void launchActiveGateway() {
- Intent intent = new Intent(this,LaunchVPN.class);
- intent.setAction(Intent.ACTION_MAIN);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra(LaunchVPN.EXTRA_NAME, gateway.getProfile().getName());
- intent.putExtra(LaunchVPN.EXTRA_HIDELOG, true);
- startActivity(intent);
+ Intent intent = new Intent(this, LaunchVPN.class);
+ intent.setAction(Intent.ACTION_MAIN);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(LaunchVPN.EXTRA_NAME, gateway.getProfile().getName());
+ intent.putExtra(LaunchVPN.EXTRA_HIDELOG, true);
+ startActivity(intent);
}
private void stopEIP() {
- EipStatus eip_status = EipStatus.getInstance();
- int result_code = Activity.RESULT_CANCELED;
- if(eip_status.isConnected() || eip_status.isConnecting())
- result_code = Activity.RESULT_OK;
+ EipStatus eip_status = EipStatus.getInstance();
+ int result_code = Activity.RESULT_CANCELED;
+ if (eip_status.isConnected() || eip_status.isConnecting())
+ result_code = Activity.RESULT_OK;
- tellToReceiver(ACTION_STOP_EIP, result_code);
+ tellToReceiver(ACTION_STOP_EIP, result_code);
}
-
+
/**
* Checks the last stored status notified by ics-openvpn
* Sends <code>Activity.RESULT_CANCELED</code> to the ResultReceiver that made the
* request if it's not connected, <code>Activity.RESULT_OK</code> otherwise.
*/
private void isRunning() {
- EipStatus eip_status = EipStatus.getInstance();
- int resultCode = (eip_status.isConnected()) ?
- Activity.RESULT_OK :
- Activity.RESULT_CANCELED;
- tellToReceiver(ACTION_IS_EIP_RUNNING, resultCode);
+ EipStatus eip_status = EipStatus.getInstance();
+ int resultCode = (eip_status.isConnected()) ?
+ Activity.RESULT_OK :
+ Activity.RESULT_CANCELED;
+ tellToReceiver(ACTION_IS_EIP_RUNNING, resultCode);
}
/**
@@ -150,27 +149,27 @@ public final class EIP extends IntentService {
* TODO Implement API call to refresh eip-service.json from the provider
*/
private void updateEIPService() {
- eip_definition = eipDefinitionFromPreferences();
- if(eip_definition.length() > 0)
+ eip_definition = eipDefinitionFromPreferences();
+ if (eip_definition.length() > 0)
updateGateways();
- tellToReceiver(ACTION_UPDATE_EIP_SERVICE, Activity.RESULT_OK);
+ tellToReceiver(ACTION_UPDATE_EIP_SERVICE, Activity.RESULT_OK);
}
private JSONObject eipDefinitionFromPreferences() {
JSONObject result = new JSONObject();
- try {
- String eip_definition_string = preferences.getString(KEY, "");
- if(!eip_definition_string.isEmpty()) {
- result = new JSONObject(eip_definition_string);
- }
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
+ try {
+ String eip_definition_string = preferences.getString(KEY, "");
+ if (!eip_definition_string.isEmpty()) {
+ result = new JSONObject(eip_definition_string);
+ }
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
return result;
}
- private void updateGateways(){
+ private void updateGateways() {
gateways_manager.fromEipServiceJson(eip_definition);
gatewaysToPreferences();
}
@@ -188,15 +187,15 @@ public final class EIP extends IntentService {
}
private void checkCertValidity() {
- VpnCertificateValidator validator = new VpnCertificateValidator(preferences.getString(CERTIFICATE, ""));
- int resultCode = validator.isValid() ?
- Activity.RESULT_OK :
- Activity.RESULT_CANCELED;
- tellToReceiver(ACTION_CHECK_CERT_VALIDITY, resultCode);
+ VpnCertificateValidator validator = new VpnCertificateValidator(preferences.getString(CERTIFICATE, ""));
+ int resultCode = validator.isValid() ?
+ Activity.RESULT_OK :
+ Activity.RESULT_CANCELED;
+ tellToReceiver(ACTION_CHECK_CERT_VALIDITY, resultCode);
}
private void tellToReceiver(String action, int resultCode) {
- if (mReceiver != null){
+ if (mReceiver != null) {
Bundle resultData = new Bundle();
resultData.putString(REQUEST_TAG, action);
mReceiver.send(resultCode, resultData);
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
index 4ac3bd6a..ad68f96e 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
@@ -1,6 +1,6 @@
/**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -16,11 +16,11 @@
*/
package se.leap.bitmaskclient.eip;
-import android.util.Log;
+import android.content.*;
-import java.util.Observable;
+import java.util.*;
-import de.blinkt.openvpn.core.VpnStatus;
+import de.blinkt.openvpn.core.*;
public class EipStatus extends Observable implements VpnStatus.StateListener {
public static String TAG = EipStatus.class.getSimpleName();
@@ -33,106 +33,123 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
private int localized_res_id;
public static EipStatus getInstance() {
- if(current_status == null) {
- current_status = new EipStatus();
- VpnStatus.addStateListener(current_status);
- }
- return current_status;
+ if (current_status == null) {
+ current_status = new EipStatus();
+ VpnStatus.addStateListener(current_status);
+ }
+ return current_status;
}
- private EipStatus() { }
+ private EipStatus() {
+ }
@Override
public void updateState(final String state, final String logmessage, final int localizedResId, final VpnStatus.ConnectionStatus level) {
- current_status = getInstance();
- current_status.setState(state);
- current_status.setLogMessage(logmessage);
- current_status.setLocalizedResId(localizedResId);
- current_status.setLevel(level);
- current_status.setChanged();
- if(isConnected() || isDisconnected())
- setConnectedOrDisconnected();
- else if(isConnecting())
- setConnecting();
- Log.d(TAG, "update state with level " + level);
- current_status.notifyObservers();
+ updateStatus(state, logmessage, localizedResId, level);
+ if (isConnected() || isDisconnected()) {
+ setConnectedOrDisconnected();
+ } else if (isConnecting())
+ setConnecting();
+ }
+
+ private void updateStatus(final String state, final String logmessage, final int localizedResId, final VpnStatus.ConnectionStatus level) {
+ current_status = getInstance();
+ current_status.setState(state);
+ current_status.setLogMessage(logmessage);
+ current_status.setLocalizedResId(localizedResId);
+ current_status.setLevel(level);
+ current_status.setChanged();
}
public boolean wantsToDisconnect() {
- return wants_to_disconnect;
+ return wants_to_disconnect;
}
public boolean isConnecting() {
- return
- !isConnected() &&
- !isDisconnected() &&
- !isPaused();
+ return
+ !isConnected() &&
+ !isDisconnected() &&
+ !isPaused();
}
public boolean isConnected() {
- return level == VpnStatus.ConnectionStatus.LEVEL_CONNECTED;
+ return level == VpnStatus.ConnectionStatus.LEVEL_CONNECTED;
}
public boolean isDisconnected() {
- return level == VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED;
+ return level == VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED;
}
public boolean isPaused() {
- return level == VpnStatus.ConnectionStatus.LEVEL_VPNPAUSED;
+ return level == VpnStatus.ConnectionStatus.LEVEL_VPNPAUSED;
}
public void setConnecting() {
- wants_to_disconnect = false;
- current_status.setChanged();
- current_status.notifyObservers();
+ wants_to_disconnect = false;
+ current_status.setChanged();
+ current_status.notifyObservers();
}
public void setConnectedOrDisconnected() {
- Log.d(TAG, "setConnectedOrDisconnected()");
- wants_to_disconnect = false;
- current_status.setChanged();
- current_status.notifyObservers();
+ wants_to_disconnect = false;
+ current_status.setChanged();
+ current_status.notifyObservers();
}
public void setDisconnecting() {
- wants_to_disconnect = false;
+ wants_to_disconnect = false;
}
public String getState() {
- return state;
+ return state;
}
public String getLogMessage() {
- return log_message;
+ return log_message;
}
public int getLocalizedResId() {
- return localized_res_id;
+ return localized_res_id;
}
public VpnStatus.ConnectionStatus getLevel() {
- return level;
+ return level;
}
private void setState(String state) {
- this.state = state;
+ this.state = state;
}
private void setLogMessage(String log_message) {
- this.log_message = log_message;
+ this.log_message = log_message;
}
private void setLocalizedResId(int localized_res_id) {
- this.localized_res_id = localized_res_id;
+ this.localized_res_id = localized_res_id;
}
private void setLevel(VpnStatus.ConnectionStatus level) {
- EipStatus.level = level;
+ EipStatus.level = level;
+ }
+
+ public boolean errorInLast(int lines, Context context) {
+ boolean result = false;
+ String[] error_keywords = {"error", "ERROR", "fatal", "FATAL"};
+
+ VpnStatus.LogItem[] log = VpnStatus.getlogbuffer();
+ String message = "";
+ for (int i = 1; i <= lines && log.length > i; i++) {
+ message = log[log.length - i].getString(context);
+ for (int j = 0; j < error_keywords.length; j++)
+ if (message.contains(error_keywords[j]))
+ result = true;
+ }
+ return result;
}
@Override
public String toString() {
- return "State: " + state + " Level: " + level.toString();
+ return "State: " + state + " Level: " + level.toString();
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
index 0d8a2f7b..ff7d011e 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
@@ -1,6 +1,6 @@
/**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -16,32 +16,25 @@
*/
package se.leap.bitmaskclient.eip;
-import android.app.Activity;
-import android.content.SharedPreferences;
-import android.util.Log;
-
-import com.google.gson.Gson;
+import com.google.gson.*;
-import org.json.JSONException;
-import org.json.JSONObject;
+import org.json.*;
-import java.io.IOException;
-import java.io.StringReader;
+import java.io.*;
-import de.blinkt.openvpn.VpnProfile;
-import de.blinkt.openvpn.core.ConfigParser;
-import se.leap.bitmaskclient.Dashboard;
+import de.blinkt.openvpn.*;
+import de.blinkt.openvpn.core.*;
/**
* Gateway provides objects defining gateways and their metadata.
* Each instance contains a VpnProfile for OpenVPN specific data and member
* variables describing capabilities and location (name)
- *
+ *
* @author Sean Leonard <meanderingcode@aetherislands.net>
* @author Parménides GV <parmegv@sdf.org>
*/
public class Gateway {
-
+
public final static String TAG = Gateway.class.getSimpleName();
private JSONObject general_configuration;
@@ -51,86 +44,85 @@ public class Gateway {
private String mName;
private int timezone;
private VpnProfile mVpnProfile;
+
/**
* Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json
* and create a VpnProfile belonging to it.
*/
- public Gateway(JSONObject eip_definition, JSONObject secrets, JSONObject gateway){
+ public Gateway(JSONObject eip_definition, JSONObject secrets, JSONObject gateway) {
- this.gateway = gateway;
+ this.gateway = gateway;
this.secrets = secrets;
- general_configuration = getGeneralConfiguration(eip_definition);
- timezone = getTimezone(eip_definition);
- mName = locationAsName(eip_definition);
+ general_configuration = getGeneralConfiguration(eip_definition);
+ timezone = getTimezone(eip_definition);
+ mName = locationAsName(eip_definition);
- mVpnProfile = createVPNProfile();
- mVpnProfile.mName = mName;
+ mVpnProfile = createVPNProfile();
+ mVpnProfile.mName = mName;
}
private JSONObject getGeneralConfiguration(JSONObject eip_definition) {
- try {
- return eip_definition.getJSONObject("openvpn_configuration");
- } catch (JSONException e) {
- return new JSONObject();
- }
+ try {
+ return eip_definition.getJSONObject("openvpn_configuration");
+ } catch (JSONException e) {
+ return new JSONObject();
+ }
}
private int getTimezone(JSONObject eip_definition) {
- JSONObject location = getLocationInfo(eip_definition);
- return location.optInt("timezone");
+ JSONObject location = getLocationInfo(eip_definition);
+ return location.optInt("timezone");
}
private String locationAsName(JSONObject eip_definition) {
- JSONObject location = getLocationInfo(eip_definition);
- return location.optString("name");
+ JSONObject location = getLocationInfo(eip_definition);
+ return location.optString("name");
}
private JSONObject getLocationInfo(JSONObject eip_definition) {
- try {
- JSONObject locations = eip_definition.getJSONObject("locations");
+ try {
+ JSONObject locations = eip_definition.getJSONObject("locations");
- return locations.getJSONObject(gateway.getString("location"));
- } catch (JSONException e) {
- return new JSONObject();
- }
+ return locations.getJSONObject(gateway.getString("location"));
+ } catch (JSONException e) {
+ return new JSONObject();
+ }
}
-
+
/**
* Create and attach the VpnProfile to our gateway object
*/
- private VpnProfile createVPNProfile(){
- try {
- ConfigParser cp = new ConfigParser();
-
- VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(general_configuration, secrets, gateway);
- String configuration = vpn_configuration_generator.generate();
-
- cp.parseConfig(new StringReader(configuration));
- return cp.convertProfile();
- } catch (ConfigParser.ConfigParseError e) {
- // FIXME We didn't get a VpnProfile! Error handling! and log level
- Log.v(TAG,"Error creating VPNProfile");
- e.printStackTrace();
- return null;
- } catch (IOException e) {
- // FIXME We didn't get a VpnProfile! Error handling! and log level
- Log.v(TAG,"Error creating VPNProfile");
- e.printStackTrace();
- return null;
- }
+ private VpnProfile createVPNProfile() {
+ try {
+ ConfigParser cp = new ConfigParser();
+
+ VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(general_configuration, secrets, gateway);
+ String configuration = vpn_configuration_generator.generate();
+
+ cp.parseConfig(new StringReader(configuration));
+ return cp.convertProfile();
+ } catch (ConfigParser.ConfigParseError e) {
+ // FIXME We didn't get a VpnProfile! Error handling! and log level
+ e.printStackTrace();
+ return null;
+ } catch (IOException e) {
+ // FIXME We didn't get a VpnProfile! Error handling! and log level
+ e.printStackTrace();
+ return null;
+ }
}
public String getName() {
- return mName;
+ return mName;
}
public VpnProfile getProfile() {
- return mVpnProfile;
+ return mVpnProfile;
}
public int getTimezone() {
- return timezone;
+ return timezone;
}
@Override
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java
index 39ae7ca6..90c8f890 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java
@@ -1,46 +1,42 @@
package se.leap.bitmaskclient.eip;
-import java.util.Calendar;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeMap;
+import java.util.*;
public class GatewaySelector {
List<Gateway> gateways;
public GatewaySelector(List<Gateway> gateways) {
- this.gateways = gateways;
+ this.gateways = gateways;
}
public Gateway select() {
- return closestGateway();
+ return closestGateway();
}
-
+
private Gateway closestGateway() {
- TreeMap<Integer, Set<Gateway>> offsets = calculateOffsets();
- return offsets.isEmpty() ? null : offsets.firstEntry().getValue().iterator().next();
+ TreeMap<Integer, Set<Gateway>> offsets = calculateOffsets();
+ return offsets.isEmpty() ? null : offsets.firstEntry().getValue().iterator().next();
}
-
+
private TreeMap<Integer, Set<Gateway>> calculateOffsets() {
- TreeMap<Integer, Set<Gateway>> offsets = new TreeMap<Integer, Set<Gateway>>();
- int localOffset = Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000;
- for(Gateway gateway : gateways) {
- int dist = timezoneDistance(localOffset, gateway.getTimezone());
- Set<Gateway> set = (offsets.get(dist) != null) ?
- offsets.get(dist) : new HashSet<Gateway>();
- set.add(gateway);
- offsets.put(dist, set);
- }
- return offsets;
+ TreeMap<Integer, Set<Gateway>> offsets = new TreeMap<Integer, Set<Gateway>>();
+ int localOffset = Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000;
+ for (Gateway gateway : gateways) {
+ int dist = timezoneDistance(localOffset, gateway.getTimezone());
+ Set<Gateway> set = (offsets.get(dist) != null) ?
+ offsets.get(dist) : new HashSet<Gateway>();
+ set.add(gateway);
+ offsets.put(dist, set);
+ }
+ return offsets;
}
-
+
private int timezoneDistance(int local_timezone, int remote_timezone) {
- // Distance along the numberline of Prime Meridian centric, assumes UTC-11 through UTC+12
- int dist = Math.abs(local_timezone - remote_timezone);
- // Farther than 12 timezones and it's shorter around the "back"
- if (dist > 12)
- dist = 12 - (dist -12); // Well i'll be. Absolute values make equations do funny things.
- return dist;
+ // Distance along the numberline of Prime Meridian centric, assumes UTC-11 through UTC+12
+ int dist = Math.abs(local_timezone - remote_timezone);
+ // Farther than 12 timezones and it's shorter around the "back"
+ if (dist > 12)
+ dist = 12 - (dist - 12); // Well i'll be. Absolute values make equations do funny things.
+ return dist;
}
}
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 401cd701..1c64328e 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
@@ -17,7 +17,6 @@
package se.leap.bitmaskclient.eip;
import android.content.*;
-import android.util.Log;
import com.google.gson.*;
import com.google.gson.reflect.*;
@@ -40,15 +39,18 @@ public class GatewaysManager {
private SharedPreferences preferences;
private List<Gateway> gateways = new ArrayList<>();
private ProfileManager profile_manager;
- private Type list_type = new TypeToken<ArrayList<Gateway>>() {}.getType();
+ private Type list_type = new TypeToken<ArrayList<Gateway>>() {
+ }.getType();
- public GatewaysManager() {}
+ public GatewaysManager() {
+ }
public GatewaysManager(Context context, SharedPreferences preferences) {
this.context = context;
this.preferences = preferences;
profile_manager = ProfileManager.getInstance(context);
}
+
public Gateway select() {
GatewaySelector gateway_selector = new GatewaySelector(gateways);
return gateway_selector.select();
@@ -66,16 +68,15 @@ public class GatewaysManager {
List<Gateway> gateways_list = new ArrayList<Gateway>();
try {
gateways_list = new Gson().fromJson(gateways, list_type);
- } catch(JsonSyntaxException e) {
+ } catch (JsonSyntaxException e) {
gateways_list.add(new Gson().fromJson(gateways, Gateway.class));
}
- if(gateways_list != null) {
+ if (gateways_list != null) {
for (Gateway gateway : gateways_list)
- addGateway(gateway);
+ addGateway(gateway);
this.gateways.addAll(gateways_list);
- } else
- Log.d("GatewaysManager", "No gateways added");
+ }
}
@Override
@@ -85,21 +86,21 @@ public class GatewaysManager {
public void fromEipServiceJson(JSONObject eip_definition) {
try {
- JSONArray gatewaysDefined = eip_definition.getJSONArray("gateways");
- for (int i = 0; i < gatewaysDefined.length(); i++) {
- JSONObject gw = gatewaysDefined.getJSONObject(i);
- if (isOpenVpnGateway(gw)) {
- JSONObject secrets = secretsConfiguration();
- Gateway aux = new Gateway(eip_definition, secrets, gw);
- if(!containsProfileWithSecrets(aux.getProfile())) {
- addGateway(aux);
- }
- }
- }
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
+ JSONArray gatewaysDefined = eip_definition.getJSONArray("gateways");
+ for (int i = 0; i < gatewaysDefined.length(); i++) {
+ JSONObject gw = gatewaysDefined.getJSONObject(i);
+ if (isOpenVpnGateway(gw)) {
+ JSONObject secrets = secretsConfiguration();
+ Gateway aux = new Gateway(eip_definition, secrets, gw);
+ if (!containsProfileWithSecrets(aux.getProfile())) {
+ addGateway(aux);
+ }
+ }
+ }
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
}
private boolean isOpenVpnGateway(JSONObject gateway) {
@@ -127,10 +128,10 @@ public class GatewaysManager {
boolean result = false;
Collection<VpnProfile> profiles = profile_manager.getProfiles();
- for(VpnProfile aux : profiles) {
+ for (VpnProfile aux : profiles) {
result = result || sameConnections(profile.mConnections, aux.mConnections)
- && profile.mClientCertFilename.equalsIgnoreCase(aux.mClientCertFilename)
- && profile.mClientKeyFilename.equalsIgnoreCase(aux.mClientKeyFilename);
+ && profile.mClientCertFilename.equalsIgnoreCase(aux.mClientCertFilename)
+ && profile.mClientKeyFilename.equalsIgnoreCase(aux.mClientKeyFilename);
}
return result;
}
@@ -149,9 +150,9 @@ public class GatewaysManager {
private void removeDuplicatedGateway(Gateway gateway) {
Iterator<Gateway> it = gateways.iterator();
List<Gateway> gateways_to_remove = new ArrayList<>();
- while(it.hasNext()) {
+ while (it.hasNext()) {
Gateway aux = it.next();
- if(sameConnections(aux.getProfile().mConnections, gateway.getProfile().mConnections)) {
+ if (sameConnections(aux.getProfile().mConnections, gateway.getProfile().mConnections)) {
gateways_to_remove.add(aux);
}
}
@@ -160,21 +161,21 @@ public class GatewaysManager {
}
private void removeDuplicatedProfiles(VpnProfile original) {
- Collection<VpnProfile> profiles = profile_manager.getProfiles();
+ Collection<VpnProfile> profiles = profile_manager.getProfiles();
List<VpnProfile> remove_list = new ArrayList<>();
- for(VpnProfile aux : profiles) {
- if (sameConnections(original.mConnections, aux.mConnections))
- remove_list.add(aux);
- }
+ for (VpnProfile aux : profiles) {
+ if (sameConnections(original.mConnections, aux.mConnections))
+ remove_list.add(aux);
+ }
for (VpnProfile profile : remove_list)
profile_manager.removeProfile(context, profile);
}
private boolean sameConnections(Connection[] c1, Connection[] c2) {
int same_connections = 0;
- for(Connection c1_aux : c1) {
- for(Connection c2_aux : c2)
- if(c2_aux.mServerName.equals(c1_aux.mServerName)) {
+ for (Connection c1_aux : c1) {
+ for (Connection c2_aux : c2)
+ if (c2_aux.mServerName.equals(c1_aux.mServerName)) {
same_connections++;
break;
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java
index d79d8003..5c9263b3 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java
@@ -1,9 +1,9 @@
package se.leap.bitmaskclient.eip;
-import android.app.Activity;
-import android.content.Intent;
-import android.net.VpnService;
-import android.os.Bundle;
+import android.app.*;
+import android.content.*;
+import android.net.*;
+import android.os.*;
public class VoidVpnLauncher extends Activity {
@@ -11,27 +11,27 @@ public class VoidVpnLauncher extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setUp();
+ super.onCreate(savedInstanceState);
+ setUp();
}
-
+
public void setUp() {
- Intent blocking_intent = VpnService.prepare(getApplicationContext()); // stops the VPN connection created by another application.
- if(blocking_intent != null)
- startActivityForResult(blocking_intent, VPN_USER_PERMISSION);
- else {
- onActivityResult(VPN_USER_PERMISSION, RESULT_OK, null);
- }
+ Intent blocking_intent = VpnService.prepare(getApplicationContext()); // stops the VPN connection created by another application.
+ if (blocking_intent != null)
+ startActivityForResult(blocking_intent, VPN_USER_PERMISSION);
+ else {
+ onActivityResult(VPN_USER_PERMISSION, RESULT_OK, null);
+ }
}
- protected void onActivityResult(int requestCode, int resultCode, Intent data){
- if(requestCode == VPN_USER_PERMISSION) {
- if(resultCode == RESULT_OK) {
- Intent void_vpn_service = new Intent(getApplicationContext(), VoidVpnService.class);
- void_vpn_service.setAction(Constants.START_BLOCKING_VPN_PROFILE);
- startService(void_vpn_service);
- }
- }
- finish();
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == VPN_USER_PERMISSION) {
+ if (resultCode == RESULT_OK) {
+ Intent void_vpn_service = new Intent(getApplicationContext(), VoidVpnService.class);
+ void_vpn_service.setAction(Constants.START_BLOCKING_VPN_PROFILE);
+ startService(void_vpn_service);
+ }
+ }
+ finish();
}
}
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 0c773208..dac92fe2 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java
@@ -1,53 +1,61 @@
package se.leap.bitmaskclient.eip;
-import android.content.Intent;
-import android.net.VpnService;
-import android.os.ParcelFileDescriptor;
+import android.content.*;
+import android.net.*;
+import android.os.*;
-import java.io.IOException;
+import java.io.*;
-public class VoidVpnService extends VpnService {
+public class VoidVpnService extends VpnService {
static final String TAG = VoidVpnService.class.getSimpleName();
static ParcelFileDescriptor fd;
+ static Thread thread;
+
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- String action = intent != null ? intent.getAction() : "";
- if (action == Constants.START_BLOCKING_VPN_PROFILE) {
- new Thread(new Runnable() {
- public void run() {
- Builder builder = new Builder();
- builder.setSession("Blocking until running");
- builder.addAddress("10.42.0.8",16);
- builder.addRoute("0.0.0.0", 1);
- builder.addRoute("192.168.1.0", 24);
- builder.addDnsServer("10.42.0.1");
- try {
- fd = builder.establish();
- } catch (Exception e) {
- e.printStackTrace();
- }
- android.util.Log.d(TAG, "VoidVpnService set up");
- }
- }).run();
- }
- return 0;
+ String action = intent != null ? intent.getAction() : "";
+ if (action == Constants.START_BLOCKING_VPN_PROFILE) {
+ thread = new Thread(new Runnable() {
+ public void run() {
+ Builder builder = new Builder();
+ builder.setSession("Blocking until running");
+ builder.addAddress("10.42.0.8", 16);
+ builder.addRoute("0.0.0.0", 1);
+ builder.addRoute("192.168.1.0", 24);
+ builder.addDnsServer("10.42.0.1");
+ try {
+ fd = builder.establish();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ thread.run();
+ }
+ return 0;
}
@Override
public void onRevoke() {
super.onRevoke();
+ closeFd();
+ }
+
+ public static void stop() {
+ if (thread != null)
+ thread.interrupt();
+ closeFd();
}
- public static boolean stop() {
+ private static void closeFd() {
try {
- fd.close();
- return true;
- } catch (IOException | NullPointerException e) {
- android.util.Log.d(TAG, "VoidVpnService didn't stop");
+ if (fd != null)
+ fd.close();
+ } catch (IOException e) {
e.printStackTrace();
- return false;
}
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java
index 0bbe9db4..8fce6a37 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java
@@ -1,6 +1,6 @@
/**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -16,14 +16,10 @@
*/
package se.leap.bitmaskclient.eip;
-import android.util.Log;
-
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.X509Certificate;
-import java.util.Calendar;
+import java.security.cert.*;
+import java.util.*;
-import se.leap.bitmaskclient.ConfigHelper;
+import se.leap.bitmaskclient.*;
public class VpnCertificateValidator {
public final static String TAG = VpnCertificateValidator.class.getSimpleName();
@@ -35,32 +31,30 @@ public class VpnCertificateValidator {
}
public boolean isValid() {
- if(!certificate.isEmpty()) {
- X509Certificate certificate_x509 = ConfigHelper.parseX509CertificateFromString(certificate);
- return isValid(certificate_x509);
- } else return true;
+ if (!certificate.isEmpty()) {
+ X509Certificate certificate_x509 = ConfigHelper.parseX509CertificateFromString(certificate);
+ return isValid(certificate_x509);
+ } else return true;
}
-
+
private boolean isValid(X509Certificate certificate) {
- Calendar offset_date = calculateOffsetCertificateValidity(certificate);
- try {
- Log.d(TAG, "offset_date = " + offset_date.getTime().toString());
- certificate.checkValidity(offset_date.getTime());
- return true;
- } catch(CertificateExpiredException e) {
- return false;
- } catch(CertificateNotYetValidException e) {
- return false;
- }
+ Calendar offset_date = calculateOffsetCertificateValidity(certificate);
+ try {
+ certificate.checkValidity(offset_date.getTime());
+ return true;
+ } catch (CertificateExpiredException e) {
+ return false;
+ } catch (CertificateNotYetValidException e) {
+ return false;
+ }
}
private Calendar calculateOffsetCertificateValidity(X509Certificate certificate) {
- Log.d(TAG, "certificate not after = " + certificate.getNotAfter());
- long preventive_time = Math.abs(certificate.getNotBefore().getTime() - certificate.getNotAfter().getTime())/2;
- long current_date_millis = Calendar.getInstance().getTimeInMillis();
-
- Calendar limit_date = Calendar.getInstance();
- limit_date.setTimeInMillis(current_date_millis + preventive_time);
- return limit_date;
+ long preventive_time = Math.abs(certificate.getNotBefore().getTime() - certificate.getNotAfter().getTime()) / 2;
+ long current_date_millis = Calendar.getInstance().getTimeInMillis();
+
+ Calendar limit_date = Calendar.getInstance();
+ limit_date.setTimeInMillis(current_date_millis + preventive_time);
+ return limit_date;
}
}
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 6f260f55..0b9c5832 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
@@ -1,6 +1,6 @@
/**
* Copyright (c) 2013 LEAP Encryption Access Project and contributers
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -16,16 +16,11 @@
*/
package se.leap.bitmaskclient.eip;
-import android.content.SharedPreferences;
-import android.util.Log;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
+import org.json.*;
-import java.util.Iterator;
+import java.util.*;
-import se.leap.bitmaskclient.Provider;
+import se.leap.bitmaskclient.*;
public class VpnConfigGenerator {
@@ -37,79 +32,79 @@ public class VpnConfigGenerator {
private final String new_line = System.getProperty("line.separator"); // Platform new line
public VpnConfigGenerator(JSONObject general_configuration, JSONObject secrets, JSONObject gateway) {
- this.general_configuration = general_configuration;
- this.gateway = gateway;
+ this.general_configuration = general_configuration;
+ this.gateway = gateway;
this.secrets = secrets;
}
-
+
public String generate() {
- return
- generalConfiguration()
- + new_line
- + gatewayConfiguration()
- + new_line
- + secretsConfiguration()
- + new_line
- + androidCustomizations();
+ return
+ generalConfiguration()
+ + new_line
+ + gatewayConfiguration()
+ + new_line
+ + secretsConfiguration()
+ + new_line
+ + androidCustomizations();
}
private String generalConfiguration() {
- String common_options = "";
- try {
- Iterator keys = general_configuration.keys();
- while ( keys.hasNext() ){
- String key = keys.next().toString();
-
- common_options += key + " ";
- for ( String word : general_configuration.getString(key).split(" ") )
- common_options += word + " ";
- common_options += new_line;
-
- }
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- common_options += "client";
-
- return common_options;
+ String common_options = "";
+ try {
+ Iterator keys = general_configuration.keys();
+ while (keys.hasNext()) {
+ String key = keys.next().toString();
+
+ common_options += key + " ";
+ for (String word : general_configuration.getString(key).split(" "))
+ common_options += word + " ";
+ common_options += new_line;
+
+ }
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ common_options += "client";
+
+ return common_options;
}
-
+
private String gatewayConfiguration() {
- String remotes = "";
-
- String ip_address_keyword = "ip_address";
- String remote_keyword = "remote";
- String ports_keyword = "ports";
- String protocol_keyword = "protocols";
- String capabilities_keyword = "capabilities";
- String udp = "udp";
-
- try {
- String ip_address = gateway.getString(ip_address_keyword);
- JSONObject capabilities = gateway.getJSONObject(capabilities_keyword);
- JSONArray ports = capabilities.getJSONArray(ports_keyword);
- for (int i=0; i<ports.length(); i++) {
- String port_specific_remotes = "";
- int port = ports.getInt(i);
- JSONArray protocols = capabilities.getJSONArray(protocol_keyword);
- for ( int j=0; j<protocols.length(); j++ ) {
- String protocol = protocols.optString(j);
- String new_remote = remote_keyword + " " + ip_address + " " + port + " " + protocol + new_line;
-
- port_specific_remotes = protocol.equalsIgnoreCase(udp) ?
- port_specific_remotes.replaceFirst(remote_keyword, new_remote + new_line + remote_keyword) :
- new_remote;
- }
- remotes += port_specific_remotes;
- }
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- return remotes;
+ String remotes = "";
+
+ String ip_address_keyword = "ip_address";
+ String remote_keyword = "remote";
+ String ports_keyword = "ports";
+ String protocol_keyword = "protocols";
+ String capabilities_keyword = "capabilities";
+ String udp = "udp";
+
+ try {
+ String ip_address = gateway.getString(ip_address_keyword);
+ JSONObject capabilities = gateway.getJSONObject(capabilities_keyword);
+ JSONArray ports = capabilities.getJSONArray(ports_keyword);
+ for (int i = 0; i < ports.length(); i++) {
+ String port_specific_remotes = "";
+ int port = ports.getInt(i);
+ JSONArray protocols = capabilities.getJSONArray(protocol_keyword);
+ for (int j = 0; j < protocols.length(); j++) {
+ String protocol = protocols.optString(j);
+ String new_remote = remote_keyword + " " + ip_address + " " + port + " " + protocol + new_line;
+
+ port_specific_remotes = protocol.equalsIgnoreCase(udp) ?
+ port_specific_remotes.replaceFirst(remote_keyword, new_remote + new_line + remote_keyword) :
+ new_remote;
+ }
+ remotes += port_specific_remotes;
+ }
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ return remotes;
}
private String secretsConfiguration() {
@@ -136,18 +131,18 @@ public class VpnConfigGenerator {
+ "</cert>";
return ca + new_line + key + new_line + openvpn_cert;
- } catch(JSONException e) {
+ } catch (JSONException e) {
e.printStackTrace();
return "";
}
}
private String androidCustomizations() {
- return
- "remote-cert-tls server"
- + new_line
- + "persist-tun"
- + new_line
- + "auth-retry nointeract";
+ return
+ "remote-cert-tls server"
+ + new_line
+ + "persist-tun"
+ + new_line
+ + "auth-retry nointeract";
}
}
diff --git a/app/src/main/res/layout-xlarge/dashboard.xml b/app/src/main/res/layout-xlarge/dashboard.xml
index bd644e1e..268bd3f9 100644
--- a/app/src/main/res/layout-xlarge/dashboard.xml
+++ b/app/src/main/res/layout-xlarge/dashboard.xml
@@ -52,6 +52,28 @@
</LinearLayout>
</LinearLayout>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="32dp">
+ <ProgressBar
+ android:id="@+id/user_session_status_progress"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:indeterminate="true"
+ android:visibility="gone"/>
+ <TextView
+ android:id="@+id/user_session_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="18sp"
+ android:layout_marginLeft="10dp"
+ android:ellipsize="marquee"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ />
+ </LinearLayout>
+
<View
android:layout_width="wrap_content"
android:layout_height="1dp"
diff --git a/app/src/main/res/layout/dashboard.xml b/app/src/main/res/layout/dashboard.xml
index 67a1122f..f4269fe2 100644
--- a/app/src/main/res/layout/dashboard.xml
+++ b/app/src/main/res/layout/dashboard.xml
@@ -16,7 +16,6 @@
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:ellipsize="marquee"
- android:fadingEdge="horizontal"
android:singleLine="true"
android:text="@string/provider_label"
android:textAppearance="?android:attr/textAppearanceMedium" />
@@ -28,19 +27,33 @@
android:textSize="28sp"
android:layout_marginLeft="10dp"
android:ellipsize="marquee"
- android:fadingEdge="horizontal"
android:singleLine="true"
android:text="@string/provider_label_none"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
- <View
- android:layout_width="wrap_content"
- android:layout_height="2dp"
- android:layout_marginBottom="15dp"
- android:background="@android:drawable/divider_horizontal_bright" />
-
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <ProgressBar
+ android:id="@+id/user_session_status_progress"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:indeterminate="true"
+ android:visibility="gone"/>
+ <TextView
+ android:id="@+id/user_session_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="18sp"
+ android:layout_marginLeft="10dp"
+ android:ellipsize="marquee"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ />
+ </LinearLayout>
+
<LinearLayout
android:id="@+id/servicesCollection"
android:layout_width="match_parent"
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 1608f487..d1e33928 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -16,8 +16,6 @@
<string name="provider_label">Provider:</string>
<string name="provider_label_none">No provider configured</string>
<string name="status_unknown">Status unknown.</string>
- <string name="anonymous_secured_status">Connection secure using an anonymous certificate.</string>
- <string name="authed_secured_status">Connection secure using your own certificate.</string>
<string name="eip_service_label">Encrypted Internet</string>
<string name="configuration_wizard_title">Select a service provider</string>
<string name="new_provider_button">Add new Provider</string>
@@ -60,17 +58,19 @@
<string name="signingup_message">Signing up</string>
<string name="logout_message">Logging out from this session.</string>
<string name="logged_out_message">Logged out.</string>
- <string name="log_out_failed_message">Didn\'t log out.</string>
+ <string name="log_out_failed_message">Didn\'t log out. Try later, it may be a problem in the network or in the provider. If the problem persists, then wipe Bitmask data from the Android settings</string>
+ <string name="login.riseup.warning">"Riseup users: You need to create a separate account to use the VPN service"</string>
<string name="succesful_authentication_message">Authentication succeeded.</string>
<string name="authentication_failed_message">Authentication failed.</string>
<string name="registration_failed_message">Registration failed.</string>
- <string name="successful_authed_cert_downloaded_message">Your own cert has been correctly downloaded.</string>
- <string name="authed_cert_download_failed_message">Your own cert has incorrectly been downloaded.</string>
<string name="eip_status_start_pending">Initiating connection</string>
<string name="eip_cancel_connect_title">Cancel connection?</string>
<string name="eip_cancel_connect_text">There is a connection attempt in progress. Do you wish to cancel it?</string>
+ <string name="eip.warning.browser_inconsistency">In order to avoid leaking your personal information, please close your browser and start a private window after disconnecting the Encrypted VPN Internet Access. Thanks.</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="eip_state_not_connected">"Not running! Connection not secure!"</string>
<string name="eip_state_connected">Connection Secure.</string>
+ <string name="provider_problem">It seems there is a problem with the provider.</string>
+ <string name="try_another_provider">Please try another provider, or contact yours.</string>
</resources>