From a74d09929575e44f86d09283ae4633b0dcfcb566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 6 Jan 2015 10:11:50 +0100 Subject: Extracted GatewaysManager + coded its tests --- .../main/java/se/leap/bitmaskclient/eip/EIP.java | 239 ++++----------------- .../java/se/leap/bitmaskclient/eip/Gateway.java | 11 +- .../se/leap/bitmaskclient/eip/GatewaysManager.java | 184 ++++++++++++++++ 3 files changed, 230 insertions(+), 204 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java (limited to 'app/src/main/java/se/leap') 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 a86b9c6a..a5cc817a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -16,46 +16,17 @@ */ package se.leap.bitmaskclient.eip; -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.app.*; +import android.content.*; +import android.os.*; import android.util.Log; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; +import org.json.*; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; +import de.blinkt.openvpn.*; +import se.leap.bitmaskclient.*; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; - -import de.blinkt.openvpn.LaunchVPN; -import de.blinkt.openvpn.VpnProfile; -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; -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.RECEIVER_TAG; -import static se.leap.bitmaskclient.eip.Constants.REQUEST_TAG; +import static se.leap.bitmaskclient.eip.Constants.*; /** * EIP is the abstract base class for interacting with and managing the Encrypted @@ -79,26 +50,25 @@ public final class EIP extends IntentService { private static SharedPreferences preferences; private static JSONObject eip_definition; - private static List gateways = new ArrayList<>(); - private static ProfileManager profile_manager; + private static GatewaysManager gateways_manager = new GatewaysManager(); private static Gateway gateway; - public EIP(){ - super(TAG); - } + public EIP(){ + super(TAG); + } - @Override - public void onCreate() { - super.onCreate(); + @Override + public void onCreate() { + super.onCreate(); - context = getApplicationContext(); + context = getApplicationContext(); preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE); - - profile_manager = ProfileManager.getInstance(context); - eip_definition = eipDefinitionFromPreferences(); - if(gateways.isEmpty()) - gateways = gatewaysFromPreferences(); - } + eip_definition = eipDefinitionFromPreferences(); + if(gateways_manager.isEmpty()) { + gateways_manager = new GatewaysManager(context, preferences); + gatewaysFromPreferences(); + } + } @Override protected void onHandleIntent(Intent intent) { @@ -123,18 +93,17 @@ public final class EIP extends IntentService { * It also sets up early routes. */ private void startEIP() { - if(gateways.isEmpty()) + if(gateways_manager.isEmpty()) updateEIPService(); earlyRoutes(); - GatewaySelector gateway_selector = new GatewaySelector(gateways); - gateway = gateway_selector.select(); + gateway = gateways_manager.select(); if(gateway != null && gateway.getProfile() != null) { mReceiver = EipFragment.getReceiver(); launchActiveGateway(); - tellToReceiver(ACTION_START_EIP, Activity.RESULT_OK); + tellToReceiver(ACTION_START_EIP, Activity.RESULT_OK); } else - tellToReceiver(ACTION_START_EIP, Activity.RESULT_CANCELED); + tellToReceiver(ACTION_START_EIP, Activity.RESULT_CANCELED); } /** @@ -184,173 +153,39 @@ public final class EIP extends IntentService { */ private void updateEIPService() { eip_definition = eipDefinitionFromPreferences(); - if(eip_definition != null) + if(eip_definition.length() > 0) updateGateways(); tellToReceiver(ACTION_UPDATE_EIP_SERVICE, Activity.RESULT_OK); } private JSONObject eipDefinitionFromPreferences() { + JSONObject result = new JSONObject(); try { String eip_definition_string = preferences.getString(KEY, ""); if(!eip_definition_string.isEmpty()) { - return new JSONObject(eip_definition_string); + result = new JSONObject(eip_definition_string); } } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } - return null; - } - - private List gatewaysFromPreferences() { - List result; - - String gateways_string = preferences.getString(Gateway.TAG, ""); - Type type_list_gateways = new TypeToken>() {}.getType(); - result = gateways_string.isEmpty() ? - new ArrayList() - : (List) new Gson().fromJson(gateways_string, type_list_gateways); - preferences.edit().remove(Gateway.TAG); - return result; - } - - /** - * Walk the list of gateways defined in eip-service.json and parse them into - * Gateway objects. - */ - private void updateGateways(){ - try { - JSONArray gatewaysDefined = eip_definition.getJSONArray("gateways"); - for (int i = 0; i < gatewaysDefined.length(); i++) { - JSONObject gw = gatewaysDefined.getJSONObject(i); - if (isOpenVpnGateway(gw)) { - JSONObject secrets = secretsConfiguration(); - Gateway aux = new Gateway(eip_definition, secrets, gw); - if(!containsProfileWithSecrets(aux.getProfile())) { - addGateway(aux); - } - } - } - gatewaysToPreferences(); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - private boolean isOpenVpnGateway(JSONObject gateway) { - try { - String transport = gateway.getJSONObject("capabilities").getJSONArray("transport").toString(); - return transport.contains("openvpn"); - } catch (JSONException e) { - return false; - } - } - - - 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); - - profile_manager.addProfile(profile); - profile_manager.saveProfile(context, profile); - profile_manager.saveProfileList(context); - - gateways.add(gateway); - } - - private void removeGateway(Gateway gateway) { - VpnProfile profile = gateway.getProfile(); - removeDuplicatedProfile(profile); - removeDuplicatedGateway(profile); - } - - private void removeDuplicatedProfile(VpnProfile original) { - if(containsProfile(original)) { - VpnProfile remove = duplicatedProfile(original); - profile_manager.removeProfile(context, remove); - }if(containsProfile(original)) removeDuplicatedProfile(original); - } - - private boolean containsProfile(VpnProfile profile) { - Collection profiles = profile_manager.getProfiles(); - for(VpnProfile aux : profiles) { - if (sameConnections(profile.mConnections, aux.mConnections)) { - return true; - } - } - return false; - } - - private boolean containsProfileWithSecrets(VpnProfile profile) { - boolean result = false; - - if(containsProfile(profile)) { - Collection 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 profiles = profile_manager.getProfiles(); - for(VpnProfile aux : profiles) { - if (sameConnections(profile.mConnections, aux.mConnections)) { - duplicated = aux; - } - } - if(duplicated != null) return duplicated; - else throw new NoSuchElementException(profile.getName()); - } - - private boolean sameConnections(Connection[] c1, Connection[] c2) { - int same_connections = 0; - for(Connection c1_aux : c1) { - for(Connection c2_aux : c2) - if(c2_aux.mServerName.equals(c1_aux.mServerName)) { - same_connections++; - break; - } - } - return c1.length == c2.length && c1.length == same_connections; - + private void updateGateways(){ + gateways_manager.fromEipServiceJson(eip_definition); + gatewaysToPreferences(); } - private void removeDuplicatedGateway(VpnProfile profile) { - Iterator it = gateways.iterator(); - List gateways_to_remove = new ArrayList<>(); - while(it.hasNext()) { - Gateway aux = it.next(); - if(sameConnections(aux.getProfile().mConnections, profile.mConnections)) { - gateways_to_remove.add(aux); - } - } - gateways.removeAll(gateways_to_remove); + private void gatewaysFromPreferences() { + String gateways_string = preferences.getString(Gateway.TAG, ""); + gateways_manager.addFromString(gateways_string); + preferences.edit().remove(Gateway.TAG).apply(); } private void gatewaysToPreferences() { - Type type_list_gateways = new TypeToken>() {}.getType(); - String gateways_string = new Gson().toJson(gateways, type_list_gateways); - preferences.edit().putString(Gateway.TAG, gateways_string).apply(); + String gateways_string = gateways_manager.toString(); + preferences.edit().putString(Gateway.TAG, gateways_string).commit(); } private void checkCertValidity() { 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 daf7d4a7..0d8a2f7b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java @@ -20,6 +20,8 @@ import android.app.Activity; import android.content.SharedPreferences; import android.util.Log; +import com.google.gson.Gson; + import org.json.JSONException; import org.json.JSONObject; @@ -40,7 +42,7 @@ import se.leap.bitmaskclient.Dashboard; */ public class Gateway { - public static String TAG = Gateway.class.getSimpleName(); + public final static String TAG = Gateway.class.getSimpleName(); private JSONObject general_configuration; private JSONObject secrets; @@ -53,7 +55,7 @@ public class Gateway { * Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json * and create a VpnProfile belonging to it. */ - protected Gateway(JSONObject eip_definition, JSONObject secrets, JSONObject gateway){ + public Gateway(JSONObject eip_definition, JSONObject secrets, JSONObject gateway){ this.gateway = gateway; this.secrets = secrets; @@ -130,4 +132,9 @@ public class Gateway { public int getTimezone() { return timezone; } + + @Override + public String toString() { + return new Gson().toJson(this, Gateway.class); + } } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java new file mode 100644 index 00000000..b1aa5a2f --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -0,0 +1,184 @@ +/** + * Copyright (c) 2013, 2014, 2015 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.*; +import android.util.Log; + +import com.google.gson.*; +import com.google.gson.reflect.*; + +import org.json.*; + +import java.lang.reflect.*; +import java.util.*; + +import de.blinkt.openvpn.*; +import de.blinkt.openvpn.core.*; +import se.leap.bitmaskclient.*; + +/** + * @author parmegv + */ +public class GatewaysManager { + + private Context context; + private SharedPreferences preferences; + private List gateways = new ArrayList<>(); + private ProfileManager profile_manager; + private Type list_type = new TypeToken>() {}.getType(); + + public GatewaysManager() {} + + public GatewaysManager(Context context, SharedPreferences preferences) { + this.context = context; + this.preferences = preferences; + profile_manager = ProfileManager.getInstance(context); + } + public Gateway select() { + GatewaySelector gateway_selector = new GatewaySelector(gateways); + return gateway_selector.select(); + } + + public boolean isEmpty() { + return gateways.isEmpty(); + } + + public int size() { + return gateways.size(); + } + + public void addFromString(String gateways) { + List gateways_list = new ArrayList(); + try { + gateways_list = new Gson().fromJson(gateways, list_type); + } catch(JsonSyntaxException e) { + gateways_list.add(new Gson().fromJson(gateways, Gateway.class)); + } + + if(gateways_list != null) { + for (Gateway gateway : gateways_list) + removeDuplicatedGateway(gateway); + this.gateways.addAll(gateways_list); + } else + Log.d("GatewaysManager", "No gateways added"); + } + + @Override + public String toString() { + return new Gson().toJson(gateways, list_type); + } + + public void fromEipServiceJson(JSONObject eip_definition) { + try { + JSONArray gatewaysDefined = eip_definition.getJSONArray("gateways"); + for (int i = 0; i < gatewaysDefined.length(); i++) { + JSONObject gw = gatewaysDefined.getJSONObject(i); + if (isOpenVpnGateway(gw)) { + JSONObject secrets = secretsConfiguration(); + Gateway aux = new Gateway(eip_definition, secrets, gw); + if(!containsProfileWithSecrets(aux.getProfile())) { + addGateway(aux); + } + } + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + private boolean isOpenVpnGateway(JSONObject gateway) { + try { + String transport = gateway.getJSONObject("capabilities").getJSONArray("transport").toString(); + return transport.contains("openvpn"); + } catch (JSONException e) { + return false; + } + } + + 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 boolean containsProfileWithSecrets(VpnProfile profile) { + boolean result = false; + + Collection profiles = profile_manager.getProfiles(); + for(VpnProfile aux : profiles) { + result = result || sameConnections(profile.mConnections, aux.mConnections) + && profile.mClientCertFilename.equalsIgnoreCase(aux.mClientCertFilename) + && profile.mClientKeyFilename.equalsIgnoreCase(aux.mClientKeyFilename); + } + return result; + } + + private void addGateway(Gateway gateway) { + removeDuplicatedGateway(gateway); + + gateways.add(gateway); + + VpnProfile profile = gateway.getProfile(); + profile_manager.addProfile(profile); + //profile_manager.saveProfile(context, profile); + //profile_manager.saveProfileList(context); + } + + private void removeDuplicatedGateway(Gateway gateway) { + Iterator it = gateways.iterator(); + List gateways_to_remove = new ArrayList<>(); + while(it.hasNext()) { + Gateway aux = it.next(); + if(sameConnections(aux.getProfile().mConnections, gateway.getProfile().mConnections)) { + gateways_to_remove.add(aux); + } + } + gateways.removeAll(gateways_to_remove); + removeDuplicatedProfiles(gateway.getProfile()); + } + + private void removeDuplicatedProfiles(VpnProfile original) { + Collection profiles = profile_manager.getProfiles(); + List remove_list = new ArrayList<>(); + for(VpnProfile aux : profiles) { + if (sameConnections(original.mConnections, aux.mConnections)) + remove_list.add(aux); + } + for (VpnProfile profile : remove_list) + profile_manager.removeProfile(context, profile); + } + + private boolean sameConnections(Connection[] c1, Connection[] c2) { + int same_connections = 0; + for(Connection c1_aux : c1) { + for(Connection c2_aux : c2) + if(c2_aux.mServerName.equals(c1_aux.mServerName)) { + same_connections++; + break; + } + } + return c1.length == c2.length && c1.length == same_connections; + } +} -- cgit v1.2.3