summaryrefslogtreecommitdiff
path: root/app/src/main/java/se
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/se')
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java10
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java145
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java35
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/DispatcherOptions.java18
5 files changed, 123 insertions, 87 deletions
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 b1554af0..50fe74b7 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
@@ -114,7 +114,7 @@ public class Gateway {
try {
VpnConfigGenerator vpnConfigurationGenerator = new VpnConfigGenerator(generalConfiguration, secrets, gateway, apiVersion);
return vpnConfigurationGenerator.generateVpnProfile();
- } catch (ConfigParser.ConfigParseError | IOException | CloneNotSupportedException | JSONException e) {
+ } catch (ConfigParser.ConfigParseError | IOException | JSONException e) {
// FIXME We didn't get a VpnProfile! Error handling! and log level
e.printStackTrace();
return null;
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
index c650938c..cd3ec1c6 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
@@ -99,12 +99,10 @@ public class GatewaysManager {
int apiVersion = eipDefinition.getInt(VERSION);
for (int i = 0; i < gatewaysDefined.length(); i++) {
JSONObject gw = gatewaysDefined.getJSONObject(i);
- if (isOpenVpnGateway(gw, apiVersion)) {
- JSONObject secrets = secretsConfiguration();
- Gateway aux = new Gateway(eipDefinition, secrets, gw);
- if (!gateways.contains(aux)) {
- addGateway(aux);
- }
+ JSONObject secrets = secretsConfiguration();
+ Gateway aux = new Gateway(eipDefinition, secrets, gw);
+ if (!gateways.contains(aux)) {
+ addGateway(aux);
}
}
} catch (JSONException e) {
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 7f09d21e..a131bdd8 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
@@ -27,9 +27,11 @@ import java.util.Iterator;
import de.blinkt.openvpn.VpnProfile;
import de.blinkt.openvpn.core.ConfigParser;
import de.blinkt.openvpn.core.connection.Connection;
-import de.blinkt.openvpn.core.connection.Obfs4Connection;
import se.leap.bitmaskclient.Provider;
+import se.leap.bitmaskclient.pluggableTransports.DispatcherOptions;
+import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4;
+import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN;
import static se.leap.bitmaskclient.Constants.CAPABILITIES;
import static se.leap.bitmaskclient.Constants.IP_ADDRESS;
import static se.leap.bitmaskclient.Constants.OPTIONS;
@@ -40,9 +42,10 @@ import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.Constants.REMOTE;
import static se.leap.bitmaskclient.Constants.TRANSPORT;
import static se.leap.bitmaskclient.Constants.TYPE;
+import static se.leap.bitmaskclient.pluggableTransports.Dispatcher.DISPATCHER_IP;
+import static se.leap.bitmaskclient.pluggableTransports.Dispatcher.DISPATCHER_PORT;
public class VpnConfigGenerator {
-
private JSONObject generalConfiguration;
private JSONObject gateway;
private JSONObject secrets;
@@ -66,18 +69,14 @@ public class VpnConfigGenerator {
public void checkCapabilities() {
try {
- switch (apiVersion) {
- case 2:
- JSONArray supportedTransports = gateway.getJSONObject(CAPABILITIES).getJSONArray(TRANSPORT);
- for (int i = 0; i < supportedTransports.length(); i++) {
- JSONObject transport = supportedTransports.getJSONObject(i);
- if (transport.getString(TYPE).equals("obfs4")) {
- obfs4Transport = transport;
- }
+ if (apiVersion == 2) {
+ JSONArray supportedTransports = gateway.getJSONObject(CAPABILITIES).getJSONArray(TRANSPORT);
+ for (int i = 0; i < supportedTransports.length(); i++) {
+ JSONObject transport = supportedTransports.getJSONObject(i);
+ if (transport.getString(TYPE).equals(OBFS4.toString())) {
+ obfs4Transport = transport;
}
- break;
- default:
- break;
+ }
}
} catch (JSONException e) {
@@ -88,54 +87,45 @@ public class VpnConfigGenerator {
public VpnProfile generateVpnProfile() throws IllegalStateException,
IOException,
ConfigParser.ConfigParseError,
- CloneNotSupportedException,
- JSONException,
- NumberFormatException {
+ NumberFormatException, JSONException {
- VpnProfile profile = createOvpnProfile();
if (supportsObfs4()) {
- addPluggableTransportConnections(profile);
+ return createProfile(OBFS4);
}
- return profile;
+
+ return createProfile(OPENVPN);
}
private boolean supportsObfs4(){
return obfs4Transport != null;
}
- private void addPluggableTransportConnections(VpnProfile profile) throws JSONException, CloneNotSupportedException {
- JSONArray ports = obfs4Transport.getJSONArray(PORTS);
- Connection[] updatedConnections = new Connection[profile.mConnections.length + ports.length()];
-
- for (int i = 0; i < ports.length(); i++) {
- String port = ports.getString(i);
- Obfs4Connection obfs4Connection = new Obfs4Connection();
- obfs4Connection.setObfs4RemoteProxyName(gateway.getString(IP_ADDRESS));
- obfs4Connection.setObfs4RemoteProxyPort(port);
- obfs4Connection.setTransportOptions(obfs4Transport.optJSONObject(OPTIONS));
- updatedConnections[i] = obfs4Connection;
- }
- int k = 0;
- for (int i = ports.length(); i < updatedConnections.length; i++, k++) {
- updatedConnections[i] = profile.mConnections[k].clone();
- }
- profile.mConnections = updatedConnections;
- }
-
- private String getConfigurationString() {
+ private String getConfigurationString(Connection.TransportType transportType) {
return generalConfiguration()
- + newLine
- + ovpnGatewayConfiguration()
- + newLine
- + secretsConfiguration()
- + newLine
- + androidCustomizations();
+ + newLine
+ + gatewayConfiguration(transportType)
+ + newLine
+ + androidCustomizations()
+ + newLine
+ + secretsConfiguration();
}
- private VpnProfile createOvpnProfile() throws IOException, ConfigParser.ConfigParseError {
- String configuration = getConfigurationString();
+ private VpnProfile createProfile(Connection.TransportType transportType) throws IOException, ConfigParser.ConfigParseError, JSONException {
+ String configuration = getConfigurationString(transportType);
icsOpenvpnConfigParser.parseConfig(new StringReader(configuration));
- return icsOpenvpnConfigParser.convertProfile();
+ if (transportType == OBFS4) {
+ icsOpenvpnConfigParser.setDispatcherOptions(getDispatcherOptions());
+ }
+ return icsOpenvpnConfigParser.convertProfile(transportType);
+ }
+
+ private DispatcherOptions getDispatcherOptions() throws JSONException {
+ JSONObject transportOptions = obfs4Transport.getJSONObject(OPTIONS);
+ String iatMode = transportOptions.getString("iat-mode");
+ String cert = transportOptions.getString("cert");
+ String port = obfs4Transport.getJSONArray(PORTS).getString(0);
+ String ip = gateway.getString(IP_ADDRESS);
+ return new DispatcherOptions(ip, port, cert, iatMode);
}
private String generalConfiguration() {
@@ -161,21 +151,21 @@ public class VpnConfigGenerator {
return commonOptions;
}
- private String ovpnGatewayConfiguration() {
+ private String gatewayConfiguration(Connection.TransportType transportType) {
String remotes = "";
StringBuilder stringBuilder = new StringBuilder();
try {
String ipAddress = gateway.getString(IP_ADDRESS);
JSONObject capabilities = gateway.getJSONObject(CAPABILITIES);
- JSONArray transports = capabilities.getJSONArray(TRANSPORT);
switch (apiVersion) {
default:
case 1:
- ovpnGatewayConfigApiv1(stringBuilder, ipAddress, capabilities);
+ gatewayConfigApiv1(stringBuilder, ipAddress, capabilities);
break;
case 2:
- ovpnGatewayConfigApiv2(stringBuilder, ipAddress, transports);
+ JSONArray transports = capabilities.getJSONArray(TRANSPORT);
+ gatewayConfigApiv2(transportType, stringBuilder, ipAddress, transports);
break;
}
} catch (JSONException e) {
@@ -190,10 +180,17 @@ public class VpnConfigGenerator {
return remotes;
}
- private void ovpnGatewayConfigApiv1(StringBuilder stringBuilder, String ipAddress, JSONObject capabilities) throws JSONException {
+ private void gatewayConfigApiv2(Connection.TransportType transportType, StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException {
+ if (transportType == OBFS4) {
+ obfs4GatewayConfigApiv2(stringBuilder, ipAddress, transports);
+ } else {
+ ovpnGatewayConfigApi2(stringBuilder, ipAddress, transports);
+ }
+ }
+
+ private void gatewayConfigApiv1(StringBuilder stringBuilder, String ipAddress, JSONObject capabilities) throws JSONException {
int port;
String protocol;
-
JSONArray ports = capabilities.getJSONArray(PORTS);
for (int i = 0; i < ports.length(); i++) {
port = ports.getInt(i);
@@ -206,27 +203,41 @@ public class VpnConfigGenerator {
}
}
- private void ovpnGatewayConfigApiv2(StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException {
+ private void ovpnGatewayConfigApi2(StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException {
String port;
String protocol;
+ JSONObject openvpnTransport = getTransport(transports, OPENVPN);
+ JSONArray ports = openvpnTransport.getJSONArray(PORTS);
+ for (int j = 0; j < ports.length(); j++) {
+ port = ports.getString(j);
+ JSONArray protocols = openvpnTransport.getJSONArray(PROTOCOLS);
+ for (int k = 0; k < protocols.length(); k++) {
+ protocol = protocols.optString(k);
+ String newRemote = REMOTE + " " + ipAddress + " " + port + " " + protocol + newLine;
+ stringBuilder.append(newRemote);
+ }
+ }
+ }
+
+ private JSONObject getTransport(JSONArray transports, Connection.TransportType transportType) throws JSONException {
+ JSONObject selectedTransport = new JSONObject();
for (int i = 0; i < transports.length(); i++) {
JSONObject transport = transports.getJSONObject(i);
- if (!transport.getString(TYPE).equals("openvpn")) {
- continue;
- }
- JSONArray ports = transport.getJSONArray(PORTS);
- for (int j = 0; j < ports.length(); j++) {
- port = ports.getString(j);
- JSONArray protocols = transport.getJSONArray(PROTOCOLS);
- for (int k = 0; k < protocols.length(); k++) {
- protocol = protocols.optString(k);
- String newRemote = REMOTE + " " + ipAddress + " " + port + " " + protocol + newLine;
- stringBuilder.append(newRemote);
- }
+ if (transport.getString(TYPE).equals(transportType.toString())) {
+ selectedTransport = transport;
+ break;
}
}
+ return selectedTransport;
}
+ private void obfs4GatewayConfigApiv2(StringBuilder stringBuilder, String ipAddress, JSONArray transports) throws JSONException {
+ JSONObject obfs4Transport = getTransport(transports, OBFS4);
+ String route = "route " + ipAddress + " 255.255.255.255 net_gateway" + newLine;
+ stringBuilder.append(route);
+ String remote = REMOTE + " " + DISPATCHER_IP + " " + DISPATCHER_PORT + " " + obfs4Transport.getJSONArray(PROTOCOLS).getString(0) + newLine;
+ stringBuilder.append(remote);
+ }
private String secretsConfiguration() {
try {
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java
index 05ce2256..240dae75 100644
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Dispatcher.java
@@ -18,13 +18,13 @@ package se.leap.bitmaskclient.pluggableTransports;
import android.content.Context;
import android.support.annotation.WorkerThread;
+import android.text.TextUtils;
import android.util.Log;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
-import java.util.NoSuchElementException;
import java.util.StringTokenizer;
@@ -34,7 +34,8 @@ import java.util.StringTokenizer;
public class Dispatcher {
private static final String ASSET_KEY = "piedispatcher";
- private static final String DISPATCHER_PORT = "4430";
+ public static final String DISPATCHER_PORT = "4430";
+ public static final String DISPATCHER_IP = "127.0.0.1";
private static final String TAG = Dispatcher.class.getName();
private final String remoteIP;
private final String remotePort;
@@ -43,14 +44,14 @@ public class Dispatcher {
private File fileDispatcher;
private Context context;
private Thread dispatcherThread = null;
- private int dipatcherPid = -1;
+ private int dispatcherPid = -1;
- public Dispatcher(Context context, String remoteIP, String remotePort, String certificate, String iatMode) {
+ public Dispatcher(Context context, DispatcherOptions dispatcherOptions) {
this.context = context.getApplicationContext();
- this.remoteIP = remoteIP;
- this.remotePort = remotePort;
- this.certificate = certificate;
- this.iatMode = iatMode;
+ this.remoteIP = dispatcherOptions.remoteIP;
+ this.remotePort = dispatcherOptions.remotePort;
+ this.certificate = dispatcherOptions.cert;
+ this.iatMode = dispatcherOptions.iatMode;
}
@WorkerThread
@@ -70,7 +71,7 @@ public class Dispatcher {
" -transports obfs4" +
" -options \"" + String.format("{\\\"cert\\\": \\\"%s\\\", \\\"iatMode\\\": \\\"%s\\\"}\"", certificate, iatMode) +
" -logLevel DEBUG -enableLogging" +
- " -proxylistenaddr 127.0.0.1:" + DISPATCHER_PORT;
+ " -proxylistenaddr "+ DISPATCHER_IP + ":" + DISPATCHER_PORT;
Log.d(TAG, "dispatcher command: " + dispatcherCommand);
runBlockingCmd(new String[]{dispatcherCommand}, dispatcherLog);
@@ -82,14 +83,22 @@ public class Dispatcher {
});
dispatcherThread.start();
- // get pid of dispatcher
+ // get pid of dispatcher, try several times in case the dispatcher
+ // process is not spawned yet
StringBuilder log = new StringBuilder();
String pidCommand = "ps | grep piedispatcher";
- runBlockingCmd(new String[]{pidCommand}, log);
+ for (int i = 0; i < 5; i++) {
+ runBlockingCmd(new String[]{pidCommand}, log);
+ if (!TextUtils.isEmpty(log)) {
+ break;
+ }
+ Thread.sleep(100);
+ }
+
String output = log.toString();
StringTokenizer st = new StringTokenizer(output, " ");
st.nextToken(); // proc owner
- dipatcherPid = Integer.parseInt(st.nextToken().trim());
+ dispatcherPid = Integer.parseInt(st.nextToken().trim());
} catch(Exception e){
if (dispatcherThread.isAlive()) {
Log.e(TAG, e.getMessage() + ". Shutting down Dispatcher thread.");
@@ -106,7 +115,7 @@ public class Dispatcher {
Log.d(TAG, "Shutting down Dispatcher thread.");
if (dispatcherThread != null && dispatcherThread.isAlive()) {
try {
- killProcess(dipatcherPid);
+ killProcess(dispatcherPid);
} catch (Exception e) {
e.printStackTrace();
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/DispatcherOptions.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/DispatcherOptions.java
new file mode 100644
index 00000000..76ccbd79
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/DispatcherOptions.java
@@ -0,0 +1,18 @@
+package se.leap.bitmaskclient.pluggableTransports;
+
+import java.io.Serializable;
+
+public class DispatcherOptions implements Serializable {
+ public String cert;
+ public String iatMode;
+ public String remoteIP;
+ public String remotePort;
+
+ public DispatcherOptions(String remoteIP, String remotePort, String cert, String iatMode) {
+ this.cert = cert;
+ this.iatMode = iatMode;
+ this.remoteIP = remoteIP;
+ this.remotePort = remotePort;
+ }
+
+}