diff options
6 files changed, 127 insertions, 73 deletions
diff --git a/app/build.gradle b/app/build.gradle index f0ea5ac1..b5c50fa4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -44,6 +44,7 @@ dependencies { provided 'com.squareup.dagger:dagger-compiler:1.2.2+' compile 'com.github.pedrovgs:renderers:1.3+' compile 'com.intellij:annotations:12.0' + compile 'com.google.code.gson:gson:2+' } def processFileInplace(file, Closure processText) { diff --git a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java index a21e0cd1..54432033 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipFragment.java @@ -187,8 +187,8 @@ public class EipFragment extends Fragment implements Observer { if(!eip_switch.isChecked()) { eip_switch.setChecked(true); - saveStatus(); } + saveStatus(); eipCommand(Constants.ACTION_START_EIP); } diff --git a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java index 3b1033bc..96b87085 100644 --- a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java +++ b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java @@ -4,6 +4,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.util.Log; import se.leap.bitmaskclient.eip.Constants; @@ -17,6 +18,8 @@ public class OnBootReceiver extends BroadcastReceiver { preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Context.MODE_PRIVATE); boolean provider_configured = !preferences.getString(Provider.KEY, "").isEmpty(); boolean start_on_boot = preferences.getBoolean(Dashboard.START_ON_BOOT, false); + Log.d("OnBootReceiver", "Provider configured " + String.valueOf(provider_configured)); + Log.d("OnBootReceiver", "Start on boot " + String.valueOf(start_on_boot)); if(provider_configured && start_on_boot) { Intent dashboard_intent = new Intent(context, Dashboard.class); dashboard_intent.setAction(Constants.ACTION_START_EIP); 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 10d222c2..dcf36a82 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -25,10 +25,14 @@ import android.os.Bundle; import android.os.ResultReceiver; import android.util.Log; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; @@ -41,6 +45,7 @@ import de.blinkt.openvpn.core.Connection; import de.blinkt.openvpn.core.ProfileManager; import se.leap.bitmaskclient.Dashboard; import se.leap.bitmaskclient.EipFragment; +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; @@ -87,12 +92,14 @@ public final class EIP extends IntentService { super.onCreate(); context = getApplicationContext(); - profile_manager = ProfileManager.getInstance(context); + preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); - preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); - refreshEipDefinition(); + profile_manager = ProfileManager.getInstance(context); + eip_definition = eipDefinitionFromPreferences(); + if(gateways.isEmpty()) + gateways = gatewaysFromPreferences(); } - + @Override protected void onHandleIntent(Intent intent) { String action = intent.getAction(); @@ -122,6 +129,7 @@ public final class EIP extends IntentService { GatewaySelector gateway_selector = new GatewaySelector(gateways); gateway = gateway_selector.select(); + Log.d(TAG, "Connecting to " + gateway.getProfile().getUUIDString()); if(gateway != null && gateway.getProfile() != null) { mReceiver = EipFragment.getReceiver(); launchActiveGateway(); @@ -179,28 +187,42 @@ public final class EIP extends IntentService { * TODO Implement API call to refresh eip-service.json from the provider */ private void updateEIPService() { - refreshEipDefinition(); + eip_definition = eipDefinitionFromPreferences(); if(eip_definition != null) updateGateways(); tellToReceiver(ACTION_UPDATE_EIP_SERVICE, Activity.RESULT_OK); } - private void refreshEipDefinition() { + private JSONObject eipDefinitionFromPreferences() { try { String eip_definition_string = preferences.getString(KEY, ""); if(!eip_definition_string.isEmpty()) { - eip_definition = new JSONObject(eip_definition_string); + return new JSONObject(eip_definition_string); } } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } + return null; + } + + private List<Gateway> gatewaysFromPreferences() { + List<Gateway> result; + + String gateways_string = preferences.getString(Gateway.TAG, ""); + Log.d(TAG, "Recovering gateways: " + gateways_string); + Type type_list_gateways = new TypeToken<ArrayList<Gateway>>() {}.getType(); + result = gateways_string.isEmpty() ? + new ArrayList<Gateway>() + : (List<Gateway>) new Gson().fromJson(gateways_string, type_list_gateways); + Log.d(TAG, "Gateways from preferences = " + result.size()); + preferences.edit().remove(Gateway.TAG); + return result; } /** * 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(){ try { @@ -208,12 +230,15 @@ public final class EIP extends IntentService { for (int i = 0; i < gatewaysDefined.length(); i++) { JSONObject gw = gatewaysDefined.getJSONObject(i); if (isOpenVpnGateway(gw)) { - Gateway gateway = new Gateway(eip_definition, context, gw); - if(!containsProfileWithSecrets(gateway.getProfile())) { - addGateway(gateway); + JSONObject secrets = secretsConfiguration(); + Gateway aux = new Gateway(eip_definition, secrets, gw); + Log.d(TAG, "Possible new gateway: " + aux.getProfile().getUUIDString()); + if(!containsProfileWithSecrets(aux.getProfile())) { + addGateway(aux); } } } + gatewaysToPreferences(); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -229,6 +254,19 @@ public final class EIP extends IntentService { } } + + private JSONObject secretsConfiguration() { + JSONObject result = new JSONObject(); + try { + result.put(Provider.CA_CERT, preferences.getString(Provider.CA_CERT, "")); + result.put(Constants.PRIVATE_KEY, preferences.getString(Constants.PRIVATE_KEY, "")); + result.put(Constants.CERTIFICATE, preferences.getString(Constants.CERTIFICATE, "")); + } catch (JSONException e) { + e.printStackTrace(); + } + return result; + } + private void addGateway(Gateway gateway) { VpnProfile profile = gateway.getProfile(); removeGateway(gateway); @@ -247,10 +285,12 @@ public final class EIP extends IntentService { removeDuplicatedGateway(profile); } - private void removeDuplicatedProfile(VpnProfile remove) { - if(containsProfile(remove)) - profile_manager.removeProfile(context, duplicatedProfile(remove)); - if(containsProfile(remove)) removeDuplicatedProfile(remove); + private void removeDuplicatedProfile(VpnProfile original) { + if(containsProfile(original)) { + VpnProfile remove = duplicatedProfile(original); + profile_manager.removeProfile(context, remove); + Log.d(TAG, "Removing profile " + remove.getUUIDString()); + }if(containsProfile(original)) removeDuplicatedProfile(original); } private boolean containsProfile(VpnProfile profile) { @@ -264,16 +304,21 @@ public final class EIP extends IntentService { } private boolean containsProfileWithSecrets(VpnProfile profile) { - if(!containsProfile(profile)) return false; - - Collection<VpnProfile> profiles = profile_manager.getProfiles(); - for(VpnProfile aux : profiles) { - return profile.mClientCertFilename.equalsIgnoreCase(aux.mClientCertFilename) - && profile.mClientKeyFilename.equalsIgnoreCase(aux.mClientKeyFilename); - } - - return false; + boolean result = false; + + if(containsProfile(profile)) { + Collection<VpnProfile> profiles = profile_manager.getProfiles(); + for(VpnProfile aux : profiles) { + result = result == false ? + sameConnections(profile.mConnections, aux.mConnections) + && profile.mClientCertFilename.equalsIgnoreCase(aux.mClientCertFilename) + && profile.mClientKeyFilename.equalsIgnoreCase(aux.mClientKeyFilename) + : true; + } + } + return result; } + private VpnProfile duplicatedProfile(VpnProfile profile) { VpnProfile duplicated = null; Collection<VpnProfile> profiles = profile_manager.getProfiles(); @@ -304,12 +349,21 @@ public final class EIP extends IntentService { List<Gateway> gateways_to_remove = new ArrayList<>(); while(it.hasNext()) { Gateway aux = it.next(); - if(sameConnections(aux.getProfile().mConnections, profile.mConnections)) + if(sameConnections(aux.getProfile().mConnections, profile.mConnections)) { gateways_to_remove.add(aux); + Log.d(TAG, "Removing gateway " + aux.getProfile().getUUIDString()); + } } gateways.removeAll(gateways_to_remove); } + private void gatewaysToPreferences() { + Type type_list_gateways = new TypeToken<List<Gateway>>() {}.getType(); + String gateways_string = new Gson().toJson(gateways, type_list_gateways); + Log.d(TAG, "Saving gateways: " + gateways_string); + preferences.edit().putString(Gateway.TAG, gateways_string).apply(); + } + private void checkCertValidity() { VpnCertificateValidator validator = new VpnCertificateValidator(); int resultCode = validator.isValid(preferences.getString(CERTIFICATE, "")) ? 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 005d0eec..daf7d4a7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java @@ -17,7 +17,6 @@ package se.leap.bitmaskclient.eip; import android.app.Activity; -import android.content.Context; import android.content.SharedPreferences; import android.util.Log; @@ -25,14 +24,10 @@ import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; -import java.io.Serializable; 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; /** @@ -43,28 +38,26 @@ import se.leap.bitmaskclient.Dashboard; * @author Sean Leonard <meanderingcode@aetherislands.net> * @author Parménides GV <parmegv@sdf.org> */ -public class Gateway implements Serializable { - - private String TAG = Gateway.class.getSimpleName(); +public class Gateway { + public static String TAG = Gateway.class.getSimpleName(); + + private JSONObject general_configuration; + private JSONObject secrets; + private JSONObject gateway; + 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){ + protected Gateway(JSONObject eip_definition, JSONObject secrets, JSONObject gateway){ + + this.gateway = gateway; + this.secrets = secrets; - mGateway = gateway; - - this.context = context; general_configuration = getGeneralConfiguration(eip_definition); timezone = getTimezone(eip_definition); mName = locationAsName(eip_definition); @@ -95,7 +88,7 @@ public class Gateway implements Serializable { try { JSONObject locations = eip_definition.getJSONObject("locations"); - return locations.getJSONObject(mGateway.getString("location")); + return locations.getJSONObject(gateway.getString("location")); } catch (JSONException e) { return new JSONObject(); } @@ -108,8 +101,7 @@ public class Gateway implements Serializable { 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); + VpnConfigGenerator vpn_configuration_generator = new VpnConfigGenerator(general_configuration, secrets, gateway); String configuration = vpn_configuration_generator.generate(); cp.parseConfig(new StringReader(configuration)); 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 a320bee5..6f260f55 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -31,15 +31,15 @@ public class VpnConfigGenerator { private JSONObject general_configuration; private JSONObject gateway; - - private static SharedPreferences preferences; + private JSONObject secrets; + 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) { + public VpnConfigGenerator(JSONObject general_configuration, JSONObject secrets, JSONObject gateway) { this.general_configuration = general_configuration; this.gateway = gateway; - VpnConfigGenerator.preferences = preferences; + this.secrets = secrets; } public String generate() { @@ -113,29 +113,33 @@ public class VpnConfigGenerator { } private String secretsConfiguration() { - - String ca = - "<ca>" - + new_line - + preferences.getString(Provider.CA_CERT, "") - + new_line - + "</ca>"; - - String key = - "<key>" - + new_line - + preferences.getString(Constants.PRIVATE_KEY, "") - + new_line - + "</key>"; - - String openvpn_cert = - "<cert>" - + new_line - + preferences.getString(Constants.CERTIFICATE, "") - + new_line - + "</cert>"; + try { + String ca = + "<ca>" + + new_line + + secrets.getString(Provider.CA_CERT) + + new_line + + "</ca>"; + + String key = + "<key>" + + new_line + + secrets.getString(Constants.PRIVATE_KEY) + + new_line + + "</key>"; + + String openvpn_cert = + "<cert>" + + new_line + + secrets.getString(Constants.CERTIFICATE) + + new_line + + "</cert>"; - return ca + new_line + key + new_line + openvpn_cert; + return ca + new_line + key + new_line + openvpn_cert; + } catch(JSONException e) { + e.printStackTrace(); + return ""; + } } private String androidCustomizations() { |