From 261dc90595e583914161e5e9011f5f5dd4a9740c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 12 Nov 2014 01:30:09 +0100 Subject: eip package, EIP constants to interface. --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 81 ++-- app/src/main/java/se/leap/bitmaskclient/EIP.java | 524 --------------------- .../se/leap/bitmaskclient/EipServiceFragment.java | 92 ++-- .../java/se/leap/bitmaskclient/OnBootReceiver.java | 7 +- .../se/leap/bitmaskclient/VoidVpnLauncher.java | 37 -- .../java/se/leap/bitmaskclient/VoidVpnService.java | 36 -- .../se/leap/bitmaskclient/VpnConfigGenerator.java | 146 ------ .../java/se/leap/bitmaskclient/eip/Constants.java | 50 ++ .../main/java/se/leap/bitmaskclient/eip/EIP.java | 486 +++++++++++++++++++ .../se/leap/bitmaskclient/eip/VoidVpnLauncher.java | 37 ++ .../se/leap/bitmaskclient/eip/VoidVpnService.java | 37 ++ .../leap/bitmaskclient/eip/VpnConfigGenerator.java | 145 ++++++ 12 files changed, 827 insertions(+), 851 deletions(-) delete mode 100644 app/src/main/java/se/leap/bitmaskclient/EIP.java delete mode 100644 app/src/main/java/se/leap/bitmaskclient/VoidVpnLauncher.java delete mode 100644 app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java delete mode 100644 app/src/main/java/se/leap/bitmaskclient/VpnConfigGenerator.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/eip/Constants.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/eip/EIP.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 364a79af..473cd5ec 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -14,38 +14,21 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - package se.leap.bitmaskclient; +package se.leap.bitmaskclient; -import org.json.JSONException; -import org.json.JSONObject; - -import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver; -import se.leap.bitmaskclient.FragmentManagerEnhanced; -import se.leap.bitmaskclient.SignUpDialog; +import se.leap.bitmaskclient.*; +import se.leap.bitmaskclient.eip.*; import de.blinkt.openvpn.activities.LogWindow; -import android.app.Activity; -import android.app.AlertDialog; -import android.app.DialogFragment; -import android.app.FragmentTransaction; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.SharedPreferences; +import android.app.*; +import android.content.*; import android.content.pm.PackageManager.NameNotFoundException; -import android.os.Bundle; -import android.os.Handler; -import android.os.ResultReceiver; +import android.os.*; import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ProgressBar; -import android.widget.TextView; -import android.widget.Toast; +import android.view.*; +import android.widget.*; +import org.json.*; /** * The main user facing Activity of LEAP Android, consisting of status, controls, @@ -54,7 +37,7 @@ import android.widget.Toast; * @author Sean Leonard * @author parmegv */ -public class Dashboard extends Activity implements LogInDialog.LogInDialogInterface, SignUpDialog.SignUpDialogInterface, Receiver { +public class Dashboard extends Activity implements LogInDialog.LogInDialogInterface, SignUpDialog.SignUpDialogInterface, ProviderAPIResultReceiver.Receiver { protected static final int CONFIGURE_LEAP = 0; protected static final int SWITCH_PROVIDER = 1; @@ -95,7 +78,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf fragment_manager = new FragmentManagerEnhanced(getFragmentManager()); handleVersion(); - authed_eip = preferences.getBoolean(EIP.AUTHED_EIP, false); + authed_eip = preferences.getBoolean(Constants.AUTHED_EIP, false); if (preferences.getString(Provider.KEY, "").isEmpty()) startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP); else @@ -113,9 +96,9 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf switch(versionCode) { case 91: // 0.6.0 without Bug #5999 case 101: // 0.8.0 - if(!preferences.getString(EIP.KEY, "").isEmpty()) { + if(!preferences.getString(Constants.KEY, "").isEmpty()) { Intent rebuildVpnProfiles = new Intent(getApplicationContext(), EIP.class); - rebuildVpnProfiles.setAction(EIP.ACTION_REBUILD_PROFILES); + rebuildVpnProfiles.setAction(Constants.ACTION_REBUILD_PROFILES); startService(rebuildVpnProfiles); } break; @@ -139,23 +122,21 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf if ( requestCode == CONFIGURE_LEAP || requestCode == SWITCH_PROVIDER) { // It should be equivalent: if ( (requestCode == CONFIGURE_LEAP) || (data!= null && data.hasExtra(STOP_FIRST))) { if ( resultCode == RESULT_OK ){ - preferences.edit().putInt(EIP.PARSED_SERIAL, 0).commit(); - preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit(); - + preferences.edit().putInt(Constants.PARSED_SERIAL, 0).commit(); + preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).commit(); Intent updateEIP = new Intent(getApplicationContext(), EIP.class); - updateEIP.setAction(EIP.ACTION_UPDATE_EIP_SERVICE); + updateEIP.setAction(Constants.ACTION_UPDATE_EIP_SERVICE); startService(updateEIP); - buildDashboard(false); invalidateOptionsMenu(); if(data != null && data.hasExtra(LogInDialog.TAG)) { View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0); logInDialog(Bundle.EMPTY); } - } else if(resultCode == RESULT_CANCELED && (data == null || data.hasExtra(ACTION_QUIT))) { - finish(); - } else - configErrorDialog(); + } else if(resultCode == RESULT_CANCELED && (data == null || data.hasExtra(ACTION_QUIT))) { + finish(); + } else + configErrorDialog(); } } @@ -227,7 +208,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf 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(EIP.ALLOWED_REGISTERED, allow_registered_eip); + preferences.edit().putBoolean(Constants.ALLOWED_REGISTERED, allow_registered_eip); if(allow_registered_eip) { if(authed_eip) { @@ -268,7 +249,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf return true; case R.id.switch_provider: if (Provider.getInstance().hasEIP()){ - if (preferences.getBoolean(EIP.AUTHED_EIP, false)){ + if (preferences.getBoolean(Constants.AUTHED_EIP, false)){ logOut(); } eipStop(); @@ -426,7 +407,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf invalidateOptionsMenu(); authed_eip = true; - preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit(); + preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).commit(); downloadAuthedUserCertificate(); } else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_FAILED) { @@ -441,7 +422,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf invalidateOptionsMenu(); authed_eip = false; - preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit(); + preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).commit(); } else if(resultCode == ProviderAPI.LOGOUT_FAILED) { changeStatusMessage(resultCode); @@ -457,7 +438,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf ResultReceiver eip_receiver = new ResultReceiver(new Handler()){ protected void onReceiveResult(int resultCode, Bundle resultData){ super.onReceiveResult(resultCode, resultData); - String request = resultData.getString(EIP.REQUEST_TAG); + String request = resultData.getString(Constants.REQUEST_TAG); if (resultCode == Activity.RESULT_OK){ if(authed_eip) eipStart(); @@ -466,8 +447,8 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } } }; - updateEIP.putExtra(EIP.RECEIVER_TAG, eip_receiver); - updateEIP.setAction(EIP.ACTION_UPDATE_EIP_SERVICE); + updateEIP.putExtra(Constants.RECEIVER_TAG, eip_receiver); + updateEIP.setAction(Constants.ACTION_UPDATE_EIP_SERVICE); startService(updateEIP); } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) { changeStatusMessage(resultCode); @@ -481,9 +462,9 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf ResultReceiver eip_status_receiver = new ResultReceiver(new Handler()){ protected void onReceiveResult(int resultCode, Bundle resultData){ super.onReceiveResult(resultCode, resultData); - String request = resultData.getString(EIP.REQUEST_TAG); + String request = resultData.getString(Constants.REQUEST_TAG); if(eipStatus == null) eipStatus = (TextView) findViewById(R.id.eipStatus); - if (request.equalsIgnoreCase(EIP.ACTION_IS_EIP_RUNNING)){ + if (request.equalsIgnoreCase(Constants.ACTION_IS_EIP_RUNNING)){ if (resultCode == Activity.RESULT_OK){ switch(previous_result_code){ @@ -544,8 +525,8 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf 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 eip_intent = new Intent(this, EIP.class); - eip_intent.setAction(EIP.ACTION_IS_EIP_RUNNING); - eip_intent.putExtra(EIP.RECEIVER_TAG, eip_receiver); + eip_intent.setAction(Constants.ACTION_IS_EIP_RUNNING); + eip_intent.putExtra(Constants.RECEIVER_TAG, eip_receiver); startService(eip_intent); } diff --git a/app/src/main/java/se/leap/bitmaskclient/EIP.java b/app/src/main/java/se/leap/bitmaskclient/EIP.java deleted file mode 100644 index 2f06def3..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/EIP.java +++ /dev/null @@ -1,524 +0,0 @@ -/** - * 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 . - */ -package se.leap.bitmaskclient; - -import android.app.Activity; -import android.app.IntentService; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Bundle; -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; -import de.blinkt.openvpn.core.ConfigParser.ConfigParseError; -import de.blinkt.openvpn.core.ProfileManager; -import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus; -import java.io.IOException; -import java.io.StringReader; -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 - * Internet Proxy connection. Connections are started, stopped, and queried through - * 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 - * @author Parménides GV - */ -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 ACTION_REBUILD_PROFILES = "se.leap.bitmaskclient.REBUILD_PROFILES"; - 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"; - public final static String PARSED_SERIAL = "eip_parsed_serial"; - public final static String SERVICE_API_PATH = "config/eip-service.json"; - public final static String RECEIVER_TAG = "receiverTag"; - public final static String REQUEST_TAG = "requestTag"; - public final static String TAG = EIP.class.getSimpleName(); - private static SharedPreferences preferences; - - private static Context context; - private static ResultReceiver mReceiver; - private static boolean mBound = false; - - 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 static SimpleDateFormat certificate_date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US); - public EIP(){ - super("LEAPEIP"); - } - - @Override - public void onCreate() { - super.onCreate(); - - context = getApplicationContext(); - - preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); - } - - @Override - public void onDestroy() { - - mBound = false; - - super.onDestroy(); - } - - - @Override - protected void onHandleIntent(Intent intent) { - String action = intent.getAction(); - mReceiver = intent.getParcelableExtra(RECEIVER_TAG); - - if ( action == ACTION_START_EIP ) - startEIP(); - else if ( action == ACTION_STOP_EIP ) - stopEIP(); - else if ( action == ACTION_IS_EIP_RUNNING ) - isRunning(); - else if ( action == ACTION_UPDATE_EIP_SERVICE ) - updateEIPService(); - else if ( action == ACTION_CHECK_CERT_VALIDITY ) - checkCertValidity(); - else if ( action == ACTION_REBUILD_PROFILES ) - updateGateways(); - } - - /** - * Initiates an EIP connection by selecting a gateway and preparing and sending an - * Intent to {@link se.leap.openvpn.LaunchVPN}. - * It also sets up early routes. - */ - private void startEIP() { - earlyRoutes(); - activeGateway = selectGateway(); - - if(activeGateway != null && activeGateway.mVpnProfile != null) { - mReceiver = EipServiceFragment.getReceiver(); - launchActiveGateway(); - } - } - - /** - * Early routes are routes that block traffic until a new - * 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); - } - - /** - * Choose a gateway to connect to based on timezone from system locale data - * - * @return The gateway to connect to - */ - private OVPNGateway selectGateway() { - String closest_location = closestGateway(); - String chosen_host = chooseHost(closest_location); - - return new OVPNGateway(chosen_host); - } - - private String closestGateway() { - TreeMap> offsets = calculateOffsets(); - return offsets.isEmpty() ? "" : offsets.firstEntry().getValue().iterator().next(); - } - - private TreeMap> calculateOffsets() { - TreeMap> offsets = new TreeMap>(); - - int localOffset = Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000; - - JSONObject locations = availableLocations(); - Iterator locations_names = locations.keys(); - while(locations_names.hasNext()) { - try { - String location_name = locations_names.next(); - JSONObject location = locations.getJSONObject(location_name); - - int dist = timezoneDistance(localOffset, location.optInt("timezone")); - - Set set = (offsets.get(dist) != null) ? - offsets.get(dist) : new HashSet(); - - set.add(location_name); - offsets.put(dist, set); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - return offsets; - } - - private JSONObject availableLocations() { - JSONObject locations = null; - try { - if(eipDefinition == null) updateEIPService(); - locations = eipDefinition.getJSONObject("locations"); - } catch (JSONException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - - return locations; - } - - 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; - } - - private String chooseHost(String location) { - String chosen_host = ""; - try { - JSONArray gateways = eipDefinition.getJSONArray("gateways"); - for (int i = 0; i < gateways.length(); i++) { - JSONObject gw = gateways.getJSONObject(i); - if ( gw.getString("location").equalsIgnoreCase(location) || location.isEmpty()){ - chosen_host = eipDefinition.getJSONObject("locations").getJSONObject(gw.getString("location")).getString("name"); - break; - } - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return chosen_host; - } - - 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); - } - - /** - * 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(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"); - } - - tellToReceiver(ACTION_STOP_EIP, Activity.RESULT_OK); - } - - private void tellToReceiver(String action, int resultCode) { - if (mReceiver != null){ - Bundle resultData = new Bundle(); - resultData.putString(REQUEST_TAG, action); - mReceiver.send(resultCode, resultData); - } - } - - /** - * Checks the last stored status notified by ics-openvpn - * Sends Activity.RESULT_CANCELED to the ResultReceiver that made the - * request if it's not connected, Activity.RESULT_OK otherwise. - */ - - private void isRunning() { - int resultCode = Activity.RESULT_CANCELED; - boolean is_connected = isConnected(); - - resultCode = (is_connected) ? Activity.RESULT_OK : Activity.RESULT_CANCELED; - - tellToReceiver(ACTION_IS_EIP_RUNNING, resultCode); - } - - 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. - * TODO Implement API call to refresh eip-service.json from the provider - */ - private void updateEIPService() { - try { - String eip_definition_string = preferences.getString(KEY, ""); - if(eip_definition_string.isEmpty() == false) { - eipDefinition = new JSONObject(eip_definition_string); - } - deleteAllVpnProfiles(); - updateGateways(); - if(mReceiver != null) mReceiver.send(Activity.RESULT_OK, Bundle.EMPTY); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - private void deleteAllVpnProfiles() { - ProfileManager vpl = ProfileManager.getInstance(context); - Collection profiles = vpl.getProfiles(); - profiles.removeAll(profiles); - } - - /** - * Walk the list of gateways defined in eip-service.json and parse them into - * OVPNGateway objects. - * TODO Store the OVPNGateways (as Serializable) in SharedPreferences - */ - private void updateGateways(){ - JSONArray gatewaysDefined = null; - try { - if(eipDefinition == null) updateEIPService(); - gatewaysDefined = eipDefinition.getJSONArray("gateways"); - for ( int i=0 ; i < gatewaysDefined.length(); i++ ){ - JSONObject gw = null; - gw = gatewaysDefined.getJSONObject(i); - - if ( gw.getJSONObject("capabilities").getJSONArray("transport").toString().contains("openvpn") ) - new OVPNGateway(gw); - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - preferences.edit().putInt(PARSED_SERIAL, eipDefinition.optInt(Provider.API_RETURN_SERIAL)).commit(); - } - - private void checkCertValidity() { - String certificate = preferences.getString(CERTIFICATE, ""); - checkCertValidity(certificate); - } - - private void checkCertValidity(String certificate_string) { - if(!certificate_string.isEmpty()) { - X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(certificate_string); - - Calendar offset_date = calculateOffsetCertificateValidity(certificate); - Bundle result = new Bundle(); - result.putString(REQUEST_TAG, ACTION_CHECK_CERT_VALIDITY); - try { - Log.d(TAG, "offset_date = " + offset_date.getTime().toString()); - certificate.checkValidity(offset_date.getTime()); - mReceiver.send(Activity.RESULT_OK, result); - Log.d(TAG, "Valid certificate"); - } catch(CertificateExpiredException e) { - mReceiver.send(Activity.RESULT_CANCELED, result); - Log.d(TAG, "Updating certificate"); - } catch(CertificateNotYetValidException e) { - mReceiver.send(Activity.RESULT_CANCELED, result); - } - } - } - - private Calendar calculateOffsetCertificateValidity(X509Certificate certificate) { - String current_date = certificate_date_format.format(Calendar.getInstance().getTime()).toString(); - - String date_string = preferences.getString(DATE_FROM_CERTIFICATE, current_date); - - Calendar offset_date = Calendar.getInstance(); - try { - Date date = certificate_date_format.parse(date_string); - long difference = Math.abs(date.getTime() - certificate.getNotAfter().getTime())/2; - long current_date_millis = offset_date.getTimeInMillis(); - offset_date.setTimeInMillis(current_date_millis + difference); - Log.d(TAG, "certificate not after = " + certificate.getNotAfter()); - } catch(ParseException e) { - e.printStackTrace(); - } - - return offset_date; - } - - /** - * OVPNGateway provides objects defining gateways and their options and metadata. - * Each instance contains a VpnProfile for OpenVPN specific data and member - * variables describing capabilities and location - * - * @author Sean Leonard - */ - private class OVPNGateway { - - private String TAG = "OVPNGateway"; - - private String mName; - private VpnProfile mVpnProfile; - private JSONObject mGateway; - private HashMap>> options = new HashMap>>(); - - - /** - * Attempts to retrieve a VpnProfile by name and build an OVPNGateway around it. - * FIXME This needs to become a findGatewayByName() method - * - * @param name The hostname of the gateway to inflate - */ - private OVPNGateway(String name){ - mName = name; - - this.loadVpnProfile(); - } - - private void loadVpnProfile() { - ProfileManager vpl = ProfileManager.getInstance(context); - try { - if ( mName == null ) - mVpnProfile = vpl.getProfiles().iterator().next(); - else - mVpnProfile = vpl.getProfileByName(mName); - } catch (NoSuchElementException e) { - updateEIPService(); - this.loadVpnProfile(); // FIXME catch infinite loops - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - /** - * Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json - * and create a VpnProfile belonging to it. - * - * @param gateway The JSON OpenVPN gateway definition to parse - */ - protected OVPNGateway(JSONObject gateway){ - - mGateway = gateway; - - // Currently deletes VpnProfile for host, if there already is one, and builds new - ProfileManager vpl = ProfileManager.getInstance(context); - Collection profiles = vpl.getProfiles(); - for (Iterator it = profiles.iterator(); it.hasNext(); ){ - VpnProfile p = it.next(); - - if ( p.mName.equalsIgnoreCase( mName ) ) { - it.remove(); - vpl.removeProfile(context, p); - } - } - - this.createVPNProfile(); - - vpl.addProfile(mVpnProfile); - vpl.saveProfile(context, mVpnProfile); - vpl.saveProfileList(context); - } - - /** - * Create and attach the VpnProfile to our gateway object - */ - protected void createVPNProfile(){ - try { - ConfigParser cp = new ConfigParser(); - - JSONObject openvpn_configuration = eipDefinition.getJSONObject("openvpn_configuration"); - VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(preferences, openvpn_configuration, mGateway); - String configuration = vpn_configuration_generator.generate(); - - cp.parseConfig(new StringReader(configuration)); - mVpnProfile = cp.convertProfile(); - mVpnProfile.mName = mName = locationAsName(); - Log.v(TAG,"Created VPNProfile"); - - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } 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 6d223dd6..f35a3cfa 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java @@ -3,34 +3,18 @@ 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; -import de.blinkt.openvpn.core.VpnStatus.StateListener; -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 se.leap.bitmaskclient.eip.*; + +import de.blinkt.openvpn.activities.*; +import de.blinkt.openvpn.core.*; +import android.app.*; +import android.content.*; +import android.os.*; import android.util.Log; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; -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; - -public class EipServiceFragment extends Fragment implements StateListener, OnCheckedChangeListener { +import android.view.*; +import android.widget.*; + +public class EipServiceFragment extends Fragment implements VpnStatus.StateListener, CompoundButton.OnCheckedChangeListener { protected static final String IS_EIP_PENDING = "is_eip_pending"; public static final String START_ON_BOOT = "start on boot"; @@ -85,8 +69,8 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe super.onResume(); VpnStatus.addStateListener(this); - - eipCommand(EIP.ACTION_CHECK_CERT_VALIDITY); + + eipCommand(Constants.ACTION_CHECK_CERT_VALIDITY); } @Override @@ -139,13 +123,13 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe } private boolean canStartEIP() { - boolean certificateExists = !Dashboard.preferences.getString(EIP.CERTIFICATE, "").isEmpty(); - boolean isAllowedAnon = Dashboard.preferences.getBoolean(EIP.ALLOWED_ANON, false); + boolean certificateExists = !Dashboard.preferences.getString(Constants.CERTIFICATE, "").isEmpty(); + boolean isAllowedAnon = Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false); return (isAllowedAnon || certificateExists) && !EIP.mIsStarting && !EIP.isConnected(); } private boolean canLogInToStartEIP() { - boolean isAllowedRegistered = Dashboard.preferences.getBoolean(EIP.ALLOWED_REGISTERED, false); + 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); @@ -192,7 +176,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe eipSwitch.setChecked(true); saveEipStatus(); } - eipCommand(EIP.ACTION_START_EIP); + eipCommand(Constants.ACTION_START_EIP); } protected void stopEIP() { @@ -203,7 +187,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe String status = getResources().getString(R.string.eip_state_not_connected); setEipStatus(status); - eipCommand(EIP.ACTION_STOP_EIP); + eipCommand(Constants.ACTION_STOP_EIP); } /** @@ -216,16 +200,16 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe // TODO validate "action"...how do we get the list of intent-filters for a class via Android API? Intent vpn_intent = new Intent(getActivity().getApplicationContext(), EIP.class); vpn_intent.setAction(action); - vpn_intent.putExtra(EIP.RECEIVER_TAG, mEIPReceiver); + vpn_intent.putExtra(Constants.RECEIVER_TAG, mEIPReceiver); getActivity().startService(vpn_intent); } @Override - public void updateState(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) { + public void updateState(final String state, final String logmessage, final int localizedResId, final VpnStatus.ConnectionStatus level) { boolean isNewLevel = EIP.lastConnectionStatusLevel != level; - boolean justDecidedOnDisconnect = EIP.lastConnectionStatusLevel == ConnectionStatus.UNKNOWN_LEVEL; + boolean justDecidedOnDisconnect = EIP.lastConnectionStatusLevel == VpnStatus.ConnectionStatus.UNKNOWN_LEVEL; Log.d(TAG, "update state with level " + level); - if(!justDecidedOnDisconnect && (isNewLevel || level == ConnectionStatus.LEVEL_CONNECTED)) { + if(!justDecidedOnDisconnect && (isNewLevel || level == VpnStatus.ConnectionStatus.LEVEL_CONNECTED)) { getActivity().runOnUiThread(new Runnable() { @Override public void run() { @@ -233,28 +217,28 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe handleNewState(state, logmessage, localizedResId, level); } }); - } else if(justDecidedOnDisconnect && level == ConnectionStatus.LEVEL_CONNECTED) { - EIP.lastConnectionStatusLevel = ConnectionStatus.LEVEL_NOTCONNECTED; + } else if(justDecidedOnDisconnect && level == VpnStatus.ConnectionStatus.LEVEL_CONNECTED) { + EIP.lastConnectionStatusLevel = VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED; updateState(state, logmessage, localizedResId, level); } // else if(isNewLevel || level == ConnectionStatus.LEVEL_AUTH_FAILED) // handleNewState(state, logmessage, localizedResId, level); } - private void handleNewState(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) { - if (level == ConnectionStatus.LEVEL_CONNECTED) + private void handleNewState(final String state, final String logmessage, final int localizedResId, final VpnStatus.ConnectionStatus level) { + if (level == VpnStatus.ConnectionStatus.LEVEL_CONNECTED) setConnectedUI(); else if (isDisconnectedLevel(level) && !EIP.mIsStarting) setDisconnectedUI(); - else if (level == ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET) + else if (level == VpnStatus.ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET) setNoServerReplyUI(localizedResId, logmessage); - else if (level == ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED) + else if (level == VpnStatus.ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED) setServerReplyUI(state, localizedResId, logmessage); - // else if (level == ConnectionStatus.LEVEL_AUTH_FAILED) + // else if (level == VpnStatus.ConnectionStatus.LEVEL_AUTH_FAILED) // handleSwitchOn(); } - private boolean isDisconnectedLevel(final ConnectionStatus level) { - return level == ConnectionStatus.LEVEL_NOTCONNECTED || level == ConnectionStatus.LEVEL_AUTH_FAILED; + private boolean isDisconnectedLevel(final VpnStatus.ConnectionStatus level) { + return level == VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED || level == VpnStatus.ConnectionStatus.LEVEL_AUTH_FAILED; } private void setConnectedUI() { @@ -331,10 +315,10 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe protected void onReceiveResult(int resultCode, Bundle resultData) { super.onReceiveResult(resultCode, resultData); - String request = resultData.getString(EIP.REQUEST_TAG); + String request = resultData.getString(Constants.REQUEST_TAG); boolean checked = false; - if (request == EIP.ACTION_IS_EIP_RUNNING) { + if (request == Constants.ACTION_IS_EIP_RUNNING) { switch (resultCode){ case Activity.RESULT_OK: checked = true; @@ -343,7 +327,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe checked = false; break; } - } else if (request == EIP.ACTION_START_EIP) { + } else if (request == Constants.ACTION_START_EIP) { switch (resultCode){ case Activity.RESULT_OK: Log.d(TAG, "Action start eip = Result OK"); @@ -356,7 +340,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe eipFragment.findViewById(R.id.eipProgress).setVisibility(View.GONE); break; } - } else if (request == EIP.ACTION_STOP_EIP) { + } else if (request == Constants.ACTION_STOP_EIP) { switch (resultCode){ case Activity.RESULT_OK: checked = false; @@ -365,7 +349,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe checked = true; break; } - } else if (request == EIP.EIP_NOTIFICATION) { + } else if (request == Constants.EIP_NOTIFICATION) { switch (resultCode){ case Activity.RESULT_OK: checked = true; @@ -374,7 +358,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe checked = false; break; } - } else if (request == EIP.ACTION_CHECK_CERT_VALIDITY) { + } else if (request == Constants.ACTION_CHECK_CERT_VALIDITY) { checked = eipSwitch.isChecked(); switch (resultCode) { @@ -387,7 +371,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe String status = getResources().getString(R.string.updating_certificate_message); setEipStatus(status); - if(LeapSRPSession.getToken().isEmpty() && !Dashboard.preferences.getBoolean(EIP.ALLOWED_ANON, false)) { + if(LeapSRPSession.getToken().isEmpty() && !Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false)) { dashboard.logInDialog(Bundle.EMPTY); } else { diff --git a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java index eb196d46..74f89ab8 100644 --- a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java +++ b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java @@ -1,10 +1,9 @@ package se.leap.bitmaskclient; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; +import android.content.*; import android.util.Log; +import se.leap.bitmaskclient.eip.Constants; public class OnBootReceiver extends BroadcastReceiver { @@ -14,7 +13,7 @@ public class OnBootReceiver extends BroadcastReceiver { if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { if (!context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Context.MODE_PRIVATE).getString(Provider.KEY, "").isEmpty() && context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Context.MODE_PRIVATE).getBoolean(Dashboard.START_ON_BOOT, false)) { Intent dashboard_intent = new Intent(context, Dashboard.class); - dashboard_intent.setAction(EIP.ACTION_START_EIP); + 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/VoidVpnLauncher.java b/app/src/main/java/se/leap/bitmaskclient/VoidVpnLauncher.java deleted file mode 100644 index 3b286fbf..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/VoidVpnLauncher.java +++ /dev/null @@ -1,37 +0,0 @@ -package se.leap.bitmaskclient; - -import android.app.Activity; -import android.content.Intent; -import android.net.VpnService; -import android.os.Bundle; - -public class VoidVpnLauncher extends Activity { - - private static final int VPN_USER_PERMISSION = 71; - - @Override - protected void onCreate(Bundle savedInstanceState) { - 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); - } - } - - 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(VoidVpnService.START_BLOCKING_VPN_PROFILE); - startService(void_vpn_service); - } - } - finish(); - } -} diff --git a/app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java b/app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java deleted file mode 100644 index 7b597554..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java +++ /dev/null @@ -1,36 +0,0 @@ -package se.leap.bitmaskclient; - -import android.content.Intent; -import android.os.Process; -import android.net.VpnService; -import android.util.Log; - -public class VoidVpnService extends VpnService { - - static final String START_BLOCKING_VPN_PROFILE = "se.leap.bitmaskclient.START_BLOCKING_VPN_PROFILE"; - static final String TAG = VoidVpnService.class.getSimpleName(); - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - String action = intent.getAction(); - if (action == 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 { - builder.establish(); - } catch (Exception e) { - e.printStackTrace(); - } - android.util.Log.d(TAG, "VoidVpnService set up"); - } - }).run(); - } - return 0; - } -} diff --git a/app/src/main/java/se/leap/bitmaskclient/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/VpnConfigGenerator.java deleted file mode 100644 index ef049a3c..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/VpnConfigGenerator.java +++ /dev/null @@ -1,146 +0,0 @@ -/** - * 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 . - */ -package se.leap.bitmaskclient; - -import android.content.SharedPreferences; -import android.util.Log; -import java.util.Iterator; -import java.util.Vector; -import org.json.JSONArray; -import org.json.JSONObject; -import org.json.JSONException; - -import se.leap.bitmaskclient.Provider; -import se.leap.bitmaskclient.EIP; - -public class VpnConfigGenerator { - - private JSONObject general_configuration; - private JSONObject gateway; - - private static SharedPreferences preferences; - public final static String TAG = VpnConfigGenerator.class.getSimpleName(); - private final String new_line = System.getProperty("line.separator"); // Platform new line - - public VpnConfigGenerator(SharedPreferences preferences, JSONObject general_configuration, JSONObject gateway) { - this.general_configuration = general_configuration; - this.gateway = gateway; - this.preferences = preferences; - } - - public String generate() { - return - generalConfiguration() - + new_line - + gatewayConfiguration() - + new_line - + secretsConfiguration() - + new_line - + androidCustomizations(); - } - - private String generalConfiguration() { - String common_options = ""; - try { - Iterator keys = general_configuration.keys(); - Vector> value = new Vector>(); - 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 remote = "ip_address"; - String remote_openvpn_keyword = "remote"; - String ports = "ports"; - String protos = "protocols"; - String capabilities = "capabilities"; - String udp = "udp"; - - try { - JSONArray protocolsJSON = gateway.getJSONObject(capabilities).getJSONArray(protos); - for ( int i=0; i" - + new_line - + preferences.getString(Provider.CA_CERT, "") - + new_line - + ""; - - String key = - "" - + new_line - + preferences.getString(EIP.PRIVATE_KEY, "") - + new_line - + ""; - - String openvpn_cert = - "" - + new_line - + preferences.getString(EIP.CERTIFICATE, "") - + new_line - + ""; - - return ca + new_line + key + new_line + openvpn_cert; - } - - private String androidCustomizations() { - return - "remote-cert-tls server" - + new_line - + "persist-tun" - + new_line - + "auth-retry nointeract"; - } -} diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java new file mode 100644 index 00000000..719fff6d --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java @@ -0,0 +1,50 @@ +/** + * 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 . + */ +package se.leap.bitmaskclient.eip; + +/** + * + * Constants for intent passing, shared preferences + * + * @author Parménides GV + * + */ +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"; + public final static String ACTION_UPDATE_EIP_SERVICE = TAG + ".UPDATE_EIP_SERVICE"; + public final static String ACTION_IS_EIP_RUNNING = TAG + ".IS_RUNNING"; + public final static String ACTION_REBUILD_PROFILES = TAG + ".REBUILD_PROFILES"; + public final static String EIP_NOTIFICATION = TAG + ".EIP_NOTIFICATION"; + public final static String STATUS = TAG + ".STATUS"; + public final static String DATE_FROM_CERTIFICATE = TAG + ".DATE_FROM_CERTIFICATE"; + public final static String ALLOWED_ANON = TAG + ".ALLOW_ANONYMOUS"; + public final static String ALLOWED_REGISTERED = TAG + ".ALLOW_REGISTRATION"; + public final static String CERTIFICATE = TAG + ".CERTIFICATE"; + public final static String PRIVATE_KEY = TAG + ".PRIVATE_KEY"; + public final static String KEY = TAG + ".KEY"; + public final static String PARSED_SERIAL = TAG + ".PARSED_SERIAL"; + public final static String RECEIVER_TAG = TAG + ".RECEIVER_TAG"; + public final static String REQUEST_TAG = TAG + ".REQUEST_TAG"; + public final static String START_BLOCKING_VPN_PROFILE = TAG + ".START_BLOCKING_VPN_PROFILE"; + +} diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java new file mode 100644 index 00000000..b668ce64 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -0,0 +1,486 @@ +/** + * 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 . + */ +package se.leap.bitmaskclient.eip; + +import android.app.*; +import android.content.*; +import android.os.*; +import android.util.Log; +import java.io.*; +import java.security.cert.*; +import java.text.*; +import java.util.*; +import org.json.*; + +import de.blinkt.openvpn.*; +import de.blinkt.openvpn.activities.*; +import de.blinkt.openvpn.core.*; +import se.leap.bitmaskclient.*; + +import static se.leap.bitmaskclient.eip.Constants.*; + +/** + * EIP is the abstract base class for interacting with and managing the Encrypted + * Internet Proxy connection. Connections are started, stopped, and queried through + * 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 + * @author Parménides GV + */ +public final class EIP extends IntentService { + + public final static String TAG = EIP.class.getSimpleName(); + + public final static String SERVICE_API_PATH = "config/eip-service.json"; + + private static SharedPreferences preferences; + + private static Context context; + private static ResultReceiver mReceiver; + private static boolean mBound = false; + + private static JSONObject eipDefinition = null; + + private static OVPNGateway activeGateway = null; + + public static VpnStatus.ConnectionStatus lastConnectionStatusLevel; + public static boolean mIsDisconnecting = false; + public static boolean mIsStarting = false; + + public static SimpleDateFormat certificate_date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US); + + public EIP(){ + super("LEAPEIP"); + } + + @Override + public void onCreate() { + super.onCreate(); + + context = getApplicationContext(); + + preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); + } + + @Override + public void onDestroy() { + + mBound = false; + + super.onDestroy(); + } + + + @Override + protected void onHandleIntent(Intent intent) { + String action = intent.getAction(); + mReceiver = intent.getParcelableExtra(RECEIVER_TAG); + + if ( action == ACTION_START_EIP ) + startEIP(); + else if ( action == ACTION_STOP_EIP ) + stopEIP(); + else if ( action == ACTION_IS_EIP_RUNNING ) + isRunning(); + else if ( action == ACTION_UPDATE_EIP_SERVICE ) + updateEIPService(); + else if ( action == ACTION_CHECK_CERT_VALIDITY ) + checkCertValidity(); + else if ( action == ACTION_REBUILD_PROFILES ) + updateGateways(); + } + + /** + * Initiates an EIP connection by selecting a gateway and preparing and sending an + * Intent to {@link se.leap.openvpn.LaunchVPN}. + * It also sets up early routes. + */ + private void startEIP() { + earlyRoutes(); + activeGateway = selectGateway(); + + if(activeGateway != null && activeGateway.mVpnProfile != null) { + mReceiver = EipServiceFragment.getReceiver(); + launchActiveGateway(); + } + } + + /** + * Early routes are routes that block traffic until a new + * 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); + } + + /** + * Choose a gateway to connect to based on timezone from system locale data + * + * @return The gateway to connect to + */ + private OVPNGateway selectGateway() { + String closest_location = closestGateway(); + String chosen_host = chooseHost(closest_location); + + return new OVPNGateway(chosen_host); + } + + private String closestGateway() { + TreeMap> offsets = calculateOffsets(); + return offsets.isEmpty() ? "" : offsets.firstEntry().getValue().iterator().next(); + } + + private TreeMap> calculateOffsets() { + TreeMap> offsets = new TreeMap>(); + + int localOffset = Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000; + + JSONObject locations = availableLocations(); + Iterator locations_names = locations.keys(); + while(locations_names.hasNext()) { + try { + String location_name = locations_names.next(); + JSONObject location = locations.getJSONObject(location_name); + + int dist = timezoneDistance(localOffset, location.optInt("timezone")); + + Set set = (offsets.get(dist) != null) ? + offsets.get(dist) : new HashSet(); + + set.add(location_name); + offsets.put(dist, set); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + return offsets; + } + + private JSONObject availableLocations() { + JSONObject locations = null; + try { + if(eipDefinition == null) updateEIPService(); + locations = eipDefinition.getJSONObject("locations"); + } catch (JSONException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + return locations; + } + + 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; + } + + private String chooseHost(String location) { + String chosen_host = ""; + try { + JSONArray gateways = eipDefinition.getJSONArray("gateways"); + for (int i = 0; i < gateways.length(); i++) { + JSONObject gw = gateways.getJSONObject(i); + if ( gw.getString("location").equalsIgnoreCase(location) || location.isEmpty()){ + chosen_host = eipDefinition.getJSONObject("locations").getJSONObject(gw.getString("location")).getString("name"); + break; + } + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return chosen_host; + } + + 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); + } + + /** + * 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(isConnected()) { + Intent disconnect_vpn = new Intent(this, DisconnectVPN.class); + disconnect_vpn.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(disconnect_vpn); + mIsDisconnecting = true; + lastConnectionStatusLevel = VpnStatus.ConnectionStatus.UNKNOWN_LEVEL; // Wait for the decision of the user + Log.d(TAG, "mIsDisconnecting = true"); + } + + tellToReceiver(ACTION_STOP_EIP, Activity.RESULT_OK); + } + + private void tellToReceiver(String action, int resultCode) { + if (mReceiver != null){ + Bundle resultData = new Bundle(); + resultData.putString(REQUEST_TAG, action); + mReceiver.send(resultCode, resultData); + } + } + + /** + * Checks the last stored status notified by ics-openvpn + * Sends Activity.RESULT_CANCELED to the ResultReceiver that made the + * request if it's not connected, Activity.RESULT_OK otherwise. + */ + + private void isRunning() { + int resultCode = Activity.RESULT_CANCELED; + boolean is_connected = isConnected(); + + resultCode = (is_connected) ? Activity.RESULT_OK : Activity.RESULT_CANCELED; + + tellToReceiver(ACTION_IS_EIP_RUNNING, resultCode); + } + + public static boolean isConnected() { + return lastConnectionStatusLevel != null && lastConnectionStatusLevel.equals(VpnStatus.ConnectionStatus.LEVEL_CONNECTED) && !mIsDisconnecting; + } + + /** + * Loads eip-service.json from SharedPreferences and calls {@link updateGateways()} + * to parse gateway definitions. + * TODO Implement API call to refresh eip-service.json from the provider + */ + private void updateEIPService() { + try { + String eip_definition_string = preferences.getString(KEY, ""); + if(eip_definition_string.isEmpty() == false) { + eipDefinition = new JSONObject(eip_definition_string); + } + deleteAllVpnProfiles(); + updateGateways(); + if(mReceiver != null) mReceiver.send(Activity.RESULT_OK, Bundle.EMPTY); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + private void deleteAllVpnProfiles() { + ProfileManager vpl = ProfileManager.getInstance(context); + Collection profiles = vpl.getProfiles(); + profiles.removeAll(profiles); + } + + /** + * Walk the list of gateways defined in eip-service.json and parse them into + * OVPNGateway objects. + * TODO Store the OVPNGateways (as Serializable) in SharedPreferences + */ + private void updateGateways(){ + JSONArray gatewaysDefined = null; + try { + if(eipDefinition == null) updateEIPService(); + gatewaysDefined = eipDefinition.getJSONArray("gateways"); + for ( int i=0 ; i < gatewaysDefined.length(); i++ ){ + JSONObject gw = null; + gw = gatewaysDefined.getJSONObject(i); + + if ( gw.getJSONObject("capabilities").getJSONArray("transport").toString().contains("openvpn") ) + new OVPNGateway(gw); + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + preferences.edit().putInt(PARSED_SERIAL, eipDefinition.optInt(Provider.API_RETURN_SERIAL)).commit(); + } + + private void checkCertValidity() { + String certificate = preferences.getString(CERTIFICATE, ""); + checkCertValidity(certificate); + } + + private void checkCertValidity(String certificate_string) { + if(!certificate_string.isEmpty()) { + X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(certificate_string); + + Calendar offset_date = calculateOffsetCertificateValidity(certificate); + Bundle result = new Bundle(); + result.putString(REQUEST_TAG, ACTION_CHECK_CERT_VALIDITY); + try { + Log.d(TAG, "offset_date = " + offset_date.getTime().toString()); + certificate.checkValidity(offset_date.getTime()); + mReceiver.send(Activity.RESULT_OK, result); + Log.d(TAG, "Valid certificate"); + } catch(CertificateExpiredException e) { + mReceiver.send(Activity.RESULT_CANCELED, result); + Log.d(TAG, "Updating certificate"); + } catch(CertificateNotYetValidException e) { + mReceiver.send(Activity.RESULT_CANCELED, result); + } + } + } + + private Calendar calculateOffsetCertificateValidity(X509Certificate certificate) { + String current_date = certificate_date_format.format(Calendar.getInstance().getTime()).toString(); + + String date_string = preferences.getString(DATE_FROM_CERTIFICATE, current_date); + + Calendar offset_date = Calendar.getInstance(); + try { + Date date = certificate_date_format.parse(date_string); + long difference = Math.abs(date.getTime() - certificate.getNotAfter().getTime())/2; + long current_date_millis = offset_date.getTimeInMillis(); + offset_date.setTimeInMillis(current_date_millis + difference); + Log.d(TAG, "certificate not after = " + certificate.getNotAfter()); + } catch(ParseException e) { + e.printStackTrace(); + } + + return offset_date; + } + + /** + * OVPNGateway provides objects defining gateways and their options and metadata. + * Each instance contains a VpnProfile for OpenVPN specific data and member + * variables describing capabilities and location + * + * @author Sean Leonard + */ + private class OVPNGateway { + + private String TAG = "OVPNGateway"; + + private String mName; + private VpnProfile mVpnProfile; + private JSONObject mGateway; + private HashMap>> options = new HashMap>>(); + + + /** + * Attempts to retrieve a VpnProfile by name and build an OVPNGateway around it. + * FIXME This needs to become a findGatewayByName() method + * + * @param name The hostname of the gateway to inflate + */ + private OVPNGateway(String name){ + mName = name; + + this.loadVpnProfile(); + } + + private void loadVpnProfile() { + ProfileManager vpl = ProfileManager.getInstance(context); + try { + if ( mName == null ) + mVpnProfile = vpl.getProfiles().iterator().next(); + else + mVpnProfile = vpl.getProfileByName(mName); + } catch (NoSuchElementException e) { + updateEIPService(); + this.loadVpnProfile(); // FIXME catch infinite loops + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json + * and create a VpnProfile belonging to it. + * + * @param gateway The JSON OpenVPN gateway definition to parse + */ + protected OVPNGateway(JSONObject gateway){ + + mGateway = gateway; + + // Currently deletes VpnProfile for host, if there already is one, and builds new + ProfileManager vpl = ProfileManager.getInstance(context); + Collection profiles = vpl.getProfiles(); + for (Iterator it = profiles.iterator(); it.hasNext(); ){ + VpnProfile p = it.next(); + + if ( p.mName.equalsIgnoreCase( mName ) ) { + it.remove(); + vpl.removeProfile(context, p); + } + } + + this.createVPNProfile(); + + vpl.addProfile(mVpnProfile); + vpl.saveProfile(context, mVpnProfile); + vpl.saveProfileList(context); + } + + /** + * Create and attach the VpnProfile to our gateway object + */ + protected void createVPNProfile(){ + try { + ConfigParser cp = new ConfigParser(); + + JSONObject openvpn_configuration = eipDefinition.getJSONObject("openvpn_configuration"); + VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(preferences, openvpn_configuration, mGateway); + String configuration = vpn_configuration_generator.generate(); + + cp.parseConfig(new StringReader(configuration)); + mVpnProfile = cp.convertProfile(); + mVpnProfile.mName = mName = locationAsName(); + Log.v(TAG,"Created VPNProfile"); + + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ConfigParser.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/eip/VoidVpnLauncher.java b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java new file mode 100644 index 00000000..9814c167 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java @@ -0,0 +1,37 @@ +package se.leap.bitmaskclient.eip; + +import android.app.Activity; +import android.content.Intent; +import android.net.VpnService; +import android.os.Bundle; + +public class VoidVpnLauncher extends Activity { + + private static final int VPN_USER_PERMISSION = 71; + + @Override + protected void onCreate(Bundle savedInstanceState) { + 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); + } + } + + 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 new file mode 100644 index 00000000..224e3bd4 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java @@ -0,0 +1,37 @@ +package se.leap.bitmaskclient.eip; + +import android.content.Intent; +import android.os.Process; +import android.net.VpnService; +import android.util.Log; + +import static se.leap.bitmaskclient.eip.Constants.*; + +public class VoidVpnService extends VpnService { + + static final String TAG = VoidVpnService.class.getSimpleName(); + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + String action = 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 { + builder.establish(); + } catch (Exception e) { + e.printStackTrace(); + } + android.util.Log.d(TAG, "VoidVpnService set up"); + } + }).run(); + } + return 0; + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java new file mode 100644 index 00000000..8e36f53c --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -0,0 +1,145 @@ +/** + * 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 . + */ +package se.leap.bitmaskclient.eip; + +import android.content.SharedPreferences; +import android.util.Log; +import java.util.Iterator; +import java.util.Vector; +import org.json.JSONArray; +import org.json.JSONObject; +import org.json.JSONException; + +import se.leap.bitmaskclient.*; + +public class VpnConfigGenerator { + + private JSONObject general_configuration; + private JSONObject gateway; + + private static SharedPreferences preferences; + public final static String TAG = VpnConfigGenerator.class.getSimpleName(); + private final String new_line = System.getProperty("line.separator"); // Platform new line + + public VpnConfigGenerator(SharedPreferences preferences, JSONObject general_configuration, JSONObject gateway) { + this.general_configuration = general_configuration; + this.gateway = gateway; + this.preferences = preferences; + } + + public String generate() { + return + generalConfiguration() + + new_line + + gatewayConfiguration() + + new_line + + secretsConfiguration() + + new_line + + androidCustomizations(); + } + + private String generalConfiguration() { + String common_options = ""; + try { + Iterator keys = general_configuration.keys(); + Vector> value = new Vector>(); + 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 remote = "ip_address"; + String remote_openvpn_keyword = "remote"; + String ports = "ports"; + String protos = "protocols"; + String capabilities = "capabilities"; + String udp = "udp"; + + try { + JSONArray protocolsJSON = gateway.getJSONObject(capabilities).getJSONArray(protos); + for ( int i=0; i" + + new_line + + preferences.getString(Provider.CA_CERT, "") + + new_line + + ""; + + String key = + "" + + new_line + + preferences.getString(Constants.PRIVATE_KEY, "") + + new_line + + ""; + + String openvpn_cert = + "" + + new_line + + preferences.getString(Constants.CERTIFICATE, "") + + new_line + + ""; + + return ca + new_line + key + new_line + openvpn_cert; + } + + private String androidCustomizations() { + return + "remote-cert-tls server" + + new_line + + "persist-tun" + + new_line + + "auth-retry nointeract"; + } +} -- cgit v1.2.3 From b8087831f7db9fbc7806c58e632bda448b3b9e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 12 Nov 2014 03:44:14 +0100 Subject: More refactoring, fixed problems from previous commit. --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 31 ++-- .../java/se/leap/bitmaskclient/eip/Constants.java | 6 +- .../main/java/se/leap/bitmaskclient/eip/EIP.java | 182 +++++---------------- .../bitmaskclient/eip/VpnCertificateValidator.java | 59 +++++++ 4 files changed, 116 insertions(+), 162 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 473cd5ec..e4e575e4 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -42,6 +42,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf protected static final int CONFIGURE_LEAP = 0; protected static final int SWITCH_PROVIDER = 1; + final public static String TAG = Dashboard.class.getSimpleName(); final public static String SHARED_PREFERENCES = "LEAPPreferences"; final public static String ACTION_QUIT = "quit"; public static final String REQUEST_CODE = "request_code"; @@ -49,21 +50,19 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf 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"; - final public static String TAG = Dashboard.class.getSimpleName(); - + private static Context app; + protected static SharedPreferences preferences; + private FragmentManagerEnhanced fragment_manager; + private EipServiceFragment eipFragment; - private ProgressBar mProgressBar; - private TextView eipStatus; - private static Context app; - protected static SharedPreferences preferences; - private static Provider provider; - - private boolean authed_eip = false; - + private ProgressBar mProgressBar; + private TextView eipStatus; public ProviderAPIResultReceiver providerAPI_result_receiver; - private FragmentManagerEnhanced fragment_manager; + private static Provider provider; + private static boolean authed_eip; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -78,11 +77,11 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf fragment_manager = new FragmentManagerEnhanced(getFragmentManager()); handleVersion(); - authed_eip = preferences.getBoolean(Constants.AUTHED_EIP, false); - if (preferences.getString(Provider.KEY, "").isEmpty()) - startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP); - else - buildDashboard(getIntent().getBooleanExtra(ON_BOOT, false)); + boolean provider_configured = preferences.getString(Constants.KEY, "").isEmpty(); + if (provider_configured) + startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP); + else + buildDashboard(getIntent().getBooleanExtra(ON_BOOT, false)); } private void handleVersion() { 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 719fff6d..3b43282b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java @@ -37,9 +37,9 @@ public interface Constants { public final static String EIP_NOTIFICATION = TAG + ".EIP_NOTIFICATION"; public final static String STATUS = TAG + ".STATUS"; public final static String DATE_FROM_CERTIFICATE = TAG + ".DATE_FROM_CERTIFICATE"; - public final static String ALLOWED_ANON = TAG + ".ALLOW_ANONYMOUS"; - public final static String ALLOWED_REGISTERED = TAG + ".ALLOW_REGISTRATION"; - public final static String CERTIFICATE = TAG + ".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 = TAG + ".PRIVATE_KEY"; public final static String KEY = TAG + ".KEY"; public final static String PARSED_SERIAL = TAG + ".PARSED_SERIAL"; 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 b668ce64..92eba23c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -51,20 +51,19 @@ public final class EIP extends IntentService { private static SharedPreferences preferences; - private static Context context; - private static ResultReceiver mReceiver; - private static boolean mBound = false; + private static Context context; + private static ResultReceiver mReceiver; + private static boolean mBound = false; - private static JSONObject eipDefinition = null; + private static int parsedEipSerial; + private static JSONObject eip_definition = null; - private static OVPNGateway activeGateway = null; + private static OVPNGateway activeGateway = null; public static VpnStatus.ConnectionStatus lastConnectionStatusLevel; public static boolean mIsDisconnecting = false; public static boolean mIsStarting = false; - public static SimpleDateFormat certificate_date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US); - public EIP(){ super("LEAPEIP"); } @@ -76,6 +75,7 @@ public final class EIP extends IntentService { context = getApplicationContext(); preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); + refreshEipDefinition(); } @Override @@ -113,8 +113,10 @@ public final class EIP extends IntentService { */ private void startEIP() { earlyRoutes(); - activeGateway = selectGateway(); - + GatewaySelector gateway_selector = new GatewaySelector(eip_definition); + String selected_gateway = gateway_selector.select(); + + activeGateway = new OVPNGateway(selected_gateway); if(activeGateway != null && activeGateway.mVpnProfile != null) { mReceiver = EipServiceFragment.getReceiver(); launchActiveGateway(); @@ -131,93 +133,6 @@ public final class EIP extends IntentService { startActivity(void_vpn_launcher); } - /** - * Choose a gateway to connect to based on timezone from system locale data - * - * @return The gateway to connect to - */ - private OVPNGateway selectGateway() { - String closest_location = closestGateway(); - String chosen_host = chooseHost(closest_location); - - return new OVPNGateway(chosen_host); - } - - private String closestGateway() { - TreeMap> offsets = calculateOffsets(); - return offsets.isEmpty() ? "" : offsets.firstEntry().getValue().iterator().next(); - } - - private TreeMap> calculateOffsets() { - TreeMap> offsets = new TreeMap>(); - - int localOffset = Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000; - - JSONObject locations = availableLocations(); - Iterator locations_names = locations.keys(); - while(locations_names.hasNext()) { - try { - String location_name = locations_names.next(); - JSONObject location = locations.getJSONObject(location_name); - - int dist = timezoneDistance(localOffset, location.optInt("timezone")); - - Set set = (offsets.get(dist) != null) ? - offsets.get(dist) : new HashSet(); - - set.add(location_name); - offsets.put(dist, set); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - return offsets; - } - - private JSONObject availableLocations() { - JSONObject locations = null; - try { - if(eipDefinition == null) updateEIPService(); - locations = eipDefinition.getJSONObject("locations"); - } catch (JSONException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - - return locations; - } - - 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; - } - - private String chooseHost(String location) { - String chosen_host = ""; - try { - JSONArray gateways = eipDefinition.getJSONArray("gateways"); - for (int i = 0; i < gateways.length(); i++) { - JSONObject gw = gateways.getJSONObject(i); - if ( gw.getString("location").equalsIgnoreCase(location) || location.isEmpty()){ - chosen_host = eipDefinition.getJSONObject("locations").getJSONObject(gw.getString("location")).getString("name"); - break; - } - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return chosen_host; - } - private void launchActiveGateway() { Intent intent = new Intent(this,LaunchVPN.class); intent.setAction(Intent.ACTION_MAIN); @@ -292,7 +207,22 @@ public final class EIP extends IntentService { e.printStackTrace(); } } + if (eip_definition != null && eip_definition.optInt("serial") >= parsedEipSerial) + updateGateways(); + } + private void refreshEipDefinition() { + try { + String eip_definition_string = preferences.getString(KEY, ""); + if(!eip_definition_string.isEmpty()) { + eip_definition = new JSONObject(eip_definition_string); + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + private void deleteAllVpnProfiles() { ProfileManager vpl = ProfileManager.getInstance(context); Collection profiles = vpl.getProfiles(); @@ -307,8 +237,8 @@ public final class EIP extends IntentService { private void updateGateways(){ JSONArray gatewaysDefined = null; try { - if(eipDefinition == null) updateEIPService(); - gatewaysDefined = eipDefinition.getJSONArray("gateways"); + if(eip_definition == null) updateEIPService(); + gatewaysDefined = eip_definition.getJSONArray("gateways"); for ( int i=0 ; i < gatewaysDefined.length(); i++ ){ JSONObject gw = null; gw = gatewaysDefined.getJSONObject(i); @@ -320,52 +250,18 @@ public final class EIP extends IntentService { // TODO Auto-generated catch block e.printStackTrace(); } - preferences.edit().putInt(PARSED_SERIAL, eipDefinition.optInt(Provider.API_RETURN_SERIAL)).commit(); + preferences.edit().putInt(PARSED_SERIAL, eip_definition.optInt(Provider.API_RETURN_SERIAL)).commit(); } private void checkCertValidity() { - String certificate = preferences.getString(CERTIFICATE, ""); - checkCertValidity(certificate); - } - - private void checkCertValidity(String certificate_string) { - if(!certificate_string.isEmpty()) { - X509Certificate certificate = ConfigHelper.parseX509CertificateFromString(certificate_string); - - Calendar offset_date = calculateOffsetCertificateValidity(certificate); - Bundle result = new Bundle(); - result.putString(REQUEST_TAG, ACTION_CHECK_CERT_VALIDITY); - try { - Log.d(TAG, "offset_date = " + offset_date.getTime().toString()); - certificate.checkValidity(offset_date.getTime()); - mReceiver.send(Activity.RESULT_OK, result); - Log.d(TAG, "Valid certificate"); - } catch(CertificateExpiredException e) { - mReceiver.send(Activity.RESULT_CANCELED, result); - Log.d(TAG, "Updating certificate"); - } catch(CertificateNotYetValidException e) { - mReceiver.send(Activity.RESULT_CANCELED, result); - } - } - } - - private Calendar calculateOffsetCertificateValidity(X509Certificate certificate) { - String current_date = certificate_date_format.format(Calendar.getInstance().getTime()).toString(); - - String date_string = preferences.getString(DATE_FROM_CERTIFICATE, current_date); - - Calendar offset_date = Calendar.getInstance(); - try { - Date date = certificate_date_format.parse(date_string); - long difference = Math.abs(date.getTime() - certificate.getNotAfter().getTime())/2; - long current_date_millis = offset_date.getTimeInMillis(); - offset_date.setTimeInMillis(current_date_millis + difference); - Log.d(TAG, "certificate not after = " + certificate.getNotAfter()); - } catch(ParseException e) { - e.printStackTrace(); - } - - return offset_date; + Bundle result = new Bundle(); + result.putString(REQUEST_TAG, ACTION_CHECK_CERT_VALIDITY); + + VpnCertificateValidator validator = new VpnCertificateValidator(); + if(validator.isValid(preferences.getString(CERTIFICATE, ""))) + mReceiver.send(Activity.RESULT_OK, result); + else + mReceiver.send(Activity.RESULT_CANCELED, result); } /** @@ -449,7 +345,7 @@ public final class EIP extends IntentService { try { ConfigParser cp = new ConfigParser(); - JSONObject openvpn_configuration = eipDefinition.getJSONObject("openvpn_configuration"); + JSONObject openvpn_configuration = eip_definition.getJSONObject("openvpn_configuration"); VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(preferences, openvpn_configuration, mGateway); String configuration = vpn_configuration_generator.generate(); @@ -475,7 +371,7 @@ public final class EIP extends IntentService { public String locationAsName() { try { - return eipDefinition.getJSONObject("locations").getJSONObject(mGateway.getString("location")).getString("name"); + return eip_definition.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(); diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java new file mode 100644 index 00000000..a5f04368 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java @@ -0,0 +1,59 @@ +/** + * 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 . + */ +package se.leap.bitmaskclient.eip; + +import android.util.Log; +import java.util.*; +import java.security.cert.*; +import java.text.*; + +import se.leap.bitmaskclient.ConfigHelper; +import static se.leap.bitmaskclient.eip.Constants.*; + +public class VpnCertificateValidator { + public final static String TAG = VpnCertificateValidator.class.getSimpleName(); + + public boolean isValid(String certificate) { + if(!certificate.isEmpty()) { + X509Certificate certificate_x509 = ConfigHelper.parseX509CertificateFromString(certificate); + return isValid(certificate_x509); + } else return false; + } + + 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; + } + } + + 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; + } +} -- cgit v1.2.3 From 1fcf003abf27b58047d59a3f8ac4787987de2ecd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 12 Nov 2014 03:58:03 +0100 Subject: Smaller method. --- app/src/main/java/se/leap/bitmaskclient/eip/EIP.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'app/src/main/java') 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 92eba23c..94027491 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -73,7 +73,6 @@ public final class EIP extends IntentService { super.onCreate(); context = getApplicationContext(); - preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); refreshEipDefinition(); } @@ -254,14 +253,9 @@ public final class EIP extends IntentService { } private void checkCertValidity() { - Bundle result = new Bundle(); - result.putString(REQUEST_TAG, ACTION_CHECK_CERT_VALIDITY); - VpnCertificateValidator validator = new VpnCertificateValidator(); - if(validator.isValid(preferences.getString(CERTIFICATE, ""))) - mReceiver.send(Activity.RESULT_OK, result); - else - mReceiver.send(Activity.RESULT_CANCELED, result); + boolean is_valid = validator.isValid(preferences.getString(CERTIFICATE, "")); + tellToReceiver(ACTION_CHECK_CERT_VALIDITY, is_valid); } /** -- cgit v1.2.3 From ba3362c6779e3b89533b1a132d67b4916a9976d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 13 Nov 2014 19:22:35 +0100 Subject: GatewaySelector is back. Had to rewrite the class, forgot to add the java file to git. --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 2 +- .../java/se/leap/bitmaskclient/eip/Constants.java | 1 - .../main/java/se/leap/bitmaskclient/eip/EIP.java | 82 +++++++++------------- 3 files changed, 36 insertions(+), 49 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index e4e575e4..395e9987 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -97,7 +97,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf case 101: // 0.8.0 if(!preferences.getString(Constants.KEY, "").isEmpty()) { Intent rebuildVpnProfiles = new Intent(getApplicationContext(), EIP.class); - rebuildVpnProfiles.setAction(Constants.ACTION_REBUILD_PROFILES); + rebuildVpnProfiles.setAction(Constants.ACTION_UPDATE_EIP_SERVICE); startService(rebuildVpnProfiles); } break; 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 3b43282b..b710d780 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java @@ -33,7 +33,6 @@ public interface Constants { public final static String ACTION_STOP_EIP = TAG + ".STOP_EIP"; public final static String ACTION_UPDATE_EIP_SERVICE = TAG + ".UPDATE_EIP_SERVICE"; public final static String ACTION_IS_EIP_RUNNING = TAG + ".IS_RUNNING"; - public final static String ACTION_REBUILD_PROFILES = TAG + ".REBUILD_PROFILES"; public final static String EIP_NOTIFICATION = TAG + ".EIP_NOTIFICATION"; public final static String STATUS = TAG + ".STATUS"; public final static String DATE_FROM_CERTIFICATE = TAG + ".DATE_FROM_CERTIFICATE"; 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 94027491..2b9f120d 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -101,8 +101,6 @@ public final class EIP extends IntentService { updateEIPService(); else if ( action == ACTION_CHECK_CERT_VALIDITY ) checkCertValidity(); - else if ( action == ACTION_REBUILD_PROFILES ) - updateGateways(); } /** @@ -175,39 +173,28 @@ public final class EIP extends IntentService { */ private void isRunning() { - int resultCode = Activity.RESULT_CANCELED; - boolean is_connected = isConnected(); - - resultCode = (is_connected) ? Activity.RESULT_OK : Activity.RESULT_CANCELED; - + int resultCode = (isConnected()) ? + Activity.RESULT_OK : + Activity.RESULT_CANCELED; tellToReceiver(ACTION_IS_EIP_RUNNING, resultCode); } public static boolean isConnected() { - return lastConnectionStatusLevel != null && lastConnectionStatusLevel.equals(VpnStatus.ConnectionStatus.LEVEL_CONNECTED) && !mIsDisconnecting; + return lastConnectionStatusLevel != null + && lastConnectionStatusLevel.equals(VpnStatus.ConnectionStatus.LEVEL_CONNECTED) + && !mIsDisconnecting; } - /** - * Loads eip-service.json from SharedPreferences and calls {@link updateGateways()} - * to parse gateway definitions. - * TODO Implement API call to refresh eip-service.json from the provider - */ - private void updateEIPService() { - try { - String eip_definition_string = preferences.getString(KEY, ""); - if(eip_definition_string.isEmpty() == false) { - eipDefinition = new JSONObject(eip_definition_string); - } - deleteAllVpnProfiles(); - updateGateways(); - if(mReceiver != null) mReceiver.send(Activity.RESULT_OK, Bundle.EMPTY); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - if (eip_definition != null && eip_definition.optInt("serial") >= parsedEipSerial) - updateGateways(); + /** + * Loads eip-service.json from SharedPreferences and calls {@link updateGateways()} + * to parse gateway definitions. + * TODO Implement API call to refresh eip-service.json from the provider + */ + private void updateEIPService() { + refreshEipDefinition(); + deleteAllVpnProfiles(); + updateGateways(); + if(mReceiver != null) mReceiver.send(Activity.RESULT_OK, Bundle.EMPTY); } private void refreshEipDefinition() { @@ -233,29 +220,30 @@ public final class EIP extends IntentService { * OVPNGateway objects. * TODO Store the OVPNGateways (as Serializable) in SharedPreferences */ - private void updateGateways(){ - JSONArray gatewaysDefined = null; - try { - if(eip_definition == null) updateEIPService(); - gatewaysDefined = eip_definition.getJSONArray("gateways"); - for ( int i=0 ; i < gatewaysDefined.length(); i++ ){ - JSONObject gw = null; - gw = gatewaysDefined.getJSONObject(i); + private void updateGateways(){ + JSONArray gatewaysDefined = null; + try { + gatewaysDefined = eip_definition.getJSONArray("gateways"); + for ( int i=0 ; i < gatewaysDefined.length(); i++ ){ + JSONObject gw = null; + gw = gatewaysDefined.getJSONObject(i); - if ( gw.getJSONObject("capabilities").getJSONArray("transport").toString().contains("openvpn") ) - new OVPNGateway(gw); - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - preferences.edit().putInt(PARSED_SERIAL, eip_definition.optInt(Provider.API_RETURN_SERIAL)).commit(); + if ( gw.getJSONObject("capabilities").getJSONArray("transport").toString().contains("openvpn") ) + new OVPNGateway(gw); + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); } + preferences.edit().putInt(PARSED_SERIAL, eip_definition.optInt(Provider.API_RETURN_SERIAL)).commit(); + } private void checkCertValidity() { VpnCertificateValidator validator = new VpnCertificateValidator(); - boolean is_valid = validator.isValid(preferences.getString(CERTIFICATE, "")); - tellToReceiver(ACTION_CHECK_CERT_VALIDITY, is_valid); + int resultCode = validator.isValid(preferences.getString(CERTIFICATE, "")) ? + Activity.RESULT_OK : + Activity.RESULT_CANCELED; + tellToReceiver(ACTION_CHECK_CERT_VALIDITY, resultCode); } /** -- cgit v1.2.3 From 301adeab4b1630645e53baa982b35cba394e52b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 17 Nov 2014 18:44:36 +0100 Subject: Update vpn certificate and store it correctly. One more onReceiveResult for Dashboard, that method needs a rethink: a statemachine class, and a simple "next()" method? The reality is that the onReceiveResult specifies a linked process, and that should have a better model than a series of if/else cases with strings comparisons hehehe --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 36 ++++++++++++---------- .../main/java/se/leap/bitmaskclient/eip/EIP.java | 2 +- 2 files changed, 21 insertions(+), 17 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 395e9987..b139f73f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -433,22 +433,8 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf hideProgressBar(); setResult(RESULT_OK); - Intent updateEIP = new Intent(getApplicationContext(), EIP.class); - ResultReceiver eip_receiver = new ResultReceiver(new Handler()){ - protected void onReceiveResult(int resultCode, Bundle resultData){ - super.onReceiveResult(resultCode, resultData); - String request = resultData.getString(Constants.REQUEST_TAG); - if (resultCode == Activity.RESULT_OK){ - if(authed_eip) - eipStart(); - else - eipStatus.setText("Certificate updated"); - } - } - }; - updateEIP.putExtra(Constants.RECEIVER_TAG, eip_receiver); - updateEIP.setAction(Constants.ACTION_UPDATE_EIP_SERVICE); - startService(updateEIP); + + updateEipService(); } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) { changeStatusMessage(resultCode); hideProgressBar(); @@ -456,6 +442,24 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } } + private void updateEipService() { + Intent updateEIP = new Intent(getApplicationContext(), EIP.class); + updateEIP.setAction(Constants.ACTION_UPDATE_EIP_SERVICE); + ResultReceiver receiver = new ResultReceiver(new Handler()) { + protected void onReceiveResult(int resultCode, Bundle resultData) { + String request = resultData.getString(Constants.REQUEST_TAG); + if(request.equalsIgnoreCase(Constants.ACTION_UPDATE_EIP_SERVICE)) { + if(resultCode == Activity.RESULT_OK) { + if(authed_eip) + eipStart(); + } + } + } + }; + updateEIP.putExtra(Constants.RECEIVER_TAG, receiver); + startService(updateEIP); + } + private void changeStatusMessage(final int previous_result_code) { // TODO Auto-generated method stub ResultReceiver eip_status_receiver = new ResultReceiver(new Handler()){ 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 2b9f120d..9f81f263 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -194,7 +194,7 @@ public final class EIP extends IntentService { refreshEipDefinition(); deleteAllVpnProfiles(); updateGateways(); - if(mReceiver != null) mReceiver.send(Activity.RESULT_OK, Bundle.EMPTY); + tellToReceiver(ACTION_UPDATE_EIP_SERVICE, Activity.RESULT_OK); } private void refreshEipDefinition() { -- cgit v1.2.3 From 5d28fc6602a214da51931e428112825117b2509f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 17 Nov 2014 19:54:51 +0100 Subject: An empty certificate is valid. If there is no certificate, there is no need to fix it. Right now, we use this class just to know if we need to update the certificate or redownload it. In case the certificate is corrupted, then it won't be empty but will contain an error message. If there is no certificate (e.g., because the user hasn't logged in and the provider doesn't provide anon vpn), then the "certificate" is ok but an upper layer of the code will have to handle the situation (in this case, eip will detect that there is no certificate and that the user needs to log in, prompting it to do so). --- .../main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/src/main/java') 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 a5f04368..16ae6a85 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java @@ -31,7 +31,7 @@ public class VpnCertificateValidator { if(!certificate.isEmpty()) { X509Certificate certificate_x509 = ConfigHelper.parseX509CertificateFromString(certificate); return isValid(certificate_x509); - } else return false; + } else return true; } private boolean isValid(X509Certificate certificate) { -- cgit v1.2.3 From 06bc3b1898e1a419693c7fc3d6a48322ad6881e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 17 Nov 2014 22:17:01 +0100 Subject: OVPNGateway extracted from EIP. Fixed a silly typo on .gitignore which was ignoring "G*"!. --- .../openvpn/core/GetRestrictionReceiver.java | 47 ++++++ .../main/java/se/leap/bitmaskclient/eip/EIP.java | 172 +++++---------------- .../java/se/leap/bitmaskclient/eip/Gateway.java | 151 ++++++++++++++++++ .../se/leap/bitmaskclient/eip/GatewaySelector.java | 44 ++++++ 4 files changed, 277 insertions(+), 137 deletions(-) create mode 100644 app/src/main/java/de/blinkt/openvpn/core/GetRestrictionReceiver.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java (limited to 'app/src/main/java') diff --git a/app/src/main/java/de/blinkt/openvpn/core/GetRestrictionReceiver.java b/app/src/main/java/de/blinkt/openvpn/core/GetRestrictionReceiver.java new file mode 100644 index 00000000..5b1dda58 --- /dev/null +++ b/app/src/main/java/de/blinkt/openvpn/core/GetRestrictionReceiver.java @@ -0,0 +1,47 @@ +package de.blinkt.openvpn.core; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.RestrictionEntry; +import android.os.Build; +import android.os.Bundle; + +import java.util.ArrayList; + +import se.leap.bitmaskclient.R; + +/** + * Created by arne on 25.07.13. + */ +@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) +public class GetRestrictionReceiver extends BroadcastReceiver { + @Override + public void onReceive(final Context context, Intent intent) { + final PendingResult result = goAsync(); + + new Thread() { + @Override + public void run() { + final Bundle extras = new Bundle(); + + ArrayList restrictionEntries = initRestrictions(context); + + extras.putParcelableArrayList(Intent.EXTRA_RESTRICTIONS_LIST, restrictionEntries); + result.setResult(Activity.RESULT_OK,null,extras); + result.finish(); + } + }.run(); + } + + private ArrayList initRestrictions(Context context) { + ArrayList restrictions = new ArrayList(); + RestrictionEntry allowChanges = new RestrictionEntry("allow_changes",false); + allowChanges.setTitle(context.getString(R.string.allow_vpn_changes)); + restrictions.add(allowChanges); + + return restrictions; + } +} 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 9f81f263..876ad172 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -58,7 +58,9 @@ public final class EIP extends IntentService { private static int parsedEipSerial; private static JSONObject eip_definition = null; - private static OVPNGateway activeGateway = null; + private static Gateway activeGateway = null; + private static List gateways = new ArrayList(); + ProfileManager profile_manager; public static VpnStatus.ConnectionStatus lastConnectionStatusLevel; public static boolean mIsDisconnecting = false; @@ -73,6 +75,8 @@ public final class EIP extends IntentService { super.onCreate(); context = getApplicationContext(); + profile_manager = ProfileManager.getInstance(context); + preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); refreshEipDefinition(); } @@ -110,11 +114,10 @@ public final class EIP extends IntentService { */ private void startEIP() { earlyRoutes(); - GatewaySelector gateway_selector = new GatewaySelector(eip_definition); - String selected_gateway = gateway_selector.select(); + GatewaySelector gateway_selector = new GatewaySelector(gateways); - activeGateway = new OVPNGateway(selected_gateway); - if(activeGateway != null && activeGateway.mVpnProfile != null) { + activeGateway = gateway_selector.select(); + if(activeGateway != null && activeGateway.getProfile() != null) { mReceiver = EipServiceFragment.getReceiver(); launchActiveGateway(); } @@ -134,8 +137,8 @@ public final class EIP extends IntentService { 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_KEY, activeGateway.getProfile().getUUID().toString() ); + intent.putExtra(LaunchVPN.EXTRA_NAME, activeGateway.getProfile().getName() ); intent.putExtra(LaunchVPN.EXTRA_HIDELOG, true); intent.putExtra(RECEIVER_TAG, mReceiver); startActivity(intent); @@ -210,26 +213,23 @@ public final class EIP extends IntentService { } private void deleteAllVpnProfiles() { - ProfileManager vpl = ProfileManager.getInstance(context); - Collection profiles = vpl.getProfiles(); + Collection profiles = profile_manager.getProfiles(); profiles.removeAll(profiles); } - /** - * Walk the list of gateways defined in eip-service.json and parse them into - * OVPNGateway objects. - * TODO Store the OVPNGateways (as Serializable) in SharedPreferences - */ + /** + * Walk the list of gateways defined in eip-service.json and parse them into + * Gateway objects. + * TODO Store the Gateways (as Serializable) in SharedPreferences + */ private void updateGateways(){ - JSONArray gatewaysDefined = null; try { - gatewaysDefined = eip_definition.getJSONArray("gateways"); + JSONArray gatewaysDefined = eip_definition.getJSONArray("gateways"); for ( int i=0 ; i < gatewaysDefined.length(); i++ ){ - JSONObject gw = null; - gw = gatewaysDefined.getJSONObject(i); - - if ( gw.getJSONObject("capabilities").getJSONArray("transport").toString().contains("openvpn") ) - new OVPNGateway(gw); + JSONObject gw = gatewaysDefined.getJSONObject(i); + if(isOpenVpnGateway(gw)) { + addGateway(new Gateway(eip_definition, context, gw)); + } } } catch (JSONException e) { // TODO Auto-generated catch block @@ -238,6 +238,20 @@ public final class EIP extends IntentService { preferences.edit().putInt(PARSED_SERIAL, eip_definition.optInt(Provider.API_RETURN_SERIAL)).commit(); } + private boolean isOpenVpnGateway(JSONObject gateway) { + try { + String transport = gateway.getJSONObject("capabilities").getJSONArray("transport").toString(); + return transport.contains("openvpn"); + } catch (JSONException e) { + return false; + } + } + + private void addGateway(Gateway gateway) { + profile_manager.addProfile(gateway.getProfile()); + gateways.add(gateway); + } + private void checkCertValidity() { VpnCertificateValidator validator = new VpnCertificateValidator(); int resultCode = validator.isValid(preferences.getString(CERTIFICATE, "")) ? @@ -245,120 +259,4 @@ public final class EIP extends IntentService { Activity.RESULT_CANCELED; tellToReceiver(ACTION_CHECK_CERT_VALIDITY, resultCode); } - - /** - * OVPNGateway provides objects defining gateways and their options and metadata. - * Each instance contains a VpnProfile for OpenVPN specific data and member - * variables describing capabilities and location - * - * @author Sean Leonard - */ - private class OVPNGateway { - - private String TAG = "OVPNGateway"; - - private String mName; - private VpnProfile mVpnProfile; - private JSONObject mGateway; - private HashMap>> options = new HashMap>>(); - - - /** - * Attempts to retrieve a VpnProfile by name and build an OVPNGateway around it. - * FIXME This needs to become a findGatewayByName() method - * - * @param name The hostname of the gateway to inflate - */ - private OVPNGateway(String name){ - mName = name; - - this.loadVpnProfile(); - } - - private void loadVpnProfile() { - ProfileManager vpl = ProfileManager.getInstance(context); - try { - if ( mName == null ) - mVpnProfile = vpl.getProfiles().iterator().next(); - else - mVpnProfile = vpl.getProfileByName(mName); - } catch (NoSuchElementException e) { - updateEIPService(); - this.loadVpnProfile(); // FIXME catch infinite loops - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - /** - * Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json - * and create a VpnProfile belonging to it. - * - * @param gateway The JSON OpenVPN gateway definition to parse - */ - protected OVPNGateway(JSONObject gateway){ - - mGateway = gateway; - - // Currently deletes VpnProfile for host, if there already is one, and builds new - ProfileManager vpl = ProfileManager.getInstance(context); - Collection profiles = vpl.getProfiles(); - for (Iterator it = profiles.iterator(); it.hasNext(); ){ - VpnProfile p = it.next(); - - if ( p.mName.equalsIgnoreCase( mName ) ) { - it.remove(); - vpl.removeProfile(context, p); - } - } - - this.createVPNProfile(); - - vpl.addProfile(mVpnProfile); - vpl.saveProfile(context, mVpnProfile); - vpl.saveProfileList(context); - } - - /** - * Create and attach the VpnProfile to our gateway object - */ - protected void createVPNProfile(){ - try { - ConfigParser cp = new ConfigParser(); - - JSONObject openvpn_configuration = eip_definition.getJSONObject("openvpn_configuration"); - VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(preferences, openvpn_configuration, mGateway); - String configuration = vpn_configuration_generator.generate(); - - cp.parseConfig(new StringReader(configuration)); - mVpnProfile = cp.convertProfile(); - mVpnProfile.mName = mName = locationAsName(); - Log.v(TAG,"Created VPNProfile"); - - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (ConfigParser.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 eip_definition.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/eip/Gateway.java b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java new file mode 100644 index 00000000..6aa66ac0 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java @@ -0,0 +1,151 @@ +/** + * 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 . + */ +package se.leap.bitmaskclient.eip; + +import android.app.Activity; +import android.content.*; +import android.util.Log; +import java.io.*; +import java.util.*; +import org.json.*; + +import de.blinkt.openvpn.*; +import de.blinkt.openvpn.activities.*; +import de.blinkt.openvpn.core.*; +import se.leap.bitmaskclient.*; + +/** + * 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 + * @author Parménides GV + */ +public class Gateway { + + private String TAG = Gateway.class.getSimpleName(); + + private String mName; + private int timezone; + private JSONObject general_configuration; + private Context context; + private VpnProfile mVpnProfile; + private JSONObject mGateway; + + /** + * Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json + * and create a VpnProfile belonging to it. + * + * @param gateway The JSON OpenVPN gateway definition to parse + */ + protected Gateway(JSONObject eip_definition, Context context, JSONObject gateway){ + + mGateway = gateway; + + this.context = context; + general_configuration = getGeneralConfiguration(eip_definition); + timezone = getTimezone(eip_definition); + mName = locationAsName(eip_definition); + + // Currently deletes VpnProfile for host, if there already is one, and builds new + ProfileManager vpl = ProfileManager.getInstance(context); + Collection profiles = vpl.getProfiles(); + for (Iterator it = profiles.iterator(); it.hasNext(); ){ + VpnProfile p = it.next(); + + if ( p.mName.equalsIgnoreCase( mName ) ) { + it.remove(); + vpl.removeProfile(context, p); + } + } + + mVpnProfile = createVPNProfile(); + mVpnProfile.mName = mName; + + vpl.addProfile(mVpnProfile); + vpl.saveProfile(context, mVpnProfile); + vpl.saveProfileList(context); + } + + private JSONObject getGeneralConfiguration(JSONObject eip_definition) { + 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"); + } + + private String locationAsName(JSONObject eip_definition) { + JSONObject location = getLocationInfo(eip_definition); + return location.optString("name"); + } + + private JSONObject getLocationInfo(JSONObject eip_definition) { + try { + JSONObject locations = eip_definition.getJSONObject("locations"); + JSONObject location = locations.getJSONObject(mGateway.getString("location")); + + return location; + } catch (JSONException e) { + return new JSONObject(); + } + } + + /** + * Create and attach the VpnProfile to our gateway object + */ + private VpnProfile createVPNProfile(){ + try { + ConfigParser cp = new ConfigParser(); + + SharedPreferences preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Activity.MODE_PRIVATE); + VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(preferences, general_configuration, mGateway); + 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; + } + } + + public String getName() { + return mName; + } + + public VpnProfile getProfile() { + return mVpnProfile; + } + + public int getTimezone() { + return timezone; + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java new file mode 100644 index 00000000..36b5fb41 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java @@ -0,0 +1,44 @@ +package se.leap.bitmaskclient.eip; + +import java.security.cert.*; +import java.util.*; +import org.json.*; + +public class GatewaySelector { + List gateways; + + public GatewaySelector(List gateways) { + this.gateways = gateways; + } + + public Gateway select() { + return closestGateway(); + } + + private Gateway closestGateway() { + TreeMap> offsets = calculateOffsets(); + return offsets.isEmpty() ? null : offsets.firstEntry().getValue().iterator().next(); + } + + private TreeMap> calculateOffsets() { + TreeMap> offsets = new TreeMap>(); + int localOffset = Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000; + for(Gateway gateway : gateways) { + int dist = timezoneDistance(localOffset, gateway.getTimezone()); + Set set = (offsets.get(dist) != null) ? + offsets.get(dist) : new HashSet(); + 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; + } +} -- cgit v1.2.3 From bc3af9b45a962721002e249806e0e9edd01e3e8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 18 Nov 2014 18:38:06 +0100 Subject: Extracted EipStatus, centralizing new state notifications. Observer pattern. The only notification is being received properly on EipServiceFragment is the connected one. I need to fix the other UI methods. --- .../se/leap/bitmaskclient/EipServiceFragment.java | 80 +++++-------- .../main/java/se/leap/bitmaskclient/eip/EIP.java | 22 +--- .../java/se/leap/bitmaskclient/eip/EipStatus.java | 133 +++++++++++++++++++++ 3 files changed, 169 insertions(+), 66 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java index f35a3cfa..675619ca 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java @@ -13,8 +13,9 @@ import android.os.*; import android.util.Log; import android.view.*; import android.widget.*; +import java.util.*; -public class EipServiceFragment extends Fragment implements VpnStatus.StateListener, CompoundButton.OnCheckedChangeListener { +public class EipServiceFragment extends Fragment implements Observer, CompoundButton.OnCheckedChangeListener { protected static final String IS_EIP_PENDING = "is_eip_pending"; public static final String START_ON_BOOT = "start on boot"; @@ -23,6 +24,7 @@ public class EipServiceFragment extends Fragment implements VpnStatus.StateListe private static Switch eipSwitch; private View eipDetail; private TextView eipStatus; + private EipStatus eip_status; private static EIPReceiver mEIPReceiver; @@ -57,7 +59,7 @@ public class EipServiceFragment extends Fragment implements VpnStatus.StateListe @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - + EipStatus.getInstance().addObserver(this); mEIPReceiver = new EIPReceiver(new Handler()); if (savedInstanceState != null) @@ -66,18 +68,8 @@ public class EipServiceFragment extends Fragment implements VpnStatus.StateListe @Override public void onResume() { - super.onResume(); - - VpnStatus.addStateListener(this); - - eipCommand(Constants.ACTION_CHECK_CERT_VALIDITY); - } - - @Override - public void onPause() { - super.onPause(); - - VpnStatus.removeStateListener(this); + super.onResume(); + eipCommand(Constants.ACTION_CHECK_CERT_VALIDITY); } @Override @@ -205,47 +197,43 @@ public class EipServiceFragment extends Fragment implements VpnStatus.StateListe } @Override - public void updateState(final String state, final String logmessage, final int localizedResId, final VpnStatus.ConnectionStatus level) { - boolean isNewLevel = EIP.lastConnectionStatusLevel != level; - boolean justDecidedOnDisconnect = EIP.lastConnectionStatusLevel == VpnStatus.ConnectionStatus.UNKNOWN_LEVEL; - Log.d(TAG, "update state with level " + level); - if(!justDecidedOnDisconnect && (isNewLevel || level == VpnStatus.ConnectionStatus.LEVEL_CONNECTED)) { - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - EIP.lastConnectionStatusLevel = level; - handleNewState(state, logmessage, localizedResId, level); - } - }); - } else if(justDecidedOnDisconnect && level == VpnStatus.ConnectionStatus.LEVEL_CONNECTED) { - EIP.lastConnectionStatusLevel = VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED; - updateState(state, logmessage, localizedResId, level); - } // else if(isNewLevel || level == ConnectionStatus.LEVEL_AUTH_FAILED) - // handleNewState(state, logmessage, localizedResId, level); + public void update (Observable observable, Object data) { + if(observable instanceof EipStatus) { + final EipStatus eip_status = (EipStatus) observable; + EipStatus previous_status = eip_status.getPreviousStatus(); + boolean isNewLevel = eip_status.getLevel() != previous_status.getLevel(); + if(!eip_status.wantsToDisconnect() && (isNewLevel || eip_status.isConnected())) { + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + handleNewState(eip_status); + } + }); + } else if(eip_status.wantsToDisconnect() && eip_status.isConnected()) { + setDisconnectedUI(); + // EIP.lastConnectionStatusLevel = VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED; + // updateState(state, logmessage, localizedResId, level); + } + } } - private void handleNewState(final String state, final String logmessage, final int localizedResId, final VpnStatus.ConnectionStatus level) { + private void handleNewState(EipStatus eip_status) { + final String state = eip_status.getState(); + final String logmessage = eip_status.getLogMessage(); + final int localizedResId = eip_status.getLocalizedResId(); + final VpnStatus.ConnectionStatus level = eip_status.getLevel(); if (level == VpnStatus.ConnectionStatus.LEVEL_CONNECTED) setConnectedUI(); - else if (isDisconnectedLevel(level) && !EIP.mIsStarting) + else if (eip_status.isDisconnected() && !eip_status.isConnecting()) setDisconnectedUI(); else if (level == VpnStatus.ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET) setNoServerReplyUI(localizedResId, logmessage); else if (level == VpnStatus.ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED) setServerReplyUI(state, localizedResId, logmessage); - // else if (level == VpnStatus.ConnectionStatus.LEVEL_AUTH_FAILED) - // handleSwitchOn(); - } - - private boolean isDisconnectedLevel(final VpnStatus.ConnectionStatus level) { - return level == VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED || level == VpnStatus.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(); @@ -253,17 +241,15 @@ public class EipServiceFragment extends Fragment implements VpnStatus.StateListe 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()) { + private void adjustSwitch() { + EipStatus eip_status = EipStatus.getInstance(); + if(eip_status.isConnected()) { if(!eipSwitch.isChecked()) { eipSwitch.setChecked(true); } 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 876ad172..97ef485a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -46,21 +46,16 @@ import static se.leap.bitmaskclient.eip.Constants.*; public final class EIP extends IntentService { public final static String TAG = EIP.class.getSimpleName(); - public final static String SERVICE_API_PATH = "config/eip-service.json"; - private static SharedPreferences preferences; - private static Context context; private static ResultReceiver mReceiver; - private static boolean mBound = false; + private static SharedPreferences preferences; - private static int parsedEipSerial; private static JSONObject eip_definition = null; - - private static Gateway activeGateway = null; private static List gateways = new ArrayList(); - ProfileManager profile_manager; + private static ProfileManager profile_manager; + private static Gateway activeGateway = null; public static VpnStatus.ConnectionStatus lastConnectionStatusLevel; public static boolean mIsDisconnecting = false; @@ -81,15 +76,6 @@ public final class EIP extends IntentService { refreshEipDefinition(); } - @Override - public void onDestroy() { - - mBound = false; - - super.onDestroy(); - } - - @Override protected void onHandleIntent(Intent intent) { String action = intent.getAction(); @@ -115,7 +101,6 @@ public final class EIP extends IntentService { private void startEIP() { earlyRoutes(); GatewaySelector gateway_selector = new GatewaySelector(gateways); - activeGateway = gateway_selector.select(); if(activeGateway != null && activeGateway.getProfile() != null) { mReceiver = EipServiceFragment.getReceiver(); @@ -137,7 +122,6 @@ public final class EIP extends IntentService { 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.getProfile().getUUID().toString() ); intent.putExtra(LaunchVPN.EXTRA_NAME, activeGateway.getProfile().getName() ); intent.putExtra(LaunchVPN.EXTRA_HIDELOG, true); intent.putExtra(RECEIVER_TAG, mReceiver); diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java new file mode 100644 index 00000000..c58650ba --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java @@ -0,0 +1,133 @@ +/** + * 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 . + */ +package se.leap.bitmaskclient.eip; + +import android.util.Log; +import java.util.*; + +import de.blinkt.openvpn.core.*; + +public class EipStatus extends Observable implements VpnStatus.StateListener { + public static String TAG = EipStatus.class.getSimpleName(); + private static EipStatus current_status; + + private static EipStatus previous_status; + private static VpnStatus.ConnectionStatus level = VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED; + private static boolean wants_to_disconnect = false; + private static boolean is_disconnecting = false; + private static boolean is_connecting = false; + + private String state, log_message; + private int localized_res_id; + + public static EipStatus getInstance() { + if(current_status == null) { + current_status = new EipStatus(); + VpnStatus.addStateListener(current_status); + } + return current_status; + } + + private EipStatus() { } + + @Override + public void updateState(final String state, final String logmessage, final int localizedResId, final VpnStatus.ConnectionStatus level) { + current_status = getInstance(); + previous_status = current_status; + current_status.setState(state); + current_status.setLogMessage(logmessage); + current_status.setLocalizedResId(localizedResId); + current_status.setLevel(level); + current_status.setChanged(); + Log.d(TAG, "update state with level " + level); + current_status.notifyObservers(); + } + + public boolean isDisconnecting() { + return is_disconnecting; + } + + public boolean isConnecting() { + return is_connecting; + } + + public boolean wantsToDisconnect() { + return wants_to_disconnect; + } + + public boolean isConnected() { + return level == VpnStatus.ConnectionStatus.LEVEL_CONNECTED; + } + + public boolean isDisconnected() { + return level == VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED || level == VpnStatus.ConnectionStatus.LEVEL_AUTH_FAILED; + } + + public void setConnecting() { + is_connecting = true; + is_disconnecting = false; + wants_to_disconnect = false; + } + + public void setDisconnecting() { + is_disconnecting = true; + is_connecting = false; + wants_to_disconnect = false; + level = VpnStatus.ConnectionStatus.UNKNOWN_LEVEL; // Wait for the decision of the user + } + + public void setWantsToDisconnect() { + wants_to_disconnect = true; + } + + public String getState() { + return state; + } + + public String getLogMessage() { + return log_message; + } + + public int getLocalizedResId() { + return localized_res_id; + } + + public VpnStatus.ConnectionStatus getLevel() { + return level; + } + + public EipStatus getPreviousStatus() { + return previous_status; + } + + private void setState(String state) { + this.state = state; + } + + private void setLogMessage(String log_message) { + this.log_message = log_message; + } + + private void setLocalizedResId(int localized_res_id) { + this.localized_res_id = localized_res_id; + } + + private void setLevel(VpnStatus.ConnectionStatus level) { + this.level = level; + } + +} -- cgit v1.2.3 From 50949530a8453e1aa62c0ff277849d6f83fe0f76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 19 Nov 2014 20:20:31 +0100 Subject: Eip status messages refactored. --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 80 ++++----- .../se/leap/bitmaskclient/EipServiceFragment.java | 181 +++++++++------------ .../main/java/se/leap/bitmaskclient/eip/EIP.java | 28 +--- .../java/se/leap/bitmaskclient/eip/EipStatus.java | 13 +- 4 files changed, 138 insertions(+), 164 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index b139f73f..fe3c3f23 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -57,7 +57,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf private EipServiceFragment eipFragment; private ProgressBar mProgressBar; - private TextView eipStatus; + private TextView status_message; public ProviderAPIResultReceiver providerAPI_result_receiver; private static Provider provider; @@ -116,28 +116,29 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf super.onPause(); } - @Override - protected void onActivityResult(int requestCode, int resultCode, final Intent data){ - if ( requestCode == CONFIGURE_LEAP || requestCode == SWITCH_PROVIDER) { - // It should be equivalent: if ( (requestCode == CONFIGURE_LEAP) || (data!= null && data.hasExtra(STOP_FIRST))) { - if ( resultCode == RESULT_OK ){ - preferences.edit().putInt(Constants.PARSED_SERIAL, 0).commit(); - preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).commit(); - Intent updateEIP = new Intent(getApplicationContext(), EIP.class); - updateEIP.setAction(Constants.ACTION_UPDATE_EIP_SERVICE); - startService(updateEIP); - buildDashboard(false); - invalidateOptionsMenu(); - if(data != null && data.hasExtra(LogInDialog.TAG)) { - View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0); - logInDialog(Bundle.EMPTY); - } - } else if(resultCode == RESULT_CANCELED && (data == null || data.hasExtra(ACTION_QUIT))) { - finish(); - } else - configErrorDialog(); + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data){ + Log.d(TAG, "onActivityResult: requestCode = " + requestCode); + if ( requestCode == CONFIGURE_LEAP || requestCode == SWITCH_PROVIDER) { + // It should be equivalent: if ( (requestCode == CONFIGURE_LEAP) || (data!= null && data.hasExtra(STOP_FIRST))) { + if ( resultCode == RESULT_OK ){ + preferences.edit().putInt(Constants.PARSED_SERIAL, 0).commit(); + preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).commit(); + updateEipService(); + buildDashboard(false); + invalidateOptionsMenu(); + if(data != null && data.hasExtra(LogInDialog.TAG)) { + View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0); + logInDialog(Bundle.EMPTY); } + } else if(resultCode == RESULT_CANCELED && (data == null || data.hasExtra(ACTION_QUIT))) { + finish(); + } else + configErrorDialog(); + } else if(requestCode == 33) { + EipStatus.getInstance().setConnectedOrDisconnected(); } + } /** * Dialog shown when encountering a configuration error. Such errors require @@ -273,7 +274,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf private Intent prepareProviderAPICommand() { mProgressBar = (ProgressBar) findViewById(R.id.eipProgress); - eipStatus = (TextView) findViewById(R.id.eipStatus); + status_message = (TextView) findViewById(R.id.status_message); providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); providerAPI_result_receiver.setReceiver(this); @@ -307,7 +308,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf parameters.putString(SessionDialogInterface.PASSWORD, password); mProgressBar.setVisibility(ProgressBar.VISIBLE); - eipStatus.setText(R.string.authenticating_message); + status_message.setText(R.string.authenticating_message); provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); provider_API_command.setAction(ProviderAPI.SRP_AUTH); @@ -331,8 +332,8 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf if(mProgressBar == null) mProgressBar = (ProgressBar) findViewById(R.id.eipProgress); mProgressBar.setVisibility(ProgressBar.VISIBLE); - if(eipStatus == null) eipStatus = (TextView) findViewById(R.id.eipStatus); - eipStatus.setText(R.string.logout_message); + if(status_message == null) status_message = (TextView) findViewById(R.id.status_message); + status_message.setText(R.string.logout_message); provider_API_command.setAction(ProviderAPI.LOG_OUT); startService(provider_API_command); @@ -362,7 +363,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf parameters.putString(SessionDialogInterface.PASSWORD, password); mProgressBar.setVisibility(ProgressBar.VISIBLE); - eipStatus.setText(R.string.signingup_message); + status_message.setText(R.string.signingup_message); provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); provider_API_command.setAction(ProviderAPI.SRP_REGISTER); @@ -390,6 +391,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf @Override public void onReceiveResult(int resultCode, Bundle resultData) { + Log.d(TAG, "onReceiveResult"); if(resultCode == ProviderAPI.SRP_REGISTRATION_SUCCESSFUL) { String username = resultData.getString(SessionDialogInterface.USERNAME); String password = resultData.getString(SessionDialogInterface.PASSWORD); @@ -466,17 +468,17 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf protected void onReceiveResult(int resultCode, Bundle resultData){ super.onReceiveResult(resultCode, resultData); String request = resultData.getString(Constants.REQUEST_TAG); - if(eipStatus == null) eipStatus = (TextView) findViewById(R.id.eipStatus); + if(status_message == null) status_message = (TextView) findViewById(R.id.status_message); if (request.equalsIgnoreCase(Constants.ACTION_IS_EIP_RUNNING)){ if (resultCode == Activity.RESULT_OK){ switch(previous_result_code){ - case ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL: eipStatus.setText(R.string.succesful_authentication_message); break; - case ProviderAPI.SRP_AUTHENTICATION_FAILED: eipStatus.setText(R.string.authentication_failed_message); break; - case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: eipStatus.setText(R.string.authed_secured_status); break; - case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: eipStatus.setText(R.string.incorrectly_downloaded_certificate_message); break; - case ProviderAPI.LOGOUT_SUCCESSFUL: eipStatus.setText(R.string.logged_out_message); break; - case ProviderAPI.LOGOUT_FAILED: eipStatus.setText(R.string.log_out_failed_message); break; + case ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL: status_message.setText(R.string.succesful_authentication_message); break; + case ProviderAPI.SRP_AUTHENTICATION_FAILED: status_message.setText(R.string.authentication_failed_message); break; + case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: status_message.setText(R.string.authed_secured_status); break; + case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: status_message.setText(R.string.incorrectly_downloaded_certificate_message); break; + case ProviderAPI.LOGOUT_SUCCESSFUL: status_message.setText(R.string.logged_out_message); break; + case ProviderAPI.LOGOUT_FAILED: status_message.setText(R.string.log_out_failed_message); break; } } @@ -484,13 +486,13 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf switch(previous_result_code){ - case ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL: eipStatus.setText(R.string.succesful_authentication_message); break; - case ProviderAPI.SRP_AUTHENTICATION_FAILED: eipStatus.setText(R.string.authentication_failed_message); break; - case ProviderAPI.SRP_REGISTRATION_FAILED: eipStatus.setText(R.string.registration_failed_message); break; + case ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL: status_message.setText(R.string.succesful_authentication_message); break; + case ProviderAPI.SRP_AUTHENTICATION_FAILED: status_message.setText(R.string.authentication_failed_message); break; + case ProviderAPI.SRP_REGISTRATION_FAILED: status_message.setText(R.string.registration_failed_message); break; case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: break; - case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: eipStatus.setText(R.string.incorrectly_downloaded_certificate_message); break; - case ProviderAPI.LOGOUT_SUCCESSFUL: eipStatus.setText(R.string.logged_out_message); break; - case ProviderAPI.LOGOUT_FAILED: eipStatus.setText(R.string.log_out_failed_message); break; + case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: status_message.setText(R.string.incorrectly_downloaded_certificate_message); break; + case ProviderAPI.LOGOUT_SUCCESSFUL: status_message.setText(R.string.logged_out_message); break; + case ProviderAPI.LOGOUT_FAILED: status_message.setText(R.string.log_out_failed_message); break; } } } diff --git a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java index 675619ca..7dfb628d 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java @@ -17,70 +17,70 @@ import java.util.*; public class EipServiceFragment extends Fragment implements Observer, CompoundButton.OnCheckedChangeListener { - protected static final String IS_EIP_PENDING = "is_eip_pending"; + protected static final String IS_EIP_PENDING = "is_eip_pending"; public static final String START_ON_BOOT = "start on boot"; - private View eipFragment; - private static Switch eipSwitch; - private View eipDetail; - private TextView eipStatus; - private EipStatus eip_status; + private View eipFragment; + private static Switch eipSwitch; + private View eipDetail; + private TextView status_message; private static EIPReceiver mEIPReceiver; - + private static EipStatus eip_status; public static String TAG = "se.leap.bitmask.EipServiceFragment"; - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + eip_status = EipStatus.getInstance(); + eip_status.addObserver(this); + mEIPReceiver = new EIPReceiver(new Handler()); + + if (savedInstanceState != null && savedInstanceState.getBoolean(IS_EIP_PENDING)) + eip_status.setConnecting(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { - eipFragment = inflater.inflate(R.layout.eip_service_fragment, container, false); - eipDetail = ((RelativeLayout) eipFragment.findViewById(R.id.eipDetail)); - eipDetail.setVisibility(View.VISIBLE); + 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! + View eipSettings = eipFragment.findViewById(R.id.eipSettings); + eipSettings.setVisibility(View.GONE); // FIXME too! - if (EIP.mIsStarting) - eipFragment.findViewById(R.id.eipProgress).setVisibility(View.VISIBLE); + if (eip_status.isConnecting()) + eipFragment.findViewById(R.id.eipProgress).setVisibility(View.VISIBLE); - eipStatus = (TextView) eipFragment.findViewById(R.id.eipStatus); + status_message = (TextView) eipFragment.findViewById(R.id.status_message); - eipSwitch = (Switch) eipFragment.findViewById(R.id.eipSwitch); - eipSwitch.setOnCheckedChangeListener(this); + eipSwitch = (Switch) eipFragment.findViewById(R.id.eipSwitch); + eipSwitch.setOnCheckedChangeListener(this); - if(getArguments() != null && getArguments().containsKey(START_ON_BOOT) && getArguments().getBoolean(START_ON_BOOT)) - startEipFromScratch(); + if(getArguments() != null && getArguments().containsKey(START_ON_BOOT) && getArguments().getBoolean(START_ON_BOOT)) + startEipFromScratch(); - return eipFragment; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - EipStatus.getInstance().addObserver(this); - mEIPReceiver = new EIPReceiver(new Handler()); - - if (savedInstanceState != null) - EIP.mIsStarting = savedInstanceState.getBoolean(IS_EIP_PENDING); - } + return eipFragment; + } - @Override - public void onResume() { - super.onResume(); - eipCommand(Constants.ACTION_CHECK_CERT_VALIDITY); - } + @Override + public void onResume() { + super.onResume(); + eipCommand(Constants.ACTION_CHECK_CERT_VALIDITY); + } - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putBoolean(IS_EIP_PENDING, EIP.mIsStarting); - } + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(IS_EIP_PENDING, eip_status.isConnecting()); + } protected void saveEipStatus() { boolean eip_is_on = false; - Log.d("bitmask", "saveEipStatus"); + Log.d(TAG, "saveEipStatus"); if(eipSwitch.isChecked()) { eip_is_on = true; } @@ -88,6 +88,7 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu if(getActivity() != null) Dashboard.preferences.edit().putBoolean(Dashboard.START_ON_BOOT, eip_is_on).commit(); } + @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (buttonView.equals(eipSwitch)){ @@ -117,7 +118,7 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu private boolean canStartEIP() { boolean certificateExists = !Dashboard.preferences.getString(Constants.CERTIFICATE, "").isEmpty(); boolean isAllowedAnon = Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false); - return (isAllowedAnon || certificateExists) && !EIP.mIsStarting && !EIP.isConnected(); + return (isAllowedAnon || certificateExists) && !eip_status.isConnected(); } private boolean canLogInToStartEIP() { @@ -125,14 +126,13 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu boolean isLoggedIn = !LeapSRPSession.getToken().isEmpty(); Log.d(TAG, "Allow registered? " + isAllowedRegistered); Log.d(TAG, "Is logged in? " + isLoggedIn); - return isAllowedRegistered && !isLoggedIn && !EIP.mIsStarting && !EIP.isConnected(); + return isAllowedRegistered && !isLoggedIn && !eip_status.isConnecting() && !eip_status.isConnected(); } private void handleSwitchOff() { - if(EIP.mIsStarting) { + if(eip_status.isConnecting()) { askPendingStartCancellation(); - } else if(EIP.isConnected()) { - Log.d(TAG, "Stopping EIP"); + } else if(eip_status.isConnected()) { stopEIP(); } } @@ -150,7 +150,6 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu .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); } }) @@ -158,13 +157,12 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu } public void startEipFromScratch() { - EIP.mIsStarting = true; + eip_status.setConnecting(); eipFragment.findViewById(R.id.eipProgress).setVisibility(View.VISIBLE); 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(); } @@ -172,7 +170,6 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu } protected void stopEIP() { - EIP.mIsStarting = false; View eipProgressBar = getActivity().findViewById(R.id.eipProgress); if(eipProgressBar != null) eipProgressBar.setVisibility(View.GONE); @@ -199,56 +196,42 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu @Override public void update (Observable observable, Object data) { if(observable instanceof EipStatus) { + this.eip_status = (EipStatus) observable; final EipStatus eip_status = (EipStatus) observable; - EipStatus previous_status = eip_status.getPreviousStatus(); - boolean isNewLevel = eip_status.getLevel() != previous_status.getLevel(); - if(!eip_status.wantsToDisconnect() && (isNewLevel || eip_status.isConnected())) { - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - handleNewState(eip_status); - } - }); - } else if(eip_status.wantsToDisconnect() && eip_status.isConnected()) { - setDisconnectedUI(); - // EIP.lastConnectionStatusLevel = VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED; - // updateState(state, logmessage, localizedResId, level); - } + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + handleNewState(eip_status); + } + }); } } private void handleNewState(EipStatus eip_status) { final String state = eip_status.getState(); - final String logmessage = eip_status.getLogMessage(); - final int localizedResId = eip_status.getLocalizedResId(); - final VpnStatus.ConnectionStatus level = eip_status.getLevel(); - if (level == VpnStatus.ConnectionStatus.LEVEL_CONNECTED) + if(eip_status.wantsToDisconnect()) + setDisconnectedUI(); + else if (eip_status.isConnected()) setConnectedUI(); else if (eip_status.isDisconnected() && !eip_status.isConnecting()) setDisconnectedUI(); - else if (level == VpnStatus.ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET) - setNoServerReplyUI(localizedResId, logmessage); - else if (level == VpnStatus.ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED) - setServerReplyUI(state, localizedResId, logmessage); + else + setInProgressUI(eip_status); } private void setConnectedUI() { hideProgressBar(); - String status = getString(R.string.eip_state_connected); - setEipStatus(status); adjustSwitch(); + setEipStatus(getString(R.string.eip_state_connected)); } private void setDisconnectedUI(){ hideProgressBar(); - - String status = getString(R.string.eip_state_not_connected); - setEipStatus(status); adjustSwitch(); + setEipStatus(getString(R.string.eip_state_not_connected)); } private void adjustSwitch() { - EipStatus eip_status = EipStatus.getInstance(); if(eip_status.isConnected()) { if(!eipSwitch.isChecked()) { eipSwitch.setChecked(true); @@ -260,25 +243,18 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu } } - 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); - } + private void setInProgressUI(EipStatus eip_status) { + int localizedResId = eip_status.getLocalizedResId(); + String logmessage = eip_status.getLogMessage(); + 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); + if(status_message == null) + status_message = (TextView) getActivity().findViewById(R.id.status_message); + status_message.setText(status); } private void hideProgressBar() { @@ -319,7 +295,6 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu 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; @@ -329,8 +304,10 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu } else if (request == Constants.ACTION_STOP_EIP) { switch (resultCode){ case Activity.RESULT_OK: - checked = false; - break; + Intent disconnect_vpn = new Intent(getActivity(), DisconnectVPN.class); + getActivity().startActivityForResult(disconnect_vpn, 33); + eip_status.setDisconnecting(); + break; case Activity.RESULT_CANCELED: checked = true; break; @@ -388,7 +365,5 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu public void checkEipSwitch(boolean checked) { eipSwitch.setChecked(checked); - // Log.d(TAG, "checkEipSwitch"); - // onCheckedChanged(eipSwitch, checked); } } 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 97ef485a..577f42a3 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -57,10 +57,6 @@ public final class EIP extends IntentService { private static ProfileManager profile_manager; private static Gateway activeGateway = null; - public static VpnStatus.ConnectionStatus lastConnectionStatusLevel; - public static boolean mIsDisconnecting = false; - public static boolean mIsStarting = false; - public EIP(){ super("LEAPEIP"); } @@ -133,16 +129,13 @@ public final class EIP extends IntentService { * if there is no bound service. Sends a message to the requesting ResultReceiver. */ private void stopEIP() { - if(isConnected()) { - Intent disconnect_vpn = new Intent(this, DisconnectVPN.class); - disconnect_vpn.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(disconnect_vpn); - mIsDisconnecting = true; - lastConnectionStatusLevel = VpnStatus.ConnectionStatus.UNKNOWN_LEVEL; // Wait for the decision of the user - Log.d(TAG, "mIsDisconnecting = true"); - } + EipStatus eip_status = EipStatus.getInstance(); + Log.d(TAG, "stopEip(): eip is connected? " + eip_status.isConnected()); + int result_code = Activity.RESULT_CANCELED; + if(eip_status.isConnected()) + result_code = Activity.RESULT_OK; - tellToReceiver(ACTION_STOP_EIP, Activity.RESULT_OK); + tellToReceiver(ACTION_STOP_EIP, result_code); } private void tellToReceiver(String action, int resultCode) { @@ -160,17 +153,12 @@ public final class EIP extends IntentService { */ private void isRunning() { - int resultCode = (isConnected()) ? + EipStatus eip_status = EipStatus.getInstance(); + int resultCode = (eip_status.isConnected()) ? Activity.RESULT_OK : Activity.RESULT_CANCELED; tellToReceiver(ACTION_IS_EIP_RUNNING, resultCode); } - - public static boolean isConnected() { - return lastConnectionStatusLevel != null - && lastConnectionStatusLevel.equals(VpnStatus.ConnectionStatus.LEVEL_CONNECTED) - && !mIsDisconnecting; - } /** * Loads eip-service.json from SharedPreferences and calls {@link updateGateways()} 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 c58650ba..ee14f2db 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java @@ -53,6 +53,8 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { current_status.setLocalizedResId(localizedResId); current_status.setLevel(level); current_status.setChanged(); + if(isConnected() || isDisconnected()) + setConnectedOrDisconnected(); Log.d(TAG, "update state with level " + level); current_status.notifyObservers(); } @@ -74,7 +76,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { } public boolean isDisconnected() { - return level == VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED || level == VpnStatus.ConnectionStatus.LEVEL_AUTH_FAILED; + return level == VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED; } public void setConnecting() { @@ -83,11 +85,18 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { wants_to_disconnect = false; } + public void setConnectedOrDisconnected() { + is_connecting = false; + is_disconnecting = false; + wants_to_disconnect = false; + current_status.setChanged(); + current_status.notifyObservers(); + } + public void setDisconnecting() { is_disconnecting = true; is_connecting = false; wants_to_disconnect = false; - level = VpnStatus.ConnectionStatus.UNKNOWN_LEVEL; // Wait for the decision of the user } public void setWantsToDisconnect() { -- cgit v1.2.3 From f314ade4e20b3c801ece7f0ad4328af38a264b03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 20 Nov 2014 12:45:12 +0100 Subject: Changing orientation, fixing... --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 30 +-- .../se/leap/bitmaskclient/EipServiceFragment.java | 266 +++++++++++---------- .../java/se/leap/bitmaskclient/LogInDialog.java | 36 ++- .../java/se/leap/bitmaskclient/SignUpDialog.java | 35 ++- 4 files changed, 183 insertions(+), 184 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index fe3c3f23..4bebf14a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -54,8 +54,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf private static Context app; protected static SharedPreferences preferences; private FragmentManagerEnhanced fragment_manager; - - private EipServiceFragment eipFragment; + private ProgressBar mProgressBar; private TextView status_message; public ProviderAPIResultReceiver providerAPI_result_receiver; @@ -180,21 +179,24 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf providerNameTV.setText(provider.getDomain()); providerNameTV.setTextSize(28); - mProgressBar = (ProgressBar) findViewById(R.id.eipProgress); + mProgressBar = (ProgressBar) findViewById(R.id.eipProgress); if ( provider.hasEIP()){ - eipFragment = new EipServiceFragment(); - if (hide_and_turn_on_eip) { - preferences.edit().remove(Dashboard.START_ON_BOOT).commit(); - Bundle arguments = new Bundle(); - arguments.putBoolean(EipServiceFragment.START_ON_BOOT, true); - eipFragment.setArguments(arguments); - } - fragment_manager.replace(R.id.servicesCollection, eipFragment, EipServiceFragment.TAG); - if (hide_and_turn_on_eip) { - onBackPressed(); - } + EipServiceFragment previous_eip_fragment = (EipServiceFragment)fragment_manager.findFragmentByTag(EipServiceFragment.TAG); + EipServiceFragment eipFragment = previous_eip_fragment == null ? + new EipServiceFragment() : previous_eip_fragment; + if (hide_and_turn_on_eip) { + preferences.edit().remove(Dashboard.START_ON_BOOT).commit(); + Bundle arguments = new Bundle(); + arguments.putBoolean(EipServiceFragment.START_ON_BOOT, true); + eipFragment.setArguments(arguments); + } + fragment_manager.replace(R.id.servicesCollection, eipFragment, EipServiceFragment.TAG); + + if (hide_and_turn_on_eip) { + onBackPressed(); + } } } diff --git a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java index 7dfb628d..3650079a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java @@ -17,7 +17,11 @@ import java.util.*; public class EipServiceFragment extends Fragment implements Observer, CompoundButton.OnCheckedChangeListener { - protected static final String IS_EIP_PENDING = "is_eip_pending"; + public static String TAG = "se.leap.bitmask.EipServiceFragment"; + + protected static final String IS_PENDING = TAG + ".is_pending"; + protected static final String IS_CONNECTED = TAG + ".is_connected"; + protected static final String STATUS_MESSAGE = TAG + ".status_message"; public static final String START_ON_BOOT = "start on boot"; private View eipFragment; @@ -25,25 +29,26 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu private View eipDetail; private TextView status_message; + private static Activity parent_activity; private static EIPReceiver mEIPReceiver; private static EipStatus eip_status; - - public static String TAG = "se.leap.bitmask.EipServiceFragment"; + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + parent_activity = activity; + } + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); eip_status = EipStatus.getInstance(); eip_status.addObserver(this); mEIPReceiver = new EIPReceiver(new Handler()); - - if (savedInstanceState != null && savedInstanceState.getBoolean(IS_EIP_PENDING)) - eip_status.setConnecting(); } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { eipFragment = inflater.inflate(R.layout.eip_service_fragment, container, false); eipDetail = ((RelativeLayout) eipFragment.findViewById(R.id.eipDetail)); @@ -58,14 +63,27 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu status_message = (TextView) eipFragment.findViewById(R.id.status_message); eipSwitch = (Switch) eipFragment.findViewById(R.id.eipSwitch); + Log.d(TAG, "onCreateView, eipSwitch is checked? " + eipSwitch.isChecked()); eipSwitch.setOnCheckedChangeListener(this); if(getArguments() != null && getArguments().containsKey(START_ON_BOOT) && getArguments().getBoolean(START_ON_BOOT)) startEipFromScratch(); - + return eipFragment; } + public void onViewStateRestored (Bundle savedInstanceState) { + super.onViewStateRestored(savedInstanceState); + if (savedInstanceState != null) { + setStatusMessage(savedInstanceState.getString(STATUS_MESSAGE)); + if(savedInstanceState.getBoolean(IS_PENDING)) + eip_status.setConnecting(); + else if(savedInstanceState.getBoolean(IS_CONNECTED)) { + eip_status.setConnectedOrDisconnected(); + } + } + } + @Override public void onResume() { super.onResume(); @@ -74,8 +92,11 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu @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_EIP_PENDING, eip_status.isConnecting()); } protected void saveEipStatus() { @@ -85,7 +106,7 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu eip_is_on = true; } - if(getActivity() != null) + if(parent_activity != null) Dashboard.preferences.edit().putBoolean(Dashboard.START_ON_BOOT, eip_is_on).commit(); } @@ -110,7 +131,7 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu startEipFromScratch(); else if(canLogInToStartEIP()) { Log.d(TAG, "Can Log In to start EIP"); - Dashboard dashboard = (Dashboard) getActivity(); + Dashboard dashboard = (Dashboard) parent_activity; dashboard.logInDialog(Bundle.EMPTY); } } @@ -138,16 +159,16 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu } 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)) + AlertDialog.Builder alertBuilder = new AlertDialog.Builder(parent_activity); + alertBuilder.setTitle(parent_activity.getString(R.string.eip_cancel_connect_title)) + .setMessage(parent_activity.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() { + .setNegativeButton(parent_activity.getString(R.string.no), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { eipSwitch.setChecked(true); @@ -159,8 +180,8 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu public void startEipFromScratch() { eip_status.setConnecting(); eipFragment.findViewById(R.id.eipProgress).setVisibility(View.VISIBLE); - String status = getResources().getString(R.string.eip_status_start_pending); - setEipStatus(status); + String status = parent_activity.getString(R.string.eip_status_start_pending); + setStatusMessage(status); if(!eipSwitch.isChecked()) { eipSwitch.setChecked(true); @@ -170,37 +191,37 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu } protected void stopEIP() { - View eipProgressBar = getActivity().findViewById(R.id.eipProgress); + View eipProgressBar = parent_activity.findViewById(R.id.eipProgress); if(eipProgressBar != null) eipProgressBar.setVisibility(View.GONE); - String status = getResources().getString(R.string.eip_state_not_connected); - setEipStatus(status); + String status = parent_activity.getString(R.string.eip_state_not_connected); + setStatusMessage(status); eipCommand(Constants.ACTION_STOP_EIP); } - /** - * Send a command to EIP - * - * @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(getActivity().getApplicationContext(), EIP.class); - vpn_intent.setAction(action); - vpn_intent.putExtra(Constants.RECEIVER_TAG, mEIPReceiver); - getActivity().startService(vpn_intent); - } + /** + * Send a command to EIP + * + * @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(parent_activity.getApplicationContext(), EIP.class); + vpn_intent.setAction(action); + vpn_intent.putExtra(Constants.RECEIVER_TAG, mEIPReceiver); + parent_activity.startService(vpn_intent); + } @Override public void update (Observable observable, Object data) { if(observable instanceof EipStatus) { this.eip_status = (EipStatus) observable; final EipStatus eip_status = (EipStatus) observable; - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { + parent_activity.runOnUiThread(new Runnable() { + @Override + public void run() { handleNewState(eip_status); } }); @@ -208,7 +229,6 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu } private void handleNewState(EipStatus eip_status) { - final String state = eip_status.getState(); if(eip_status.wantsToDisconnect()) setDisconnectedUI(); else if (eip_status.isConnected()) @@ -221,18 +241,20 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu private void setConnectedUI() { hideProgressBar(); + Log.d(TAG, "setConnectedUi? " + eip_status.isConnected()); adjustSwitch(); - setEipStatus(getString(R.string.eip_state_connected)); + setStatusMessage(parent_activity.getString(R.string.eip_state_connected)); } private void setDisconnectedUI(){ hideProgressBar(); adjustSwitch(); - setEipStatus(getString(R.string.eip_state_not_connected)); + setStatusMessage(parent_activity.getString(R.string.eip_state_not_connected)); } private void adjustSwitch() { if(eip_status.isConnected()) { + Log.d(TAG, "adjustSwitch, isConnected, is checked? " + eipSwitch.isChecked()); if(!eipSwitch.isChecked()) { eipSwitch.setChecked(true); } @@ -246,113 +268,96 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu private void setInProgressUI(EipStatus eip_status) { int localizedResId = eip_status.getLocalizedResId(); String logmessage = eip_status.getLogMessage(); - String prefix = getString(localizedResId); + String prefix = parent_activity.getString(localizedResId); - setEipStatus(prefix + " " + logmessage); + setStatusMessage(prefix + " " + logmessage); } - protected void setEipStatus(String status) { + protected void setStatusMessage(String status) { if(status_message == null) - status_message = (TextView) getActivity().findViewById(R.id.status_message); + status_message = (TextView) parent_activity.findViewById(R.id.status_message); status_message.setText(status); } private void hideProgressBar() { - if(getActivity() != null && getActivity().findViewById(R.id.eipProgress) != null) - getActivity().findViewById(R.id.eipProgress).setVisibility(View.GONE); + if(parent_activity != null && parent_activity.findViewById(R.id.eipProgress) != null) + parent_activity.findViewById(R.id.eipProgress).setVisibility(View.GONE); } - /** - * Inner class for handling messages related to EIP status and control requests - * - * @author Sean Leonard - */ - protected class EIPReceiver extends ResultReceiver { + protected class EIPReceiver extends ResultReceiver { - protected EIPReceiver(Handler handler){ - super(handler); - } + protected EIPReceiver(Handler handler){ + super(handler); + } - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - super.onReceiveResult(resultCode, resultData); + @Override + protected void onReceiveResult(int resultCode, Bundle resultData) { + super.onReceiveResult(resultCode, resultData); - String request = resultData.getString(Constants.REQUEST_TAG); - boolean checked = false; + String request = resultData.getString(Constants.REQUEST_TAG); + boolean checked = false; - if (request == Constants.ACTION_IS_EIP_RUNNING) { - switch (resultCode){ - case Activity.RESULT_OK: - checked = true; - break; - case Activity.RESULT_CANCELED: - checked = false; - break; - } - } else if (request == Constants.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); - break; - case Activity.RESULT_CANCELED: - checked = false; - eipFragment.findViewById(R.id.eipProgress).setVisibility(View.GONE); - break; - } - } else if (request == Constants.ACTION_STOP_EIP) { - switch (resultCode){ - case Activity.RESULT_OK: - Intent disconnect_vpn = new Intent(getActivity(), DisconnectVPN.class); - getActivity().startActivityForResult(disconnect_vpn, 33); - eip_status.setDisconnecting(); - break; - case Activity.RESULT_CANCELED: - checked = true; - break; - } - } else if (request == Constants.EIP_NOTIFICATION) { - switch (resultCode){ - case Activity.RESULT_OK: - checked = true; - break; - case Activity.RESULT_CANCELED: - checked = false; - break; - } - } else if (request == Constants.ACTION_CHECK_CERT_VALIDITY) { - checked = eipSwitch.isChecked(); - - switch (resultCode) { - case Activity.RESULT_OK: - break; - case Activity.RESULT_CANCELED: - Dashboard dashboard = (Dashboard) getActivity(); - - dashboard.showProgressBar(); - String status = getResources().getString(R.string.updating_certificate_message); - setEipStatus(status); - - if(LeapSRPSession.getToken().isEmpty() && !Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false)) { - dashboard.logInDialog(Bundle.EMPTY); - } else { - - 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; - } + if (request == Constants.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); + break; + case Activity.RESULT_CANCELED: + checked = false; + eipFragment.findViewById(R.id.eipProgress).setVisibility(View.GONE); + break; + } + } else if (request == Constants.ACTION_STOP_EIP) { + switch (resultCode){ + case Activity.RESULT_OK: + Intent disconnect_vpn = new Intent(parent_activity, DisconnectVPN.class); + parent_activity.startActivityForResult(disconnect_vpn, 33); + eip_status.setDisconnecting(); + break; + case Activity.RESULT_CANCELED: + checked = true; + break; + } + } else if (request == Constants.EIP_NOTIFICATION) { + switch (resultCode){ + case Activity.RESULT_OK: + checked = true; + break; + case Activity.RESULT_CANCELED: + checked = false; + break; + } + } else if (request == Constants.ACTION_CHECK_CERT_VALIDITY) { + checked = eipSwitch.isChecked(); + switch (resultCode) { + case Activity.RESULT_OK: + break; + case Activity.RESULT_CANCELED: + Dashboard dashboard = (Dashboard) parent_activity; + + dashboard.showProgressBar(); + String status = parent_activity.getString(R.string.updating_certificate_message); + setStatusMessage(status); + if(LeapSRPSession.getToken().isEmpty() && !Dashboard.preferences.getBoolean(Constants.ALLOWED_ANON, false)) { + dashboard.logInDialog(Bundle.EMPTY); + } else { + Intent provider_API_command = new Intent(parent_activity, 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); + parent_activity.startService(provider_API_command); + } + break; } + } } + } public static EIPReceiver getReceiver() { @@ -366,4 +371,5 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu public void checkEipSwitch(boolean checked) { eipSwitch.setChecked(checked); } + } diff --git a/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java b/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java index 5a0c9a6d..cede9bfb 100644 --- a/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java @@ -55,32 +55,28 @@ public class LogInDialog extends SessionDialogInterface { View log_in_dialog_view = inflater.inflate(R.layout.log_in_dialog, null); final TextView user_message = (TextView)log_in_dialog_view.findViewById(R.id.user_message); - if(getArguments() != null && getArguments().containsKey(getResources().getString(R.string.user_message))) { - user_message.setText(getArguments().getString(getResources().getString(R.string.user_message))); - } else { - user_message.setVisibility(View.GONE); - } - final EditText username_field = (EditText)log_in_dialog_view.findViewById(R.id.username_entered); - if(getArguments() != null && getArguments().containsKey(USERNAME)) { - String username = getArguments().getString(USERNAME); - username_field.setText(username); - } - if (getArguments() != null && getArguments().containsKey(USERNAME_MISSING)) { - username_field.setError(getResources().getString(R.string.username_ask)); - } - final EditText password_field = (EditText)log_in_dialog_view.findViewById(R.id.password_entered); + if(!username_field.getText().toString().isEmpty() && password_field.isFocusable()) { password_field.requestFocus(); } - if (getArguments() != null && getArguments().containsKey(PASSWORD_INVALID_LENGTH)) { - password_field.setError(getResources().getString(R.string.error_not_valid_password_user_message)); - } - if(getArguments() != null && getArguments().getBoolean(EipServiceFragment.IS_EIP_PENDING, false)) { - is_eip_pending = true; + if (getArguments() != null) { + is_eip_pending = getArguments().getBoolean(EipServiceFragment.IS_PENDING, false); + if (getArguments().containsKey(PASSWORD_INVALID_LENGTH)) + password_field.setError(getResources().getString(R.string.error_not_valid_password_user_message)); + if (getArguments().containsKey(USERNAME)) { + String username = getArguments().getString(USERNAME); + username_field.setText(username); } - + if (getArguments().containsKey(USERNAME_MISSING)) { + username_field.setError(getResources().getString(R.string.username_ask)); + } + if(getArguments().containsKey(getResources().getString(R.string.user_message))) + user_message.setText(getArguments().getString(getResources().getString(R.string.user_message))); + else + user_message.setVisibility(View.GONE); + } builder.setView(log_in_dialog_view) .setPositiveButton(R.string.login_button, new DialogInterface.OnClickListener() { diff --git a/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java b/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java index 3cb41f4f..16ad2d19 100644 --- a/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java @@ -54,32 +54,27 @@ public class SignUpDialog extends SessionDialogInterface { View log_in_dialog_view = inflater.inflate(R.layout.log_in_dialog, null); final TextView user_message = (TextView)log_in_dialog_view.findViewById(R.id.user_message); - if(getArguments() != null && getArguments().containsKey(getResources().getString(R.string.user_message))) { - user_message.setText(getArguments().getString(getResources().getString(R.string.user_message))); - } else { - user_message.setVisibility(View.GONE); - } - final EditText username_field = (EditText)log_in_dialog_view.findViewById(R.id.username_entered); - if(getArguments() != null && getArguments().containsKey(USERNAME)) { - String username = getArguments().getString(USERNAME); - username_field.setText(username); - } - if (getArguments() != null && getArguments().containsKey(USERNAME_MISSING)) { - username_field.setError(getResources().getString(R.string.username_ask)); - } - final EditText password_field = (EditText)log_in_dialog_view.findViewById(R.id.password_entered); + if(!username_field.getText().toString().isEmpty() && password_field.isFocusable()) { password_field.requestFocus(); } - if (getArguments() != null && getArguments().containsKey(PASSWORD_INVALID_LENGTH)) { - password_field.setError(getResources().getString(R.string.error_not_valid_password_user_message)); - } - if(getArguments() != null && getArguments().getBoolean(EipServiceFragment.IS_EIP_PENDING, false)) { - is_eip_pending = true; + if (getArguments() != null) { + is_eip_pending = getArguments().getBoolean(EipServiceFragment.IS_PENDING, false); + if (getArguments().containsKey(PASSWORD_INVALID_LENGTH)) + password_field.setError(getResources().getString(R.string.error_not_valid_password_user_message)); + if(getArguments().containsKey(USERNAME_MISSING)) + username_field.setError(getResources().getString(R.string.username_ask)); + if(getArguments().containsKey(USERNAME)) { + String username = getArguments().getString(USERNAME); + username_field.setText(username); } - + if(getArguments().containsKey(getResources().getString(R.string.user_message))) + user_message.setText(getArguments().getString(getResources().getString(R.string.user_message))); + else + user_message.setVisibility(View.GONE); + } builder.setView(log_in_dialog_view) .setPositiveButton(R.string.signup_button, new DialogInterface.OnClickListener() { -- cgit v1.2.3 From 2681e877c6c2e871247cf5e42269d1b867422f1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 20 Nov 2014 12:55:22 +0100 Subject: OnViewStateRestore is available just from api 17. We support from api 14. --- .../se/leap/bitmaskclient/EipServiceFragment.java | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java index 3650079a..0cdc8c75 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java @@ -69,21 +69,17 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu if(getArguments() != null && getArguments().containsKey(START_ON_BOOT) && getArguments().getBoolean(START_ON_BOOT)) startEipFromScratch(); + if (savedInstanceState != null) { + setStatusMessage(savedInstanceState.getString(STATUS_MESSAGE)); + if(savedInstanceState.getBoolean(IS_PENDING)) + eip_status.setConnecting(); + else if(savedInstanceState.getBoolean(IS_CONNECTED)) { + eip_status.setConnectedOrDisconnected(); + } + } return eipFragment; } - public void onViewStateRestored (Bundle savedInstanceState) { - super.onViewStateRestored(savedInstanceState); - if (savedInstanceState != null) { - setStatusMessage(savedInstanceState.getString(STATUS_MESSAGE)); - if(savedInstanceState.getBoolean(IS_PENDING)) - eip_status.setConnecting(); - else if(savedInstanceState.getBoolean(IS_CONNECTED)) { - eip_status.setConnectedOrDisconnected(); - } - } - } - @Override public void onResume() { super.onResume(); -- cgit v1.2.3 From e4d4c07be386f809a8ac028df8146916fc0f7597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Sat, 22 Nov 2014 00:10:46 +0100 Subject: EipStatus detects and notifies changes by itself. Initial status message is "not connected", rather than "unknown". --- .../main/java/se/leap/bitmaskclient/Dashboard.java | 9 ++----- .../se/leap/bitmaskclient/EipServiceFragment.java | 31 ++++++++++++---------- .../java/se/leap/bitmaskclient/LogInDialog.java | 3 +-- .../java/se/leap/bitmaskclient/SignUpDialog.java | 3 +-- .../main/java/se/leap/bitmaskclient/eip/EIP.java | 5 +++- .../java/se/leap/bitmaskclient/eip/EipStatus.java | 29 ++++++++++++++------ .../se/leap/bitmaskclient/eip/VoidVpnLauncher.java | 2 +- 7 files changed, 47 insertions(+), 35 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 4bebf14a..4f6c6285 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -134,7 +134,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf finish(); } else configErrorDialog(); - } else if(requestCode == 33) { + } else if(requestCode == EIP.DISCONNECT) { EipStatus.getInstance().setConnectedOrDisconnected(); } } @@ -317,13 +317,8 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf startService(provider_API_command); } - public void cancelAuthedEipOn() { - EipServiceFragment eipFragment = (EipServiceFragment) getFragmentManager().findFragmentByTag(EipServiceFragment.TAG); - eipFragment.checkEipSwitch(false); - } - public void cancelLoginOrSignup() { - hideProgressBar(); + EipStatus.getInstance().setConnectedOrDisconnected(); } /** diff --git a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java index 0cdc8c75..f29d1338 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java @@ -23,7 +23,7 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu protected static final String IS_CONNECTED = TAG + ".is_connected"; protected static final String STATUS_MESSAGE = TAG + ".status_message"; public static final String START_ON_BOOT = "start on boot"; - + private View eipFragment; private static Switch eipSwitch; private View eipDetail; @@ -174,7 +174,6 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu } public void startEipFromScratch() { - eip_status.setConnecting(); eipFragment.findViewById(R.id.eipProgress).setVisibility(View.VISIBLE); String status = parent_activity.getString(R.string.eip_status_start_pending); setStatusMessage(status); @@ -212,6 +211,7 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu @Override public void update (Observable observable, Object data) { + Log.d(TAG, "handleNewState?"); if(observable instanceof EipStatus) { this.eip_status = (EipStatus) observable; final EipStatus eip_status = (EipStatus) observable; @@ -225,6 +225,7 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu } private void handleNewState(EipStatus eip_status) { + Log.d(TAG, "handleNewState: " + eip_status.toString()); if(eip_status.wantsToDisconnect()) setDisconnectedUI(); else if (eip_status.isConnected()) @@ -249,12 +250,14 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu } private void adjustSwitch() { - if(eip_status.isConnected()) { - Log.d(TAG, "adjustSwitch, isConnected, is checked? " + eipSwitch.isChecked()); + if(eip_status.isConnected() || eip_status.isConnecting()) { + Log.d(TAG, "adjustSwitch, isConnected || isConnecting, is checked? " + eipSwitch.isChecked()); if(!eipSwitch.isChecked()) { eipSwitch.setChecked(true); } } else { + Log.d(TAG, "adjustSwitch, !isConnected && !isConnecting? " + eip_status.toString()); + if(eipSwitch.isChecked()) { eipSwitch.setChecked(false); } @@ -267,6 +270,7 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu String prefix = parent_activity.getString(localizedResId); setStatusMessage(prefix + " " + logmessage); + adjustSwitch(); } protected void setStatusMessage(String status) { @@ -280,6 +284,14 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu parent_activity.findViewById(R.id.eipProgress).setVisibility(View.GONE); } + public static EipStatus getEipStatus() { + return eip_status; + } + + public void checkEipSwitch(boolean activated) { + eipSwitch.setChecked(activated); + } + protected class EIPReceiver extends ResultReceiver { protected EIPReceiver(Handler handler){ @@ -309,7 +321,7 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu switch (resultCode){ case Activity.RESULT_OK: Intent disconnect_vpn = new Intent(parent_activity, DisconnectVPN.class); - parent_activity.startActivityForResult(disconnect_vpn, 33); + parent_activity.startActivityForResult(disconnect_vpn, EIP.DISCONNECT); eip_status.setDisconnecting(); break; case Activity.RESULT_CANCELED: @@ -359,13 +371,4 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu public static EIPReceiver getReceiver() { return mEIPReceiver; } - - public static boolean isEipSwitchChecked() { - return eipSwitch.isChecked(); - } - - public void checkEipSwitch(boolean checked) { - eipSwitch.setChecked(checked); - } - } diff --git a/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java b/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java index cede9bfb..97a9aecc 100644 --- a/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java @@ -112,7 +112,6 @@ public class LogInDialog extends SessionDialogInterface { */ public interface LogInDialogInterface { public void logIn(String username, String password); - public void cancelAuthedEipOn(); public void signUp(String username, String password); public void cancelLoginOrSignup(); } @@ -142,6 +141,6 @@ public class LogInDialog extends SessionDialogInterface { public void onCancel(DialogInterface dialog) { super.onCancel(dialog); if(is_eip_pending) - interface_with_Dashboard.cancelAuthedEipOn(); + interface_with_Dashboard.cancelLoginOrSignup(); } } diff --git a/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java b/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java index 16ad2d19..d197e589 100644 --- a/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java @@ -103,7 +103,6 @@ public class SignUpDialog extends SessionDialogInterface { */ public interface SignUpDialogInterface { public void signUp(String username, String password); - public void cancelAuthedEipOn(); public void cancelLoginOrSignup(); } @@ -131,7 +130,7 @@ public class SignUpDialog extends SessionDialogInterface { @Override public void onCancel(DialogInterface dialog) { if(is_eip_pending) - interface_with_Dashboard.cancelAuthedEipOn(); + interface_with_Dashboard.cancelLoginOrSignup(); super.onCancel(dialog); } } 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 577f42a3..379fb246 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -47,6 +47,9 @@ public final class EIP extends IntentService { public final static String TAG = EIP.class.getSimpleName(); 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; @@ -95,13 +98,13 @@ public final class EIP extends IntentService { * It also sets up early routes. */ private void startEIP() { - earlyRoutes(); GatewaySelector gateway_selector = new GatewaySelector(gateways); activeGateway = gateway_selector.select(); if(activeGateway != null && activeGateway.getProfile() != null) { mReceiver = EipServiceFragment.getReceiver(); launchActiveGateway(); } + earlyRoutes(); } /** 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 ee14f2db..82c3ceb8 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java @@ -29,7 +29,6 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { private static VpnStatus.ConnectionStatus level = VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED; private static boolean wants_to_disconnect = false; private static boolean is_disconnecting = false; - private static boolean is_connecting = false; private String state, log_message; private int localized_res_id; @@ -55,6 +54,8 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { current_status.setChanged(); if(isConnected() || isDisconnected()) setConnectedOrDisconnected(); + else if(isConnecting()) + setConnecting(); Log.d(TAG, "update state with level " + level); current_status.notifyObservers(); } @@ -63,14 +64,17 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { return is_disconnecting; } - public boolean isConnecting() { - return is_connecting; - } - public boolean wantsToDisconnect() { return wants_to_disconnect; } + public boolean isConnecting() { + return + !isConnected() && + !isDisconnected() && + !isPaused(); + } + public boolean isConnected() { return level == VpnStatus.ConnectionStatus.LEVEL_CONNECTED; } @@ -79,14 +83,19 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { return level == VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED; } + public boolean isPaused() { + return level == VpnStatus.ConnectionStatus.LEVEL_VPNPAUSED; + } + public void setConnecting() { - is_connecting = true; is_disconnecting = false; wants_to_disconnect = false; + current_status.setChanged(); + current_status.notifyObservers(); } public void setConnectedOrDisconnected() { - is_connecting = false; + Log.d(TAG, "setConnectedOrDisconnected()"); is_disconnecting = false; wants_to_disconnect = false; current_status.setChanged(); @@ -95,7 +104,6 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { public void setDisconnecting() { is_disconnecting = true; - is_connecting = false; wants_to_disconnect = false; } @@ -139,4 +147,9 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { this.level = level; } + @Override + public String toString() { + return "State: " + state + " Level: " + level.toString(); + } + } 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 9814c167..d79d8003 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java @@ -8,7 +8,7 @@ import android.os.Bundle; public class VoidVpnLauncher extends Activity { private static final int VPN_USER_PERMISSION = 71; - + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); -- cgit v1.2.3 From 2fc73d6bfe8d86464571258f008d8bcf6db0cc2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 27 Nov 2014 20:09:05 +0100 Subject: Removed unused imports and unused .eip variables --- .../java/se/leap/bitmaskclient/AboutActivity.java | 5 -- .../java/se/leap/bitmaskclient/ConfigHelper.java | 13 ++--- .../main/java/se/leap/bitmaskclient/Dashboard.java | 68 +++++++++++++--------- .../leap/bitmaskclient/DownloadFailedDialog.java | 3 - .../se/leap/bitmaskclient/EipServiceFragment.java | 67 ++++++++++----------- .../java/se/leap/bitmaskclient/LeapSRPSession.java | 3 +- .../java/se/leap/bitmaskclient/LogInDialog.java | 14 ++--- .../java/se/leap/bitmaskclient/OnBootReceiver.java | 5 +- .../main/java/se/leap/bitmaskclient/Provider.java | 12 ++-- .../se/leap/bitmaskclient/ProviderListAdapter.java | 4 +- .../leap/bitmaskclient/ProviderListFragment.java | 11 ++-- .../leap/bitmaskclient/SessionDialogInterface.java | 2 - .../java/se/leap/bitmaskclient/SignUpDialog.java | 12 ++-- .../java/se/leap/bitmaskclient/eip/Constants.java | 2 - .../main/java/se/leap/bitmaskclient/eip/EIP.java | 61 ++++++++++++------- .../java/se/leap/bitmaskclient/eip/EipStatus.java | 25 ++------ .../java/se/leap/bitmaskclient/eip/Gateway.java | 25 ++++---- .../se/leap/bitmaskclient/eip/GatewaySelector.java | 8 ++- .../se/leap/bitmaskclient/eip/VoidVpnService.java | 4 -- .../bitmaskclient/eip/VpnCertificateValidator.java | 9 +-- .../leap/bitmaskclient/eip/VpnConfigGenerator.java | 12 ++-- 21 files changed, 177 insertions(+), 188 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/AboutActivity.java b/app/src/main/java/se/leap/bitmaskclient/AboutActivity.java index 6d025422..6c4e517b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/AboutActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/AboutActivity.java @@ -1,15 +1,10 @@ package se.leap.bitmaskclient; import android.app.Activity; -import android.app.Fragment; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; import android.widget.TextView; -import se.leap.bitmaskclient.R; public class AboutActivity extends Activity { diff --git a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java index c95d0c8b..c0f0b0c3 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/ConfigHelper.java @@ -16,11 +16,15 @@ */ 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.lang.IllegalArgumentException; import java.security.KeyFactory; import java.security.KeyStore; import java.security.KeyStoreException; @@ -33,13 +37,6 @@ import java.security.interfaces.RSAPrivateKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; -import org.json.JSONException; -import org.json.JSONObject; - -import android.content.Context; -import android.content.SharedPreferences; -import android.util.Base64; - /** * Stores constants, and implements auxiliary methods used across all LEAP Android classes. * diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 4f6c6285..6288fd1f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -16,19 +16,31 @@ */ package se.leap.bitmaskclient; -import se.leap.bitmaskclient.*; -import se.leap.bitmaskclient.eip.*; - -import de.blinkt.openvpn.activities.LogWindow; - -import android.app.*; -import android.content.*; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.DialogFragment; +import android.app.FragmentTransaction; +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.*; +import android.os.Bundle; +import android.os.Handler; +import android.os.ResultReceiver; import android.util.Log; -import android.view.*; -import android.widget.*; -import org.json.*; +import android.view.Menu; +import android.view.MenuItem; +import android.widget.ProgressBar; +import android.widget.TextView; + +import org.json.JSONException; +import org.json.JSONObject; + +import de.blinkt.openvpn.activities.LogWindow; +import se.leap.bitmaskclient.eip.Constants; +import se.leap.bitmaskclient.eip.EIP; +import se.leap.bitmaskclient.eip.EipStatus; /** * The main user facing Activity of LEAP Android, consisting of status, controls, @@ -59,7 +71,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf private TextView status_message; public ProviderAPIResultReceiver providerAPI_result_receiver; - private static Provider provider; private static boolean authed_eip; @Override @@ -87,7 +98,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf try { int versionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode; int lastDetectedVersion = preferences.getInt(APP_VERSION, 0); - preferences.edit().putInt(APP_VERSION, versionCode); + preferences.edit().putInt(APP_VERSION, versionCode).apply(); Log.d("Dashboard", "detected version code: " + versionCode); Log.d("Dashboard", "last detected version code: " + lastDetectedVersion); @@ -102,6 +113,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf break; } } catch (NameNotFoundException e) { + Log.d(TAG, "Handle version didn't find any " + getPackageName() + " package"); } } @@ -121,13 +133,12 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf if ( requestCode == CONFIGURE_LEAP || requestCode == SWITCH_PROVIDER) { // It should be equivalent: if ( (requestCode == CONFIGURE_LEAP) || (data!= null && data.hasExtra(STOP_FIRST))) { if ( resultCode == RESULT_OK ){ - preferences.edit().putInt(Constants.PARSED_SERIAL, 0).commit(); - preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).commit(); + preferences.edit().putInt(Constants.PARSED_SERIAL, 0).apply(); + preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); updateEipService(); buildDashboard(false); invalidateOptionsMenu(); if(data != null && data.hasExtra(LogInDialog.TAG)) { - View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0); logInDialog(Bundle.EMPTY); } } else if(resultCode == RESULT_CANCELED && (data == null || data.hasExtra(ACTION_QUIT))) { @@ -158,7 +169,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf .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).commit(); + preferences.edit().remove(Provider.KEY).apply(); finish(); } }) @@ -170,7 +181,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf * service dependent UI elements to include. */ private void buildDashboard(boolean hide_and_turn_on_eip) { - provider = Provider.getInstance(); + Provider provider = Provider.getInstance(); provider.init( this ); setContentView(R.layout.client_dashboard); @@ -183,16 +194,17 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf if ( provider.hasEIP()){ - EipServiceFragment previous_eip_fragment = (EipServiceFragment)fragment_manager.findFragmentByTag(EipServiceFragment.TAG); - EipServiceFragment eipFragment = previous_eip_fragment == null ? - new EipServiceFragment() : previous_eip_fragment; + EipServiceFragment eipFragment = new EipServiceFragment(); + if (hide_and_turn_on_eip) { - preferences.edit().remove(Dashboard.START_ON_BOOT).commit(); + preferences.edit().remove(Dashboard.START_ON_BOOT).apply(); Bundle arguments = new Bundle(); arguments.putBoolean(EipServiceFragment.START_ON_BOOT, true); eipFragment.setArguments(arguments); } - fragment_manager.replace(R.id.servicesCollection, eipFragment, EipServiceFragment.TAG); + + fragment_manager.removePreviousFragment(EipServiceFragment.TAG); + fragment_manager.replace(R.id.servicesCollection, eipFragment, EipServiceFragment.TAG); if (hide_and_turn_on_eip) { onBackPressed(); @@ -205,12 +217,12 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf JSONObject provider_json; try { String provider_json_string = preferences.getString(Provider.KEY, ""); - if(provider_json_string.isEmpty() == false) { + 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); + preferences.edit().putBoolean(Constants.ALLOWED_REGISTERED, allow_registered_eip).apply(); if(allow_registered_eip) { if(authed_eip) { @@ -256,7 +268,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } eipStop(); } - preferences.edit().clear().commit(); + preferences.edit().clear().apply(); startActivityForResult(new Intent(this,ConfigurationWizard.class), SWITCH_PROVIDER); return true; case R.id.login_button: @@ -405,7 +417,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf invalidateOptionsMenu(); authed_eip = true; - preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).commit(); + preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); downloadAuthedUserCertificate(); } else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_FAILED) { @@ -420,7 +432,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf invalidateOptionsMenu(); authed_eip = false; - preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).commit(); + preferences.edit().putBoolean(Constants.AUTHED_EIP, authed_eip).apply(); } else if(resultCode == ProviderAPI.LOGOUT_FAILED) { changeStatusMessage(resultCode); diff --git a/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java b/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java index f78002b0..a44253c6 100644 --- a/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/DownloadFailedDialog.java @@ -16,9 +16,6 @@ */ package se.leap.bitmaskclient; -import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.NewProviderDialog.NewProviderDialogInterface; -import se.leap.bitmaskclient.ProviderListContent.ProviderItem; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; diff --git a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java index f29d1338..b896c00f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java @@ -1,19 +1,28 @@ package se.leap.bitmaskclient; -import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.ProviderAPIResultReceiver; -import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver; -import se.leap.bitmaskclient.eip.*; - -import de.blinkt.openvpn.activities.*; -import de.blinkt.openvpn.core.*; -import android.app.*; -import android.content.*; -import android.os.*; +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.*; -import android.widget.*; -import java.util.*; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CompoundButton; +import android.widget.Switch; +import android.widget.TextView; + +import java.util.Observable; +import java.util.Observer; + +import de.blinkt.openvpn.activities.DisconnectVPN; +import se.leap.bitmaskclient.eip.Constants; +import se.leap.bitmaskclient.eip.EIP; +import se.leap.bitmaskclient.eip.EipStatus; public class EipServiceFragment extends Fragment implements Observer, CompoundButton.OnCheckedChangeListener { @@ -26,7 +35,6 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu private View eipFragment; private static Switch eipSwitch; - private View eipDetail; private TextView status_message; private static Activity parent_activity; @@ -50,8 +58,8 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - eipFragment = inflater.inflate(R.layout.eip_service_fragment, container, false); - eipDetail = ((RelativeLayout) eipFragment.findViewById(R.id.eipDetail)); + eipFragment = inflater.inflate(R.layout.eip_service_fragment, container, false); + View eipDetail = eipFragment.findViewById(R.id.eipDetail); eipDetail.setVisibility(View.VISIBLE); View eipSettings = eipFragment.findViewById(R.id.eipSettings); @@ -213,7 +221,7 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu public void update (Observable observable, Object data) { Log.d(TAG, "handleNewState?"); if(observable instanceof EipStatus) { - this.eip_status = (EipStatus) observable; + eip_status = (EipStatus) observable; final EipStatus eip_status = (EipStatus) observable; parent_activity.runOnUiThread(new Runnable() { @Override @@ -284,14 +292,6 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu parent_activity.findViewById(R.id.eipProgress).setVisibility(View.GONE); } - public static EipStatus getEipStatus() { - return eip_status; - } - - public void checkEipSwitch(boolean activated) { - eipSwitch.setChecked(activated); - } - protected class EIPReceiver extends ResultReceiver { protected EIPReceiver(Handler handler){ @@ -303,21 +303,18 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu super.onReceiveResult(resultCode, resultData); String request = resultData.getString(Constants.REQUEST_TAG); - boolean checked = false; - - if (request == Constants.ACTION_START_EIP) { + + if (request.equals(Constants.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); break; case Activity.RESULT_CANCELED: - checked = false; eipFragment.findViewById(R.id.eipProgress).setVisibility(View.GONE); break; } - } else if (request == Constants.ACTION_STOP_EIP) { + } else if (request.equals(Constants.ACTION_STOP_EIP)) { switch (resultCode){ case Activity.RESULT_OK: Intent disconnect_vpn = new Intent(parent_activity, DisconnectVPN.class); @@ -325,20 +322,16 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu eip_status.setDisconnecting(); break; case Activity.RESULT_CANCELED: - checked = true; break; } - } else if (request == Constants.EIP_NOTIFICATION) { + } else if (request.equals(Constants.EIP_NOTIFICATION)) { switch (resultCode){ case Activity.RESULT_OK: - checked = true; break; case Activity.RESULT_CANCELED: - checked = false; break; } - } else if (request == Constants.ACTION_CHECK_CERT_VALIDITY) { - checked = eipSwitch.isChecked(); + } else if (request.equals(Constants.ACTION_CHECK_CERT_VALIDITY)) { switch (resultCode) { case Activity.RESULT_OK: break; diff --git a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java index a953a710..989dc395 100644 --- a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java +++ b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java @@ -17,13 +17,14 @@ package se.leap.bitmaskclient; +import org.jboss.security.srp.SRPParameters; + 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 org.jboss.security.srp.SRPParameters; /** * Implements all SRP algorithm logic. diff --git a/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java b/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java index 97a9aecc..5263392e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java @@ -16,19 +16,13 @@ */ package se.leap.bitmaskclient; -import se.leap.bitmaskclient.R; -import android.R.color; import android.app.Activity; import android.app.AlertDialog; import android.app.DialogFragment; import android.content.DialogInterface; -import android.content.res.ColorStateList; import android.os.Bundle; -import android.provider.CalendarContract.Colors; import android.view.LayoutInflater; import android.view.View; -import android.view.animation.AlphaAnimation; -import android.view.animation.BounceInterpolator; import android.widget.EditText; import android.widget.TextView; @@ -47,6 +41,8 @@ public class LogInDialog extends SessionDialogInterface { final public static String TAG = LogInDialog.class.getSimpleName(); + private static LogInDialog dialog; + private static boolean is_eip_pending = false; public AlertDialog onCreateDialog(Bundle savedInstanceState) { @@ -122,8 +118,10 @@ public class LogInDialog extends SessionDialogInterface { * @return a new instance of this DialogFragment. */ public static DialogFragment newInstance() { - LogInDialog dialog_fragment = new LogInDialog(); - return dialog_fragment; + if(dialog == null) + dialog = new LogInDialog(); + + return dialog; } @Override diff --git a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java index 74f89ab8..07ed6c8f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java +++ b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java @@ -1,7 +1,8 @@ package se.leap.bitmaskclient; -import android.content.*; -import android.util.Log; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; import se.leap.bitmaskclient.eip.Constants; diff --git a/app/src/main/java/se/leap/bitmaskclient/Provider.java b/app/src/main/java/se/leap/bitmaskclient/Provider.java index 8d6385e0..fa1a4fb5 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/Provider.java @@ -16,17 +16,17 @@ */ package se.leap.bitmaskclient; -import java.io.Serializable; -import java.util.Arrays; -import java.util.Locale; +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import android.content.Context; -import android.app.Activity; -import android.content.SharedPreferences; +import java.io.Serializable; +import java.util.Arrays; +import java.util.Locale; /** * @author Sean Leonard diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java b/app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java index 43bba085..1148e65e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderListAdapter.java @@ -1,7 +1,5 @@ package se.leap.bitmaskclient; -import java.util.List; - import android.content.Context; import android.view.LayoutInflater; import android.view.View; @@ -9,6 +7,8 @@ import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TwoLineListItem; +import java.util.List; + public class ProviderListAdapter extends ArrayAdapter { private static boolean[] hidden = null; diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderListFragment.java b/app/src/main/java/se/leap/bitmaskclient/ProviderListFragment.java index db414d87..e5baebc0 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderListFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderListFragment.java @@ -16,8 +16,6 @@ */ package se.leap.bitmaskclient; -import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.ProviderListContent.ProviderItem; import android.app.Activity; import android.app.ListFragment; import android.os.Bundle; @@ -26,11 +24,12 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ListView; +import se.leap.bitmaskclient.ProviderListContent.ProviderItem; + /** * A list fragment representing a list of Providers. This fragment * also supports tablet devices by allowing list items to be given an - * 'activated' state upon selection. This helps indicate which item is - * currently being viewed in a {@link DashboardFragment}. + * 'activated' state upon selection. *

* Activities containing this fragment MUST implement the {@link Callbacks} * interface. @@ -123,7 +122,7 @@ public class ProviderListFragment extends ListFragment { if(getArguments() != null && getArguments().containsKey(TOP_PADDING)) { int topPadding = getArguments().getInt(TOP_PADDING); View current_view = getView(); - getView().setPadding(current_view.getPaddingLeft(), topPadding, current_view.getPaddingRight(), current_view.getPaddingBottom()); + current_view.setPadding(current_view.getPaddingLeft(), topPadding, current_view.getPaddingRight(), current_view.getPaddingBottom()); } } @@ -215,7 +214,7 @@ public class ProviderListFragment extends ListFragment { real_count--; } else { i++; - } + } } public void unhideAll() { diff --git a/app/src/main/java/se/leap/bitmaskclient/SessionDialogInterface.java b/app/src/main/java/se/leap/bitmaskclient/SessionDialogInterface.java index 7b08a4d1..66b86ccd 100644 --- a/app/src/main/java/se/leap/bitmaskclient/SessionDialogInterface.java +++ b/app/src/main/java/se/leap/bitmaskclient/SessionDialogInterface.java @@ -17,10 +17,8 @@ package se.leap.bitmaskclient; import android.app.Activity; -import android.app.AlertDialog; import android.app.DialogFragment; import android.content.DialogInterface; -import android.os.Bundle; /** * @author parmegv diff --git a/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java b/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java index d197e589..f6d6cc3f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java @@ -16,19 +16,13 @@ */ package se.leap.bitmaskclient; -import se.leap.bitmaskclient.R; -import android.R.color; import android.app.Activity; import android.app.AlertDialog; import android.app.DialogFragment; import android.content.DialogInterface; -import android.content.res.ColorStateList; import android.os.Bundle; -import android.provider.CalendarContract.Colors; import android.view.LayoutInflater; import android.view.View; -import android.view.animation.AlphaAnimation; -import android.view.animation.BounceInterpolator; import android.widget.EditText; import android.widget.TextView; @@ -46,6 +40,7 @@ public class SignUpDialog extends SessionDialogInterface { final public static String TAG = SignUpDialog.class.getSimpleName(); + private static SignUpDialog dialog; private static boolean is_eip_pending = false; public AlertDialog onCreateDialog(Bundle savedInstanceState) { @@ -112,8 +107,9 @@ public class SignUpDialog extends SessionDialogInterface { * @return a new instance of this DialogFragment. */ public static DialogFragment newInstance() { - SignUpDialog dialog_fragment = new SignUpDialog(); - return dialog_fragment; + if(dialog == null) + dialog = new SignUpDialog(); + return dialog; } @Override 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 b710d780..e1a7e616 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java @@ -34,8 +34,6 @@ public interface Constants { public final static String ACTION_UPDATE_EIP_SERVICE = TAG + ".UPDATE_EIP_SERVICE"; public final static String ACTION_IS_EIP_RUNNING = TAG + ".IS_RUNNING"; public final static String EIP_NOTIFICATION = TAG + ".EIP_NOTIFICATION"; - public final static String STATUS = TAG + ".STATUS"; - public final static String DATE_FROM_CERTIFICATE = TAG + ".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"; 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 379fb246..5169ef62 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -16,22 +16,40 @@ */ package se.leap.bitmaskclient.eip; -import android.app.*; -import android.content.*; -import android.os.*; +import android.app.Activity; +import android.app.IntentService; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.os.ResultReceiver; import android.util.Log; -import java.io.*; -import java.security.cert.*; -import java.text.*; -import java.util.*; -import org.json.*; -import de.blinkt.openvpn.*; -import de.blinkt.openvpn.activities.*; -import de.blinkt.openvpn.core.*; -import se.leap.bitmaskclient.*; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; -import static se.leap.bitmaskclient.eip.Constants.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import de.blinkt.openvpn.LaunchVPN; +import de.blinkt.openvpn.VpnProfile; +import de.blinkt.openvpn.core.ProfileManager; +import se.leap.bitmaskclient.Dashboard; +import se.leap.bitmaskclient.EipServiceFragment; +import se.leap.bitmaskclient.Provider; + +import static se.leap.bitmaskclient.eip.Constants.ACTION_CHECK_CERT_VALIDITY; +import static se.leap.bitmaskclient.eip.Constants.ACTION_IS_EIP_RUNNING; +import static se.leap.bitmaskclient.eip.Constants.ACTION_START_EIP; +import static se.leap.bitmaskclient.eip.Constants.ACTION_STOP_EIP; +import static se.leap.bitmaskclient.eip.Constants.ACTION_UPDATE_EIP_SERVICE; +import static se.leap.bitmaskclient.eip.Constants.CERTIFICATE; +import static se.leap.bitmaskclient.eip.Constants.KEY; +import static se.leap.bitmaskclient.eip.Constants.PARSED_SERIAL; +import static se.leap.bitmaskclient.eip.Constants.RECEIVER_TAG; +import static se.leap.bitmaskclient.eip.Constants.REQUEST_TAG; /** * EIP is the abstract base class for interacting with and managing the Encrypted @@ -80,21 +98,21 @@ public final class EIP extends IntentService { String action = intent.getAction(); mReceiver = intent.getParcelableExtra(RECEIVER_TAG); - if ( action == ACTION_START_EIP ) + if ( action.equals(ACTION_START_EIP)) startEIP(); - else if ( action == ACTION_STOP_EIP ) + else if (action.equals(ACTION_STOP_EIP)) stopEIP(); - else if ( action == ACTION_IS_EIP_RUNNING ) + else if (action.equals(ACTION_IS_EIP_RUNNING)) isRunning(); - else if ( action == ACTION_UPDATE_EIP_SERVICE ) + else if (action.equals(ACTION_UPDATE_EIP_SERVICE)) updateEIPService(); - else if ( action == ACTION_CHECK_CERT_VALIDITY ) + 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 se.leap.openvpn.LaunchVPN}. + * Intent to {@link de.blinkt.openvpn.LaunchVPN}. * It also sets up early routes. */ private void startEIP() { @@ -164,8 +182,7 @@ public final class EIP extends IntentService { } /** - * Loads eip-service.json from SharedPreferences and calls {@link updateGateways()} - * to parse gateway definitions. + * Loads eip-service.json from SharedPreferences, delete previous vpn profiles and add new gateways. * TODO Implement API call to refresh eip-service.json from the provider */ private void updateEIPService() { @@ -210,7 +227,7 @@ public final class EIP extends IntentService { // TODO Auto-generated catch block e.printStackTrace(); } - preferences.edit().putInt(PARSED_SERIAL, eip_definition.optInt(Provider.API_RETURN_SERIAL)).commit(); + preferences.edit().putInt(PARSED_SERIAL, eip_definition.optInt(Provider.API_RETURN_SERIAL)).apply(); } private boolean isOpenVpnGateway(JSONObject gateway) { 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 82c3ceb8..4ac3bd6a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java @@ -17,18 +17,17 @@ package se.leap.bitmaskclient.eip; import android.util.Log; -import java.util.*; -import de.blinkt.openvpn.core.*; +import java.util.Observable; + +import de.blinkt.openvpn.core.VpnStatus; public class EipStatus extends Observable implements VpnStatus.StateListener { public static String TAG = EipStatus.class.getSimpleName(); private static EipStatus current_status; - private static EipStatus previous_status; private static VpnStatus.ConnectionStatus level = VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED; private static boolean wants_to_disconnect = false; - private static boolean is_disconnecting = false; private String state, log_message; private int localized_res_id; @@ -46,7 +45,6 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { @Override public void updateState(final String state, final String logmessage, final int localizedResId, final VpnStatus.ConnectionStatus level) { current_status = getInstance(); - previous_status = current_status; current_status.setState(state); current_status.setLogMessage(logmessage); current_status.setLocalizedResId(localizedResId); @@ -60,10 +58,6 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { current_status.notifyObservers(); } - public boolean isDisconnecting() { - return is_disconnecting; - } - public boolean wantsToDisconnect() { return wants_to_disconnect; } @@ -88,7 +82,6 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { } public void setConnecting() { - is_disconnecting = false; wants_to_disconnect = false; current_status.setChanged(); current_status.notifyObservers(); @@ -96,21 +89,15 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { public void setConnectedOrDisconnected() { Log.d(TAG, "setConnectedOrDisconnected()"); - is_disconnecting = false; wants_to_disconnect = false; current_status.setChanged(); current_status.notifyObservers(); } public void setDisconnecting() { - is_disconnecting = true; wants_to_disconnect = false; } - public void setWantsToDisconnect() { - wants_to_disconnect = true; - } - public String getState() { return state; } @@ -127,10 +114,6 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { return level; } - public EipStatus getPreviousStatus() { - return previous_status; - } - private void setState(String state) { this.state = state; } @@ -144,7 +127,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { } private void setLevel(VpnStatus.ConnectionStatus level) { - this.level = level; + EipStatus.level = level; } @Override 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 6aa66ac0..3ee9443c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java @@ -17,16 +17,22 @@ package se.leap.bitmaskclient.eip; import android.app.Activity; -import android.content.*; +import android.content.Context; +import android.content.SharedPreferences; import android.util.Log; -import java.io.*; -import java.util.*; -import org.json.*; -import de.blinkt.openvpn.*; -import de.blinkt.openvpn.activities.*; -import de.blinkt.openvpn.core.*; -import se.leap.bitmaskclient.*; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.io.StringReader; +import java.util.Collection; +import java.util.Iterator; + +import de.blinkt.openvpn.VpnProfile; +import de.blinkt.openvpn.core.ConfigParser; +import de.blinkt.openvpn.core.ProfileManager; +import se.leap.bitmaskclient.Dashboard; /** * Gateway provides objects defining gateways and their metadata. @@ -103,9 +109,8 @@ public class Gateway { private JSONObject getLocationInfo(JSONObject eip_definition) { try { JSONObject locations = eip_definition.getJSONObject("locations"); - JSONObject location = locations.getJSONObject(mGateway.getString("location")); - return location; + return locations.getJSONObject(mGateway.getString("location")); } catch (JSONException e) { return new JSONObject(); } 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 36b5fb41..39ae7ca6 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java @@ -1,8 +1,10 @@ package se.leap.bitmaskclient.eip; -import java.security.cert.*; -import java.util.*; -import org.json.*; +import java.util.Calendar; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.TreeMap; public class GatewaySelector { List gateways; 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 224e3bd4..a6f9fe76 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java @@ -1,11 +1,7 @@ package se.leap.bitmaskclient.eip; import android.content.Intent; -import android.os.Process; import android.net.VpnService; -import android.util.Log; - -import static se.leap.bitmaskclient.eip.Constants.*; public class VoidVpnService extends VpnService { 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 16ae6a85..6487f6c1 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java @@ -17,12 +17,13 @@ package se.leap.bitmaskclient.eip; import android.util.Log; -import java.util.*; -import java.security.cert.*; -import java.text.*; + +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; +import java.security.cert.X509Certificate; +import java.util.Calendar; import se.leap.bitmaskclient.ConfigHelper; -import static se.leap.bitmaskclient.eip.Constants.*; public class VpnCertificateValidator { public final static String TAG = VpnCertificateValidator.class.getSimpleName(); 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 8e36f53c..0c8e9a04 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -18,13 +18,14 @@ package se.leap.bitmaskclient.eip; import android.content.SharedPreferences; import android.util.Log; -import java.util.Iterator; -import java.util.Vector; + import org.json.JSONArray; -import org.json.JSONObject; import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Iterator; -import se.leap.bitmaskclient.*; +import se.leap.bitmaskclient.Provider; public class VpnConfigGenerator { @@ -38,7 +39,7 @@ public class VpnConfigGenerator { public VpnConfigGenerator(SharedPreferences preferences, JSONObject general_configuration, JSONObject gateway) { this.general_configuration = general_configuration; this.gateway = gateway; - this.preferences = preferences; + VpnConfigGenerator.preferences = preferences; } public String generate() { @@ -56,7 +57,6 @@ public class VpnConfigGenerator { String common_options = ""; try { Iterator keys = general_configuration.keys(); - Vector> value = new Vector>(); while ( keys.hasNext() ){ String key = keys.next().toString(); -- cgit v1.2.3 From ba682a453c4f188d57562d764635f1db7e2e1cab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 1 Dec 2014 17:13:26 +0100 Subject: Refresh gateways if the list is empty while starting eip. --- app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java | 1 - app/src/main/java/se/leap/bitmaskclient/eip/EIP.java | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java index b896c00f..592a9552 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java @@ -219,7 +219,6 @@ public class EipServiceFragment extends Fragment implements Observer, CompoundBu @Override public void update (Observable observable, Object data) { - Log.d(TAG, "handleNewState?"); if(observable instanceof EipStatus) { eip_status = (EipStatus) observable; final EipStatus eip_status = (EipStatus) observable; 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 5169ef62..a67eaccd 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -116,6 +116,8 @@ public final class EIP extends IntentService { * It also sets up early routes. */ private void startEIP() { + if(gateways.isEmpty()) + updateEIPService(); GatewaySelector gateway_selector = new GatewaySelector(gateways); activeGateway = gateway_selector.select(); if(activeGateway != null && activeGateway.getProfile() != null) { -- cgit v1.2.3 From b32fdf11b0ef473d489f9fb23f136fecf7051354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 1 Dec 2014 17:45:24 +0100 Subject: Restore eip fragment on screen orientation. --- app/src/main/java/se/leap/bitmaskclient/Dashboard.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 6288fd1f..8143d8d6 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -194,17 +194,19 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf if ( provider.hasEIP()){ - EipServiceFragment eipFragment = new EipServiceFragment(); + EipServiceFragment eip_fragment = (EipServiceFragment) fragment_manager.findFragmentByTag(EipServiceFragment.TAG); + if(eip_fragment == null) + eip_fragment = new EipServiceFragment(); if (hide_and_turn_on_eip) { preferences.edit().remove(Dashboard.START_ON_BOOT).apply(); Bundle arguments = new Bundle(); arguments.putBoolean(EipServiceFragment.START_ON_BOOT, true); - eipFragment.setArguments(arguments); + eip_fragment.setArguments(arguments); } fragment_manager.removePreviousFragment(EipServiceFragment.TAG); - fragment_manager.replace(R.id.servicesCollection, eipFragment, EipServiceFragment.TAG); + fragment_manager.replace(R.id.servicesCollection, eip_fragment, EipServiceFragment.TAG); if (hide_and_turn_on_eip) { onBackPressed(); -- cgit v1.2.3 From a59f2e0083b05fd94e2d0d2c1fcfeaa42b851531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 1 Dec 2014 19:52:54 +0100 Subject: Reordered EIP methods. Written basic skeleton for testEIP, renamed testDashboard to start, in the future, unit tests. --- app/src/main/java/se/leap/bitmaskclient/eip/EIP.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'app/src/main/java') 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 a67eaccd..b4208556 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -160,21 +160,12 @@ public final class EIP extends IntentService { tellToReceiver(ACTION_STOP_EIP, result_code); } - - private void tellToReceiver(String action, int resultCode) { - if (mReceiver != null){ - Bundle resultData = new Bundle(); - resultData.putString(REQUEST_TAG, action); - mReceiver.send(resultCode, resultData); - } - } /** * Checks the last stored status notified by ics-openvpn * Sends Activity.RESULT_CANCELED to the ResultReceiver that made the * request if it's not connected, Activity.RESULT_OK otherwise. */ - private void isRunning() { EipStatus eip_status = EipStatus.getInstance(); int resultCode = (eip_status.isConnected()) ? @@ -253,4 +244,12 @@ public final class EIP extends IntentService { Activity.RESULT_CANCELED; tellToReceiver(ACTION_CHECK_CERT_VALIDITY, resultCode); } + + private void tellToReceiver(String action, int resultCode) { + if (mReceiver != null){ + Bundle resultData = new Bundle(); + resultData.putString(REQUEST_TAG, action); + mReceiver.send(resultCode, resultData); + } + } } -- cgit v1.2.3