summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorParménides GV <parmegv@sdf.org>2014-11-17 22:17:01 +0100
committerParménides GV <parmegv@sdf.org>2014-11-26 13:00:28 +0100
commit06bc3b1898e1a419693c7fc3d6a48322ad6881e6 (patch)
tree1c84bc3f27623825f2f3c8d8a079a1e91eb836ad
parent5d28fc6602a214da51931e428112825117b2509f (diff)
OVPNGateway extracted from EIP.
Fixed a silly typo on .gitignore which was ignoring "G*"!.
-rw-r--r--.gitignore1
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/GetRestrictionReceiver.java47
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EIP.java172
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java151
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java44
-rw-r--r--ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/GetRestrictionReceiver.java47
6 files changed, 324 insertions, 138 deletions
diff --git a/.gitignore b/.gitignore
index 804337f0..6702a070 100644
--- a/.gitignore
+++ b/.gitignore
@@ -75,7 +75,6 @@ gradle.properties*
build
.gradle
jniLibs
-G*
*.dot
/ics-openvpn/
/TAGS
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<RestrictionEntry> restrictionEntries = initRestrictions(context);
+
+ extras.putParcelableArrayList(Intent.EXTRA_RESTRICTIONS_LIST, restrictionEntries);
+ result.setResult(Activity.RESULT_OK,null,extras);
+ result.finish();
+ }
+ }.run();
+ }
+
+ private ArrayList<RestrictionEntry> initRestrictions(Context context) {
+ ArrayList<RestrictionEntry> restrictions = new ArrayList<RestrictionEntry>();
+ 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<Gateway> gateways = new ArrayList<Gateway>();
+ 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<VpnProfile> profiles = vpl.getProfiles();
+ Collection<VpnProfile> 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 <meanderingcode@aetherislands.net>
- */
- private class OVPNGateway {
-
- private String TAG = "OVPNGateway";
-
- private String mName;
- private VpnProfile mVpnProfile;
- private JSONObject mGateway;
- private HashMap<String,Vector<Vector<String>>> options = new HashMap<String, Vector<Vector<String>>>();
-
-
- /**
- * 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<VpnProfile> profiles = vpl.getProfiles();
- for (Iterator<VpnProfile> 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 <http://www.gnu.org/licenses/>.
+ */
+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 <meanderingcode@aetherislands.net>
+ * @author Parménides GV <parmegv@sdf.org>
+ */
+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<VpnProfile> profiles = vpl.getProfiles();
+ for (Iterator<VpnProfile> 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<Gateway> gateways;
+
+ public GatewaySelector(List<Gateway> gateways) {
+ this.gateways = gateways;
+ }
+
+ public Gateway select() {
+ return closestGateway();
+ }
+
+ private Gateway closestGateway() {
+ TreeMap<Integer, Set<Gateway>> offsets = calculateOffsets();
+ return offsets.isEmpty() ? null : offsets.firstEntry().getValue().iterator().next();
+ }
+
+ private TreeMap<Integer, Set<Gateway>> calculateOffsets() {
+ TreeMap<Integer, Set<Gateway>> offsets = new TreeMap<Integer, Set<Gateway>>();
+ int localOffset = Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000;
+ for(Gateway gateway : gateways) {
+ int dist = timezoneDistance(localOffset, gateway.getTimezone());
+ Set<Gateway> set = (offsets.get(dist) != null) ?
+ offsets.get(dist) : new HashSet<Gateway>();
+ set.add(gateway);
+ offsets.put(dist, set);
+ }
+ return offsets;
+ }
+
+ 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;
+ }
+}
diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/GetRestrictionReceiver.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/GetRestrictionReceiver.java
new file mode 100644
index 00000000..5b1dda58
--- /dev/null
+++ b/ics-openvpn-stripped/main/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<RestrictionEntry> restrictionEntries = initRestrictions(context);
+
+ extras.putParcelableArrayList(Intent.EXTRA_RESTRICTIONS_LIST, restrictionEntries);
+ result.setResult(Activity.RESULT_OK,null,extras);
+ result.finish();
+ }
+ }.run();
+ }
+
+ private ArrayList<RestrictionEntry> initRestrictions(Context context) {
+ ArrayList<RestrictionEntry> restrictions = new ArrayList<RestrictionEntry>();
+ RestrictionEntry allowChanges = new RestrictionEntry("allow_changes",false);
+ allowChanges.setTitle(context.getString(R.string.allow_vpn_changes));
+ restrictions.add(allowChanges);
+
+ return restrictions;
+ }
+}