summaryrefslogtreecommitdiff
path: root/app/src/main/java/se/leap/bitmaskclient
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/se/leap/bitmaskclient')
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Dashboard.java68
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/EIP.java560
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java348
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/EipStatusReceiver.java17
4 files changed, 519 insertions, 474 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
index cb451b86..fe546a21 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
@@ -33,6 +33,7 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.os.Handler;
import android.os.ResultReceiver;
@@ -63,12 +64,14 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
public static final String PARAMETERS = "dashboard parameters";
public static final String START_ON_BOOT = "dashboard start on boot";
final public static String ON_BOOT = "dashboard on boot";
+ public static final String APP_VERSION = "bitmask version";
-
+
+ private EipServiceFragment eipFragment;
private ProgressBar mProgressBar;
private TextView eipStatus;
private static Context app;
- private static SharedPreferences preferences;
+ protected static SharedPreferences preferences;
private static Provider provider;
private TextView providerNameTV;
@@ -81,17 +84,15 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- app = this;
+ app = this;
PRNGFixes.apply();
- // mProgressBar = (ProgressBar) findViewById(R.id.progressbar_dashboard);
- // mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
- // eipStatus = (TextView) findViewById(R.id.eipStatus);
mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
-
+ handleVersion();
+
authed_eip = preferences.getBoolean(EIP.AUTHED_EIP, false);
if (preferences.getString(Provider.KEY, "").isEmpty())
startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP);
@@ -99,8 +100,21 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
buildDashboard(getIntent().getBooleanExtra(ON_BOOT, false));
}
+ private void handleVersion() {
+ try {
+ int versionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode;
+ int lastDetectedVersion = preferences.getInt(APP_VERSION, 0);
+ if(lastDetectedVersion == 0) // New install
+ getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putInt(APP_VERSION, versionCode);
+ else if(lastDetectedVersion < versionCode) {
+ }
+ } catch (NameNotFoundException e) {
+ }
+ }
+
@Override
protected void onDestroy() {
+
super.onDestroy();
}
@@ -122,7 +136,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
invalidateOptionsMenu();
if(data != null && data.hasExtra(LogInDialog.VERB)) {
View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0);
- logInDialog(view, Bundle.EMPTY);
+ logInDialog(Bundle.EMPTY);
}
} else if(resultCode == RESULT_CANCELED && (data == null || data.hasExtra(ACTION_QUIT))) {
finish();
@@ -176,9 +190,9 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
FragmentManager fragMan = getFragmentManager();
if ( provider.hasEIP()){
- EipServiceFragment eipFragment = new EipServiceFragment();
- if (hide_and_turn_on_eip) {
- getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().remove(Dashboard.START_ON_BOOT).commit();
+ eipFragment = new EipServiceFragment();
+ if (hide_and_turn_on_eip) {
+ getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().remove(Dashboard.START_ON_BOOT).commit();
Bundle arguments = new Bundle();
arguments.putBoolean(EipServiceFragment.START_ON_BOOT, true);
eipFragment.setArguments(arguments);
@@ -197,8 +211,10 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
try {
provider_json = new JSONObject(getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE).getString(Provider.KEY, ""));
JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE);
-
- if(service_description.getBoolean(Provider.ALLOW_REGISTRATION)) {
+ boolean authed_eip = preferences.getBoolean(EIP.AUTHED_EIP, false);
+ boolean allow_registered_eip = service_description.getBoolean(Provider.ALLOW_REGISTRATION);
+ preferences.edit().putBoolean(EIP.ALLOWED_REGISTERED, allow_registered_eip);
+ if(allow_registered_eip) {
if(authed_eip) {
menu.findItem(R.id.login_button).setVisible(false);
menu.findItem(R.id.logout_button).setVisible(true);
@@ -238,15 +254,15 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
if (Provider.getInstance().hasEIP()){
if (getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getBoolean(EIP.AUTHED_EIP, false)){
logOut();
- }
+ }
eipStop();
}
- getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().remove(Provider.KEY).commit();
+ getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().clear().commit();
startActivityForResult(new Intent(this,ConfigurationWizard.class), SWITCH_PROVIDER);
return true;
case R.id.login_button:
View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0);
- logInDialog(view, Bundle.EMPTY);
+ logInDialog(Bundle.EMPTY);
return true;
case R.id.logout_button:
logOut();
@@ -305,6 +321,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
if(eipStatus == null) eipStatus = (TextView) findViewById(R.id.eipStatus);
if(eipStatus != null) eipStatus.setText("");
}
+ cancelAuthedEipOn();
}
/**
@@ -343,9 +360,9 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
/**
* Shows the log in dialog.
- * @param view from which the dialog is created.
*/
- public void logInDialog(View view, Bundle resultData) {
+ public void logInDialog(Bundle resultData) {
+ Log.d("Dashboard", "Log In Dialog");
FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
Fragment previous_log_in_dialog = getFragmentManager().findFragmentByTag(LogInDialog.TAG);
if (previous_log_in_dialog != null) {
@@ -455,7 +472,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
//Cookie session_id = new BasicClientCookie(session_id_cookie_key, session_id_string);
downloadAuthedUserCertificate(/*session_id*/);
} else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_FAILED) {
- logInDialog(getCurrentFocus(), resultData);
+ logInDialog(resultData);
} else if(resultCode == ProviderAPI.LOGOUT_SUCCESSFUL) {
authed_eip = false;
getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit();
@@ -468,13 +485,16 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
} else if(resultCode == ProviderAPI.LOGOUT_FAILED) {
setResult(RESULT_CANCELED);
changeStatusMessage(resultCode);
- mProgressBar.setVisibility(ProgressBar.GONE);
+ mProgressBar.setVisibility(ProgressBar.GONE);
} else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) {
setResult(RESULT_OK);
changeStatusMessage(resultCode);
- mProgressBar.setVisibility(ProgressBar.GONE);
+ if(mProgressBar != null)
+ mProgressBar.setVisibility(ProgressBar.GONE);
if(EipServiceFragment.isEipSwitchChecked())
eipStart();
+ else
+ eipStatus.setText(R.string.eip_state_not_connected);
} else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) {
setResult(RESULT_CANCELED);
changeStatusMessage(resultCode);
@@ -570,4 +590,10 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
startService(eip_intent);
}
+
+ protected void setProgressBarVisibility(int visibility) {
+ if(mProgressBar == null)
+ mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
+ mProgressBar.setVisibility(visibility);
+ }
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/EIP.java b/app/src/main/java/se/leap/bitmaskclient/EIP.java
index 21a573fe..41299318 100644
--- a/app/src/main/java/se/leap/bitmaskclient/EIP.java
+++ b/app/src/main/java/se/leap/bitmaskclient/EIP.java
@@ -16,35 +16,9 @@
*/
package se.leap.bitmaskclient;
-import java.io.StringReader;
-import java.io.IOException;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.Vector;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.Dashboard;
-import se.leap.bitmaskclient.Provider;
-import de.blinkt.openvpn.activities.DisconnectVPN;
-import de.blinkt.openvpn.core.ConfigParser;
-import de.blinkt.openvpn.core.ConfigParser.ConfigParseError;
-import de.blinkt.openvpn.LaunchVPN;
-import de.blinkt.openvpn.core.OpenVpnManagementThread;
-import de.blinkt.openvpn.core.OpenVpnService;
-import de.blinkt.openvpn.core.OpenVpnService.LocalBinder;
-import de.blinkt.openvpn.core.ProfileManager;
-import de.blinkt.openvpn.VpnProfile;
import android.app.Activity;
import android.app.IntentService;
@@ -58,6 +32,41 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.ResultReceiver;
import android.util.Log;
+import de.blinkt.openvpn.LaunchVPN;
+import de.blinkt.openvpn.VpnProfile;
+import de.blinkt.openvpn.activities.DisconnectVPN;
+import de.blinkt.openvpn.core.ConfigParser.ConfigParseError;
+import de.blinkt.openvpn.core.ConfigParser;
+import de.blinkt.openvpn.core.OpenVpnManagementThread;
+import de.blinkt.openvpn.core.OpenVpnService.LocalBinder;
+import de.blinkt.openvpn.core.OpenVpnService;
+import de.blinkt.openvpn.core.ProfileManager;
+import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus;
+import java.io.IOException;
+import java.io.StringReader;
+import java.lang.StringBuffer;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.Vector;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import se.leap.bitmaskclient.Dashboard;
+import se.leap.bitmaskclient.Provider;
+import se.leap.bitmaskclient.R;
/**
* EIP is the abstract base class for interacting with and managing the Encrypted
@@ -72,13 +81,16 @@ import android.util.Log;
public final class EIP extends IntentService {
public final static String AUTHED_EIP = "authed eip";
+ public final static String ACTION_CHECK_CERT_VALIDITY = "se.leap.bitmaskclient.CHECK_CERT_VALIDITY";
public final static String ACTION_START_EIP = "se.leap.bitmaskclient.START_EIP";
public final static String ACTION_STOP_EIP = "se.leap.bitmaskclient.STOP_EIP";
public final static String ACTION_UPDATE_EIP_SERVICE = "se.leap.bitmaskclient.UPDATE_EIP_SERVICE";
public final static String ACTION_IS_EIP_RUNNING = "se.leap.bitmaskclient.IS_RUNNING";
public final static String EIP_NOTIFICATION = "EIP_NOTIFICATION";
public final static String STATUS = "eip status";
+ public final static String DATE_FROM_CERTIFICATE = "date from certificate";
public final static String ALLOWED_ANON = "allow_anonymous";
+ public final static String ALLOWED_REGISTERED = "allow_registration";
public final static String CERTIFICATE = "cert";
public final static String PRIVATE_KEY = "private_key";
public final static String KEY = "eip";
@@ -87,8 +99,9 @@ public final class EIP extends IntentService {
public final static String RECEIVER_TAG = "receiverTag";
public final static String REQUEST_TAG = "requestTag";
public final static String TAG = "se.leap.bitmaskclient.EIP";
-
-
+
+ public final static SimpleDateFormat certificate_date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US);
+
private static Context context;
private static ResultReceiver mReceiver;
private static OpenVpnService mVpnService;
@@ -100,6 +113,10 @@ public final class EIP extends IntentService {
private static JSONObject eipDefinition = null;
private static OVPNGateway activeGateway = null;
+
+ protected static ConnectionStatus lastConnectionStatusLevel;
+ protected static boolean mIsDisconnecting = false;
+ protected static boolean mIsStarting = false;
public EIP(){
super("LEAPEIP");
@@ -112,13 +129,11 @@ public final class EIP extends IntentService {
context = getApplicationContext();
updateEIPService();
-
- this.retreiveVpnService();
}
@Override
public void onDestroy() {
- unbindService(mVpnServiceConn);
+
mBound = false;
super.onDestroy();
@@ -138,108 +153,30 @@ public final class EIP extends IntentService {
this.startEIP();
else if ( action == ACTION_STOP_EIP )
this.stopEIP();
+ else if ( action == ACTION_CHECK_CERT_VALIDITY )
+ this.checkCertValidity();
}
/**
- * Sends an Intent to bind OpenVpnService.
- * Used when OpenVpnService isn't bound but might be running.
- */
- private boolean retreiveVpnService() {
- Intent bindIntent = new Intent(this,OpenVpnService.class);
- bindIntent.setAction(OpenVpnService.START_SERVICE);
- return bindService(bindIntent, mVpnServiceConn, BIND_AUTO_CREATE);
- }
-
- private ServiceConnection mVpnServiceConn = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- LocalBinder binder = (LocalBinder) service;
- mVpnService = binder.getService();
- mBound = true;
-
- if (mReceiver != null && mPending != null) {
-
- boolean running = isConnected();
-
- int resultCode = Activity.RESULT_CANCELED;
-
- if (mPending.equals(ACTION_IS_EIP_RUNNING)){
- resultCode = (running) ? Activity.RESULT_OK : Activity.RESULT_CANCELED;
-
- }
- else if (mPending.equals(ACTION_START_EIP)){
- resultCode = (running) ? Activity.RESULT_OK : Activity.RESULT_CANCELED;
- }
- else if (mPending.equals(ACTION_STOP_EIP)){
- resultCode = (running) ? Activity.RESULT_CANCELED
- : Activity.RESULT_OK;
- }
- Bundle resultData = new Bundle();
- resultData.putString(REQUEST_TAG, ACTION_IS_EIP_RUNNING);
- mReceiver.send(resultCode, resultData);
-
- mPending = null;
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- mBound = false;
-
- if (mReceiver != null){
- Bundle resultData = new Bundle();
- resultData.putString(REQUEST_TAG, EIP_NOTIFICATION);
- mReceiver.send(Activity.RESULT_CANCELED, resultData);
- }
- }
-
-
- };
-
- /**
- * Attempts to determine if OpenVpnService has an established VPN connection
- * through the bound ServiceConnection. If there is no bound service, this
- * method will attempt to bind a running OpenVpnService and send
- * <code>Activity.RESULT_CANCELED</code> to the ResultReceiver that made the
- * request.
- * Note: If the request to bind OpenVpnService is successful, the ResultReceiver
- * will be notified in {@link onServiceConnected()}
+ * 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() {
- Bundle resultData = new Bundle();
- resultData.putString(REQUEST_TAG, ACTION_IS_EIP_RUNNING);
- int resultCode = Activity.RESULT_CANCELED;
- boolean is_connected = isConnected();
- if (mBound) {
- resultCode = (is_connected) ? Activity.RESULT_OK : Activity.RESULT_CANCELED;
+ Bundle resultData = new Bundle();
+ resultData.putString(REQUEST_TAG, ACTION_IS_EIP_RUNNING);
+ int resultCode = Activity.RESULT_CANCELED;
+ boolean is_connected = isConnected();
+
+ resultCode = (is_connected) ? Activity.RESULT_OK : Activity.RESULT_CANCELED;
- if (mReceiver != null){
- mReceiver.send(resultCode, resultData);
- }
- } else {
- mPending = ACTION_IS_EIP_RUNNING;
- boolean retrieved_vpn_service = retreiveVpnService();
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- boolean running = is_connected;
-
- if (retrieved_vpn_service && running && mReceiver != null){
- mReceiver.send(Activity.RESULT_OK, resultData);
- }
- else{
- mReceiver.send(Activity.RESULT_CANCELED, resultData);
- }
- }
- }
-
- private boolean isConnected() {
- return getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(STATUS, "").equalsIgnoreCase("LEVEL_CONNECTED");
- }
+ if (mReceiver != null){
+ mReceiver.send(resultCode, resultData);
+ }
+
+ Log.d(TAG, "isRunning() = " + is_connected);
+ }
/**
* Initiates an EIP connection by selecting a gateway and preparing and sending an
@@ -249,31 +186,36 @@ public final class EIP extends IntentService {
activeGateway = selectGateway();
if(activeGateway != null && activeGateway.mVpnProfile != null) {
- Intent intent = new Intent(this,LaunchVPN.class);
- intent.setAction(Intent.ACTION_MAIN);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra(LaunchVPN.EXTRA_KEY, activeGateway.mVpnProfile.getUUID().toString() );
- intent.putExtra(LaunchVPN.EXTRA_NAME, activeGateway.mVpnProfile.getName() );
- intent.putExtra(LaunchVPN.EXTRA_HIDELOG, true);
- intent.putExtra(RECEIVER_TAG, mReceiver);
- startActivity(intent);
- mPending = ACTION_START_EIP;
+ launchActiveGateway();
}
}
+
+ 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_KEY, activeGateway.mVpnProfile.getUUID().toString() );
+ intent.putExtra(LaunchVPN.EXTRA_NAME, activeGateway.mVpnProfile.getName() );
+ intent.putExtra(LaunchVPN.EXTRA_HIDELOG, true);
+ intent.putExtra(RECEIVER_TAG, mReceiver);
+ startActivity(intent);
+ mPending = ACTION_START_EIP;
+ }
/**
* Disconnects the EIP connection gracefully through the bound service or forcefully
* if there is no bound service. Sends a message to the requesting ResultReceiver.
*/
private void stopEIP() {
- if (mBound)
- mVpnService.onRevoke();
- else if(getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(STATUS, "").startsWith("LEVEL_CONNECT")){
+ if(isConnected()) {
Intent disconnect_vpn = new Intent(this, DisconnectVPN.class);
disconnect_vpn.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(disconnect_vpn);
+ mIsDisconnecting = true;
+ lastConnectionStatusLevel = ConnectionStatus.UNKNOWN_LEVEL; // Wait for the decision of the user
+ Log.d(TAG, "mIsDisconnecting = true");
}
-
+
if (mReceiver != null){
Bundle resultData = new Bundle();
resultData.putString(REQUEST_TAG, ACTION_STOP_EIP);
@@ -281,6 +223,10 @@ public final class EIP extends IntentService {
}
}
+ protected static boolean isConnected() {
+ return lastConnectionStatusLevel != null && lastConnectionStatusLevel.equals(ConnectionStatus.LEVEL_CONNECTED) && !mIsDisconnecting;
+ }
+
/**
* Loads eip-service.json from SharedPreferences and calls {@link updateGateways()}
* to parse gateway definitions.
@@ -295,62 +241,27 @@ public final class EIP extends IntentService {
e.printStackTrace();
}
if(parsedEipSerial == 0) {
- // Delete all vpn profiles
- ProfileManager vpl = ProfileManager.getInstance(context);
- VpnProfile[] profiles = (VpnProfile[]) vpl.getProfiles().toArray(new VpnProfile[vpl.getProfiles().size()]);
- for (int current_profile = 0; current_profile < profiles.length; current_profile++){
- vpl.removeProfile(context, profiles[current_profile]);
- }
+ deleteAllVpnProfiles();
}
- if (eipDefinition.optInt("serial") > parsedEipSerial)
+ if (eipDefinition != null && eipDefinition.optInt("serial") > parsedEipSerial)
updateGateways();
}
-
+
+ private void deleteAllVpnProfiles() {
+ ProfileManager vpl = ProfileManager.getInstance(context);
+ VpnProfile[] profiles = (VpnProfile[]) vpl.getProfiles().toArray(new VpnProfile[vpl.getProfiles().size()]);
+ for (int current_profile = 0; current_profile < profiles.length; current_profile++){
+ vpl.removeProfile(context, profiles[current_profile]);
+ }
+ }
/**
* Choose a gateway to connect to based on timezone from system locale data
*
* @return The gateway to connect to
*/
private OVPNGateway selectGateway() {
- // TODO Remove String arg constructor in favor of findGatewayByName(String)
+ String closestLocation = closestGateway();
- Calendar cal = Calendar.getInstance();
- int localOffset = cal.get(Calendar.ZONE_OFFSET) / 3600000;
- TreeMap<Integer, Set<String>> offsets = new TreeMap<Integer, Set<String>>();
- JSONObject locationsObjects = null;
- Iterator<String> locations = null;
- try {
- locationsObjects = eipDefinition.getJSONObject("locations");
- locations = locationsObjects.keys();
- } catch (JSONException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
-
- while (locations.hasNext()) {
- String locationName = locations.next();
- JSONObject location = null;
- try {
- location = locationsObjects.getJSONObject(locationName);
-
- // Distance along the numberline of Prime Meridian centric, assumes UTC-11 through UTC+12
- int dist = Math.abs(localOffset - location.optInt("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.
-
- Set<String> set = offsets.get(dist);
- if (set == null) set = new HashSet<String>();
- set.add(locationName);
- offsets.put(dist, set);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
-
- String closestLocation = offsets.isEmpty() ? "" : offsets.firstEntry().getValue().iterator().next();
JSONArray gateways = null;
String chosenHost = null;
try {
@@ -358,7 +269,7 @@ public final class EIP extends IntentService {
for (int i = 0; i < gateways.length(); i++) {
JSONObject gw = gateways.getJSONObject(i);
if ( gw.getString("location").equalsIgnoreCase(closestLocation) || closestLocation.isEmpty()){
- chosenHost = gw.getString("host");
+ chosenHost = eipDefinition.getJSONObject("locations").getJSONObject(gw.getString("location")).getString("name");
break;
}
}
@@ -369,6 +280,44 @@ public final class EIP extends IntentService {
return new OVPNGateway(chosenHost);
}
+
+ private String closestGateway() {
+ Calendar cal = Calendar.getInstance();
+ int localOffset = cal.get(Calendar.ZONE_OFFSET) / 3600000;
+ TreeMap<Integer, Set<String>> offsets = new TreeMap<Integer, Set<String>>();
+ JSONObject locationsObjects = null;
+ Iterator<String> locations = null;
+ try {
+ locationsObjects = eipDefinition.getJSONObject("locations");
+ locations = locationsObjects.keys();
+ } catch (JSONException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+
+ while (locations.hasNext()) {
+ String locationName = locations.next();
+ JSONObject location = null;
+ try {
+ location = locationsObjects.getJSONObject(locationName);
+
+ // Distance along the numberline of Prime Meridian centric, assumes UTC-11 through UTC+12
+ int dist = Math.abs(localOffset - location.optInt("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.
+
+ Set<String> set = offsets.get(dist);
+ if (set == null) set = new HashSet<String>();
+ set.add(locationName);
+ offsets.put(dist, set);
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ return offsets.isEmpty() ? "" : offsets.firstEntry().getValue().iterator().next();
+ }
/**
* Walk the list of gateways defined in eip-service.json and parse them into
@@ -379,35 +328,55 @@ public final class EIP extends IntentService {
JSONArray gatewaysDefined = null;
try {
- gatewaysDefined = eipDefinition.getJSONArray("gateways");
- } catch (JSONException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
-
- for ( int i=0 ; i < gatewaysDefined.length(); i++ ){
-
- JSONObject gw = null;
-
- try {
- gw = gatewaysDefined.getJSONObject(i);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
+ gatewaysDefined = eipDefinition.getJSONArray("gateways");
+ for ( int i=0 ; i < gatewaysDefined.length(); i++ ){
+ JSONObject gw = null;
+ gw = gatewaysDefined.getJSONObject(i);
- try {
- if ( gw.getJSONObject("capabilities").getJSONArray("transport").toString().contains("openvpn") ){
- new OVPNGateway(gw);
- }
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ if ( gw.getJSONObject("capabilities").getJSONArray("transport").toString().contains("openvpn") )
+ new OVPNGateway(gw);
}
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
}
+
getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putInt(PARSED_SERIAL, eipDefinition.optInt(Provider.API_RETURN_SERIAL)).commit();
}
+ private void checkCertValidity() {
+ String certificate_string = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(CERTIFICATE, "");
+ if(!certificate_string.isEmpty()) {
+ String date_from_certificate_string = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(DATE_FROM_CERTIFICATE, certificate_date_format.format(Calendar.getInstance().getTime()).toString());
+ X509Certificate certificate_x509 = ConfigHelper.parseX509CertificateFromString(certificate_string);
+
+ Calendar offset_date = Calendar.getInstance();
+ try {
+ Date date_from_certificate = certificate_date_format.parse(date_from_certificate_string);
+ long difference = Math.abs(date_from_certificate.getTime() - certificate_x509.getNotAfter().getTime())/2;
+ long current_date_millis = offset_date.getTimeInMillis();
+ offset_date.setTimeInMillis(current_date_millis + difference);
+ Log.d(TAG, "certificate not after = " + certificate_x509.getNotAfter());
+ } catch(ParseException e) {
+ e.printStackTrace();
+ }
+
+ Bundle result_data = new Bundle();
+ result_data.putString(REQUEST_TAG, ACTION_CHECK_CERT_VALIDITY);
+ try {
+ Log.d(TAG, "offset_date = " + offset_date.getTime().toString());
+ certificate_x509.checkValidity(offset_date.getTime());
+ mReceiver.send(Activity.RESULT_OK, result_data);
+ Log.d(TAG, "Valid certificate");
+ } catch(CertificateExpiredException e) {
+ mReceiver.send(Activity.RESULT_CANCELED, result_data);
+ Log.d(TAG, "Updating certificate");
+ } catch(CertificateNotYetValidException e) {
+ mReceiver.send(Activity.RESULT_CANCELED, result_data);
+ }
+ }
+ }
+
/**
* OVPNGateway provides objects defining gateways and their options and metadata.
* Each instance contains a VpnProfile for OpenVPN specific data and member
@@ -439,7 +408,6 @@ public final class EIP extends IntentService {
private void loadVpnProfile() {
ProfileManager vpl = ProfileManager.getInstance(context);
-
try {
if ( mName == null )
mVpnProfile = vpl.getProfiles().iterator().next();
@@ -469,48 +437,44 @@ public final class EIP extends IntentService {
Collection<VpnProfile> profiles = vpl.getProfiles();
for (Iterator<VpnProfile> it = profiles.iterator(); it.hasNext(); ){
VpnProfile p = it.next();
- try {
- if ( p.mName.equalsIgnoreCase( gateway.getString("host") ) ){
- it.remove();
- vpl.removeProfile(context, p);
- }
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+
+ if ( p.mName.equalsIgnoreCase( mName ) ) {
+ it.remove();
+ vpl.removeProfile(context, p);
}
}
this.createVPNProfile();
- setUniqueProfileName(vpl);
vpl.addProfile(mVpnProfile);
vpl.saveProfile(context, mVpnProfile);
vpl.saveProfileList(context);
}
-
+
/**
- * Attempts to create a unique profile name from the hostname of the gateway
- *
- * @param profileManager
+ * Create and attach the VpnProfile to our gateway object
*/
- private void setUniqueProfileName(ProfileManager profileManager) {
- int i=0;
-
- String newname;
+ protected void createVPNProfile(){
try {
- newname = mGateway.getString("host");
- while(profileManager.getProfileByName(newname)!=null) {
- i++;
- if(i==1)
- newname = getString(R.string.converted_profile);
- else
- newname = getString(R.string.converted_profile_i,i);
- }
-
- mVpnProfile.mName=newname;
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- Log.v(TAG,"Couldn't read gateway name for profile creation!");
+ ConfigParser cp = new ConfigParser();
+ cp.parseConfig(new StringReader(configFromEipServiceDotJson()));
+ cp.parseConfig(new StringReader(caSecretFromSharedPreferences()));
+ cp.parseConfig(new StringReader(keySecretFromSharedPreferences()));
+ cp.parseConfig(new StringReader(certSecretFromSharedPreferences()));
+ cp.parseConfig(new StringReader("remote-cert-tls server"));
+ cp.parseConfig(new StringReader("persist-tun"));
+ VpnProfile vp = cp.convertProfile();
+ //vp.mAuthenticationType=VpnProfile.TYPE_STATICKEYS;
+ mVpnProfile = vp;
+ mVpnProfile.mName = mName = locationAsName();
+ Log.v(TAG,"Created VPNProfile");
+ } catch (ConfigParseError e) {
+ // FIXME We didn't get a VpnProfile! Error handling! and log level
+ Log.v(TAG,"Error creating VPNProfile");
+ e.printStackTrace();
+ } catch (IOException e) {
+ // FIXME We didn't get a VpnProfile! Error handling! and log level
+ Log.v(TAG,"Error creating VPNProfile");
e.printStackTrace();
}
}
@@ -520,29 +484,30 @@ public final class EIP extends IntentService {
*/
private String configFromEipServiceDotJson() {
String parsed_configuration = "";
-
- String common_options = "openvpn_configuration";
- String remote = "ip_address";
- String ports = "ports";
- String protos = "protocols";
- String capabilities = "capabilities";
+
String location_key = "location";
String locations = "locations";
-
- Vector<String> arg = new Vector<String>();
- Vector<Vector<String>> args = new Vector<Vector<String>>();
-
+
+ parsed_configuration += extractCommonOptionsFromEipServiceDotJson();
+ parsed_configuration += extractRemotesFromEipServiceDotJson();
+
+ return parsed_configuration;
+ }
+
+ private String extractCommonOptionsFromEipServiceDotJson() {
+ String common_options = "";
try {
- JSONObject openvpn_configuration = eipDefinition.getJSONObject(common_options);
+ String common_options_key = "openvpn_configuration";
+ JSONObject openvpn_configuration = eipDefinition.getJSONObject(common_options_key);
Iterator keys = openvpn_configuration.keys();
Vector<Vector<String>> value = new Vector<Vector<String>>();
while ( keys.hasNext() ){
String key = keys.next().toString();
- parsed_configuration += key + " ";
+ common_options += key + " ";
for ( String word : openvpn_configuration.getString(key).split(" ") )
- parsed_configuration += word + " ";
- parsed_configuration += System.getProperty("line.separator");
+ common_options += word + " ";
+ common_options += System.getProperty("line.separator");
}
} catch (JSONException e) {
@@ -550,48 +515,44 @@ public final class EIP extends IntentService {
e.printStackTrace();
}
- parsed_configuration += "client" + System.getProperty("line.separator");
+ common_options += "client" + System.getProperty("line.separator");
- try {
+ return common_options;
+ }
+
+
+ private String extractRemotesFromEipServiceDotJson() {
+ String remotes = "";
+
+ String remote = "ip_address";
+ String remote_openvpn_keyword = "remote";
+ String ports = "ports";
+ String protos = "protocols";
+ String capabilities = "capabilities";
+ String udp = "udp";
+
+ try {
JSONArray protocolsJSON = mGateway.getJSONObject(capabilities).getJSONArray(protos);
- String remote_line = "remote";
for ( int i=0; i<protocolsJSON.length(); i++ ) {
+ String remote_line = remote_openvpn_keyword;
remote_line += " " + mGateway.getString(remote);
remote_line += " " + mGateway.getJSONObject(capabilities).getJSONArray(ports).optString(0);
remote_line += " " + protocolsJSON.optString(i);
- if(remote_line.endsWith("udp"))
- parsed_configuration = parsed_configuration.replaceFirst(System.getProperty("line.separator") + "remote", System.getProperty("line.separator") + remote_line + System.getProperty("line.separator") + "remote");
+ if(remote_line.endsWith(udp))
+ remotes = remotes.replaceFirst(remote_openvpn_keyword, remote_line + System.getProperty("line.separator") + remote_openvpn_keyword);
else
- parsed_configuration += remote_line;
- remote_line = "remote";
- parsed_configuration += System.getProperty("line.separator");
+ remotes += remote_line;
+ remotes += System.getProperty("line.separator");
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
- // try {
- // arg.add(location_key);
- // String locationText = "";
- // locationText = eipDefinition.getJSONObject(locations).getJSONObject(mGateway.getString(location_key)).getString("name");
- // arg.add(locationText);
- // Log.d(TAG, "location = " + locationText);
-
- // } catch (JSONException e) {
- // // TODO Auto-generated catch block
- // e.printStackTrace();
- // }
- // args.add((Vector<String>) arg.clone());
- // options.put("location", (Vector<Vector<String>>) args.clone() );
-
- // arg.clear();
- // args.clear();
-
- return parsed_configuration;
+ Log.d(TAG, "remotes = " + remotes);
+ return remotes;
}
-
private String caSecretFromSharedPreferences() {
String secret_lines = "";
SharedPreferences preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, context.MODE_PRIVATE);
@@ -635,35 +596,16 @@ public final class EIP extends IntentService {
return secret_lines;
}
+
- /**
- * Create and attach the VpnProfile to our gateway object
- */
- protected void createVPNProfile(){
- try {
- ConfigParser cp = new ConfigParser();
- Log.d(TAG, configFromEipServiceDotJson());
- Log.d(TAG, caSecretFromSharedPreferences());
- Log.d(TAG, keySecretFromSharedPreferences());
- Log.d(TAG, certSecretFromSharedPreferences());
- cp.parseConfig(new StringReader(configFromEipServiceDotJson()));
- cp.parseConfig(new StringReader(caSecretFromSharedPreferences()));
- cp.parseConfig(new StringReader(keySecretFromSharedPreferences()));
- cp.parseConfig(new StringReader(certSecretFromSharedPreferences()));
- VpnProfile vp = cp.convertProfile();
- //vp.mAuthenticationType=VpnProfile.TYPE_STATICKEYS;
- mVpnProfile = vp;
- Log.v(TAG,"Created VPNProfile");
- } catch (ConfigParseError e) {
- // FIXME We didn't get a VpnProfile! Error handling! and log level
- Log.v(TAG,"Error creating VPNProfile");
- e.printStackTrace();
- } catch (IOException e) {
- // FIXME We didn't get a VpnProfile! Error handling! and log level
- Log.v(TAG,"Error creating VPNProfile");
- e.printStackTrace();
- }
+ public String locationAsName() {
+ try {
+ return eipDefinition.getJSONObject("locations").getJSONObject(mGateway.getString("location")).getString("name");
+ } catch (JSONException e) {
+ Log.v(TAG,"Couldn't read gateway name for profile creation! Returning original name = " + mName);
+ e.printStackTrace();
+ return (mName != null) ? mName : "";
}
+ }
}
-
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java
index 299d89a4..c8a28c0a 100644
--- a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java
@@ -1,6 +1,10 @@
package se.leap.bitmaskclient;
import se.leap.bitmaskclient.R;
+import se.leap.bitmaskclient.ProviderAPIResultReceiver;
+import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver;
+import se.leap.bitmaskclient.Dashboard;
+
import de.blinkt.openvpn.activities.LogWindow;
import de.blinkt.openvpn.core.VpnStatus;
import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus;
@@ -21,6 +25,7 @@ import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.CompoundButton;
+import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.Switch;
import android.widget.TextView;
@@ -35,12 +40,6 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
private View eipDetail;
private TextView eipStatus;
- private boolean eipAutoSwitched = true;
-
- private boolean mEipStartPending = false;
-
- private boolean set_switch_off = false;
-
private static EIPReceiver mEIPReceiver;
@@ -50,29 +49,19 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- eipFragment = inflater.inflate(R.layout.eip_service_fragment, container, false);
-
+ eipFragment = inflater.inflate(R.layout.eip_service_fragment, container, false);
eipDetail = ((RelativeLayout) eipFragment.findViewById(R.id.eipDetail));
eipDetail.setVisibility(View.VISIBLE);
View eipSettings = eipFragment.findViewById(R.id.eipSettings);
eipSettings.setVisibility(View.GONE); // FIXME too!
- if (mEipStartPending)
- eipFragment.findViewById(R.id.eipProgress).setVisibility(View.VISIBLE);
+ if (EIP.mIsStarting)
+ eipFragment.findViewById(R.id.eipProgress).setVisibility(View.VISIBLE);
eipStatus = (TextView) eipFragment.findViewById(R.id.eipStatus);
eipSwitch = (Switch) eipFragment.findViewById(R.id.eipSwitch);
-
-
- eipSwitch.setOnTouchListener(new View.OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- eipAutoSwitched = false;
- return false;
- }
- });
eipSwitch.setOnCheckedChangeListener(this);
if(getArguments() != null && getArguments().containsKey(START_ON_BOOT) && getArguments().getBoolean(START_ON_BOOT))
@@ -88,7 +77,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
mEIPReceiver = new EIPReceiver(new Handler());
if (savedInstanceState != null)
- mEipStartPending = savedInstanceState.getBoolean(IS_EIP_PENDING);
+ EIP.mIsStarting = savedInstanceState.getBoolean(IS_EIP_PENDING);
}
@Override
@@ -96,15 +85,9 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
super.onResume();
VpnStatus.addStateListener(this);
- if(set_switch_off) {
- eipSwitch.setChecked(false);
- set_switch_off = false;
- }
+
+ eipCommand(EIP.ACTION_CHECK_CERT_VALIDITY);
}
-
- protected void setSwitchOff(boolean value) {
- set_switch_off = value;
- }
@Override
public void onPause() {
@@ -116,7 +99,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
- outState.putBoolean(IS_EIP_PENDING, mEipStartPending);
+ outState.putBoolean(IS_EIP_PENDING, EIP.mIsStarting);
}
protected void saveEipStatus() {
@@ -127,68 +110,101 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
}
if(getActivity() != null)
- getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE).edit().putBoolean(Dashboard.START_ON_BOOT, eip_is_on).commit();
+ Dashboard.preferences.edit().putBoolean(Dashboard.START_ON_BOOT, eip_is_on).commit();
}
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- Log.d("bitmask", "onCheckChanged");
- if (buttonView.equals(eipSwitch) && !eipAutoSwitched){
- boolean allowed_anon = getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE).getBoolean(EIP.ALLOWED_ANON, false);
- String certificate = getActivity().getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE).getString(EIP.CERTIFICATE, "");
- if(allowed_anon || !certificate.isEmpty()) {
- if (isChecked){
- startEipFromScratch();
- } else {
- if (mEipStartPending){
- AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity());
- alertBuilder.setTitle(getResources().getString(R.string.eip_cancel_connect_title));
- alertBuilder
- .setMessage(getResources().getString(R.string.eip_cancel_connect_text))
- .setPositiveButton(getResources().getString(R.string.eip_cancel_connect_cancel), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- eipCommand(EIP.ACTION_STOP_EIP);
- mEipStartPending = false;
- }
- })
- .setNegativeButton(getResources().getString(R.string.eip_cancel_connect_false), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- eipAutoSwitched = true;
- eipSwitch.setChecked(true);
- eipAutoSwitched = false;
- }
- })
- .show();
- } else {
- eipCommand(EIP.ACTION_STOP_EIP);
- }
- }
- }
- else {
- Dashboard dashboard = (Dashboard)getActivity();
- Bundle waiting_on_login = new Bundle();
- waiting_on_login.putBoolean(IS_EIP_PENDING, true);
- dashboard.logInDialog(getActivity().getCurrentFocus(), waiting_on_login);
- }
- }
- else {
- if(!eipSwitch.isChecked())
- eipStatus.setText(R.string.state_noprocess);
- }
- eipAutoSwitched = true;
- saveEipStatus();
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (buttonView.equals(eipSwitch)){
+ handleSwitch(isChecked);
}
+ }
+
+ private void handleSwitch(boolean isChecked) {
+ if(isChecked)
+ handleSwitchOn();
+ else
+ handleSwitchOff();
+ saveEipStatus();
+ }
+
+ private void handleSwitchOn() {
+ if(canStartEIP())
+ startEipFromScratch();
+ else if(canLogInToStartEIP()) {
+ Log.d(TAG, "Can Log In to start EIP");
+ Dashboard dashboard = (Dashboard) getActivity();
+ dashboard.logInDialog(Bundle.EMPTY);
+ }
+ }
+
+ private boolean canStartEIP() {
+ boolean certificateExists = !Dashboard.preferences.getString(EIP.CERTIFICATE, "").isEmpty();
+ boolean isAllowedAnon = Dashboard.preferences.getBoolean(EIP.ALLOWED_ANON, false);
+ return (isAllowedAnon || certificateExists) && !EIP.mIsStarting && !EIP.isConnected();
+ }
+
+ private boolean canLogInToStartEIP() {
+ boolean isAllowedRegistered = Dashboard.preferences.getBoolean(EIP.ALLOWED_REGISTERED, false);
+ boolean isLoggedIn = Dashboard.preferences.getBoolean(EIP.AUTHED_EIP, false);
+ Log.d(TAG, "Allow registered? " + isAllowedRegistered);
+ Log.d(TAG, "Is logged in? " + isLoggedIn);
+ return isAllowedRegistered && !isLoggedIn && !EIP.mIsStarting && !EIP.isConnected();
+ }
+
+ private void handleSwitchOff() {
+ if(EIP.mIsStarting) {
+ askPendingStartCancellation();
+ } else if(EIP.isConnected()) {
+ Log.d(TAG, "Stopping EIP");
+ stopEIP();
+ }
+ }
+
+ private void askPendingStartCancellation() {
+ AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity());
+ alertBuilder.setTitle(getResources().getString(R.string.eip_cancel_connect_title))
+ .setMessage(getResources().getString(R.string.eip_cancel_connect_text))
+ .setPositiveButton((R.string.yes), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ stopEIP();
+ }
+ })
+ .setNegativeButton(getResources().getString(R.string.no), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Log.d(TAG, "askPendingStartCancellation checks the switch to true");
+ eipSwitch.setChecked(true);
+ }
+ })
+ .show();
+ }
public void startEipFromScratch() {
- mEipStartPending = true;
+ EIP.mIsStarting = true;
eipFragment.findViewById(R.id.eipProgress).setVisibility(View.VISIBLE);
- ((TextView) eipFragment.findViewById(R.id.eipStatus)).setText(R.string.eip_status_start_pending);
- eipSwitch.setChecked(true);
- saveEipStatus();
+ String status = getResources().getString(R.string.eip_status_start_pending);
+ setEipStatus(status);
+
+ if(!eipSwitch.isChecked()) {
+ Log.d(TAG, "startEipFromScratch checks the switch to true");
+ eipSwitch.setChecked(true);
+ saveEipStatus();
+ }
eipCommand(EIP.ACTION_START_EIP);
}
+
+ private void stopEIP() {
+ EIP.mIsStarting = false;
+ View eipProgressBar = getActivity().findViewById(R.id.eipProgress);
+ if(eipProgressBar != null)
+ eipProgressBar.setVisibility(View.GONE);
+
+ String status = getResources().getString(R.string.eip_state_not_connected);
+ setEipStatus(status);
+ eipCommand(EIP.ACTION_STOP_EIP);
+ }
/**
* Send a command to EIP
@@ -198,49 +214,104 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
*/
private void eipCommand(String action){
// TODO validate "action"...how do we get the list of intent-filters for a class via Android API?
- Intent vpnIntent = new Intent(action);
- vpnIntent.putExtra(EIP.RECEIVER_TAG, mEIPReceiver);
- getActivity().startService(vpnIntent);
+ Intent vpn_intent = new Intent(getActivity().getApplicationContext(), EIP.class);
+ vpn_intent.setAction(action);
+ vpn_intent.putExtra(EIP.RECEIVER_TAG, mEIPReceiver);
+ getActivity().startService(vpn_intent);
}
- @Override
- public void updateState(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) {
- // Note: "states" are not organized anywhere...collected state strings:
- // NOPROCESS,NONETWORK,BYTECOUNT,AUTH_FAILED + some parsing thing ( WAIT(?),AUTH,GET_CONFIG,ASSIGN_IP,CONNECTED,SIGINT )
- getActivity().runOnUiThread(new Runnable() {
-
- @Override
- public void run() {
- if (eipStatus != null) {
- boolean switchState = true;
- String statusMessage = "";
- String prefix = getString(localizedResId);
- if (level == ConnectionStatus.LEVEL_CONNECTED){
- statusMessage = getString(R.string.eip_state_connected);
- getActivity().findViewById(R.id.eipProgress).setVisibility(View.GONE);
- mEipStartPending = false;
- } else if ( level == ConnectionStatus.LEVEL_NONETWORK || level == ConnectionStatus.LEVEL_NOTCONNECTED || level == ConnectionStatus.LEVEL_AUTH_FAILED) {
- statusMessage = getString(R.string.eip_state_not_connected);
- if(getActivity() != null && getActivity().findViewById(R.id.eipProgress) != null)
- getActivity().findViewById(R.id.eipProgress).setVisibility(View.GONE);
- mEipStartPending = false;
- switchState = false;
- } else if (level == ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED) {
- if(state.equals("AUTH") || state.equals("GET_CONFIG"))
- statusMessage = prefix + " " + logmessage;
- } else if (level == ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET) {
- statusMessage = prefix + " " + logmessage;
- }
-
- eipAutoSwitched = true;
- eipSwitch.setChecked(switchState);
- eipAutoSwitched = false;
- eipStatus.setText(statusMessage);
- }
- }
+ @Override
+ public void updateState(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) {
+ boolean isNewLevel = EIP.lastConnectionStatusLevel != level;
+ boolean justDecidedOnDisconnect = EIP.lastConnectionStatusLevel == ConnectionStatus.UNKNOWN_LEVEL;
+ Log.d(TAG, "update state with level " + level);
+ if(!justDecidedOnDisconnect && (isNewLevel || level == ConnectionStatus.LEVEL_CONNECTED)) {
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ EIP.lastConnectionStatusLevel = level;
+ handleNewState(state, logmessage, localizedResId, level);
+ }
});
+ } else if(justDecidedOnDisconnect && level == ConnectionStatus.LEVEL_CONNECTED) {
+ EIP.lastConnectionStatusLevel = ConnectionStatus.LEVEL_NOTCONNECTED;
+ updateState(state, logmessage, localizedResId, level);
+ }
+ }
+
+ private void handleNewState(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) {
+ if (level == ConnectionStatus.LEVEL_CONNECTED)
+ setConnectedUI();
+ else if (isDisconnectedLevel(level) && !EIP.mIsStarting)
+ setDisconnectedUI();
+ else if (level == ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET)
+ setNoServerReplyUI(localizedResId, logmessage);
+ else if (level == ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED)
+ setServerReplyUI(state, localizedResId, logmessage);
+ }
+
+ private boolean isDisconnectedLevel(final ConnectionStatus level) {
+ return level == ConnectionStatus.LEVEL_NONETWORK || level == ConnectionStatus.LEVEL_NOTCONNECTED || level == ConnectionStatus.LEVEL_AUTH_FAILED;
+ }
+
+ private void setConnectedUI() {
+ hideProgressBar();
+ Log.d(TAG, "mIsDisconnecting = false in setConnectedUI");
+ EIP.mIsStarting = false; //TODO This should be done in the onReceiveResult from START_EIP command, but right now LaunchVPN isn't notifying anybody the resultcode of the request so we need to listen the states with this listener.
+ EIP.mIsDisconnecting = false; //TODO See comment above
+ String status = getString(R.string.eip_state_connected);
+ setEipStatus(status);
+ adjustSwitch();
+ }
+
+ private void setDisconnectedUI(){
+ hideProgressBar();
+ EIP.mIsStarting = false; //TODO See comment in setConnectedUI()
+ Log.d(TAG, "mIsDisconnecting = false in setDisconnectedUI");
+ EIP.mIsDisconnecting = false; //TODO See comment in setConnectedUI()
+
+ String status = getString(R.string.eip_state_not_connected);
+ setEipStatus(status);
+ adjustSwitch();
+ }
+
+ private void adjustSwitch() {
+ if(EIP.isConnected()) {
+ if(!eipSwitch.isChecked()) {
+ eipSwitch.setChecked(true);
+ }
+ } else {
+ if(eipSwitch.isChecked()) {
+ eipSwitch.setChecked(false);
+ }
}
+ }
+
+ private void setNoServerReplyUI(int localizedResId, String logmessage) {
+ if(eipStatus != null) {
+ String prefix = getString(localizedResId);
+ setEipStatus(prefix + " " + logmessage);
+ }
+ }
+
+ private void setServerReplyUI(String state, int localizedResId, String logmessage) {
+ if(eipStatus != null)
+ if(state.equals("AUTH") || state.equals("GET_CONFIG")) {
+ String prefix = getString(localizedResId);
+ setEipStatus(prefix + " " + logmessage);
+ }
+ }
+ protected void setEipStatus(String status) {
+ if(eipStatus == null)
+ eipStatus = (TextView) getActivity().findViewById(R.id.eipStatus);
+ eipStatus.setText(status);
+ }
+
+ private void hideProgressBar() {
+ if(getActivity() != null && getActivity().findViewById(R.id.eipProgress) != null)
+ getActivity().findViewById(R.id.eipProgress).setVisibility(View.GONE);
+ }
/**
* Inner class for handling messages related to EIP status and control requests
@@ -256,7 +327,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
-
+
String request = resultData.getString(EIP.REQUEST_TAG);
boolean checked = false;
@@ -272,8 +343,10 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
} else if (request == EIP.ACTION_START_EIP) {
switch (resultCode){
case Activity.RESULT_OK:
+ Log.d(TAG, "Action start eip = Result OK");
checked = true;
eipFragment.findViewById(R.id.eipProgress).setVisibility(View.VISIBLE);
+ EIP.mIsStarting = false;
break;
case Activity.RESULT_CANCELED:
checked = false;
@@ -298,11 +371,31 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
checked = false;
break;
}
+ } else if (request == EIP.ACTION_CHECK_CERT_VALIDITY) {
+ checked = eipSwitch.isChecked();
+
+ switch (resultCode) {
+ case Activity.RESULT_OK:
+ break;
+ case Activity.RESULT_CANCELED:
+ Dashboard dashboard = (Dashboard) getActivity();
+
+ dashboard.setProgressBarVisibility(ProgressBar.VISIBLE);
+ String status = getResources().getString(R.string.updating_certificate_message);
+ setEipStatus(status);
+
+ Intent provider_API_command = new Intent(getActivity(), ProviderAPI.class);
+ if(dashboard.providerAPI_result_receiver == null) {
+ dashboard.providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
+ dashboard.providerAPI_result_receiver.setReceiver(dashboard);
+ }
+
+ provider_API_command.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE);
+ provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, dashboard.providerAPI_result_receiver);
+ getActivity().startService(provider_API_command);
+ break;
+ }
}
-
- eipAutoSwitched = true;
- eipSwitch.setChecked(checked);
- eipAutoSwitched = false;
}
}
@@ -317,6 +410,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe
public void checkEipSwitch(boolean checked) {
eipSwitch.setChecked(checked);
- onCheckedChanged(eipSwitch, checked);
+ // Log.d(TAG, "checkEipSwitch");
+ // onCheckedChanged(eipSwitch, checked);
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/EipStatusReceiver.java b/app/src/main/java/se/leap/bitmaskclient/EipStatusReceiver.java
deleted file mode 100644
index 8793cf36..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/EipStatusReceiver.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package se.leap.bitmaskclient;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-
-public class EipStatusReceiver extends BroadcastReceiver {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals("de.blinkt.openvpn.VPN_STATUS")) {
- context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Context.MODE_PRIVATE).edit().putString(EIP.STATUS, intent.getStringExtra("status")).commit();
- }
- }
-}