summaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
Diffstat (limited to 'app/src')
-rw-r--r--app/src/main/java/de/blinkt/openvpn/VpnProfile.java25
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java43
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java9
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java16
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java74
-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
10 files changed, 200 insertions, 177 deletions
diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
index 9f18b8ed..dc12c6a8 100644
--- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
+++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
@@ -5,11 +5,6 @@
package de.blinkt.openvpn;
-import de.blinkt.openvpn.core.connection.Connection;
-import de.blinkt.openvpn.core.connection.OpenvpnConnection;
-import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.BuildConfig;
-
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
@@ -58,7 +53,6 @@ import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
-import de.blinkt.openvpn.core.Connection;
import de.blinkt.openvpn.core.ExtAuthHelper;
import de.blinkt.openvpn.core.NativeUtils;
import de.blinkt.openvpn.core.OpenVPNService;
@@ -68,9 +62,13 @@ import de.blinkt.openvpn.core.Preferences;
import de.blinkt.openvpn.core.VPNLaunchHelper;
import de.blinkt.openvpn.core.VpnStatus;
import de.blinkt.openvpn.core.X509Utils;
+import de.blinkt.openvpn.core.connection.Connection;
+import de.blinkt.openvpn.core.connection.Obfs4Connection;
+import de.blinkt.openvpn.core.connection.OpenvpnConnection;
import se.leap.bitmaskclient.BuildConfig;
import se.leap.bitmaskclient.R;
+import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4;
import static se.leap.bitmaskclient.Constants.PROVIDER_PROFILE;
public class VpnProfile implements Serializable, Cloneable {
@@ -121,7 +119,7 @@ public class VpnProfile implements Serializable, Cloneable {
public String mTLSAuthFilename;
public String mClientKeyFilename;
public String mCaFilename;
- public boolean mUseLzo = true;
+ public boolean mUseLzo = false;
public String mPKCS12Filename;
public String mPKCS12Password;
public boolean mUseTLSAuth = false;
@@ -186,16 +184,16 @@ public class VpnProfile implements Serializable, Cloneable {
// set members to default values
private UUID mUuid;
private int mProfileVersion;
+ public boolean mUsePluggableTransports;
-
- public VpnProfile(String name) {
+ public VpnProfile(String name, Connection.TransportType transportType) {
mUuid = UUID.randomUUID();
mName = name;
mProfileVersion = CURRENT_PROFILE_VERSION;
mConnections = new Connection[1];
- mConnections[0] = new OpenvpnConnection();
mLastUsed = System.currentTimeMillis();
+ mUsePluggableTransports = transportType == OBFS4;
}
public static String openVpnEscape(String unescaped) {
@@ -297,6 +295,7 @@ public class VpnProfile implements Serializable, Cloneable {
return mName;
}
+ @Deprecated
public void upgradeProfile() {
if (mProfileVersion < 2) {
/* default to the behaviour the OS used */
@@ -327,9 +326,10 @@ public class VpnProfile implements Serializable, Cloneable {
}
+ @Deprecated
private void moveOptionsToConnection() {
mConnections = new Connection[1];
- Connection conn = new OpenvpnConnection();
+ Connection conn = mUsePluggableTransports ? new Obfs4Connection() : new OpenvpnConnection();
conn.setServerName(mServerName);
conn.setServerPort(mServerPort);
@@ -499,7 +499,8 @@ public class VpnProfile implements Serializable, Cloneable {
if (!TextUtils.isEmpty(mCrlFilename))
cfg.append(insertFileData("crl-verify", mCrlFilename));
- if (mUseLzo) {
+ // compression does not work in conjunction with shapeshifter-dispatcher so far
+ if (mUseLzo && !mUsePluggableTransports) {
cfg.append("comp-lzo\n");
}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
index 0e9b1bc4..4c53087f 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
@@ -6,8 +6,8 @@
package de.blinkt.openvpn.core;
import android.os.Build;
-import android.text.TextUtils;
import android.support.v4.util.Pair;
+import android.text.TextUtils;
import java.io.BufferedReader;
import java.io.IOException;
@@ -23,7 +23,11 @@ import java.util.Vector;
import de.blinkt.openvpn.VpnProfile;
import de.blinkt.openvpn.core.connection.Connection;
+import de.blinkt.openvpn.core.connection.Obfs4Connection;
import de.blinkt.openvpn.core.connection.OpenvpnConnection;
+import se.leap.bitmaskclient.pluggableTransports.DispatcherOptions;
+
+import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4;
//! Openvpn Config FIle Parser, probably not 100% accurate but close enough
@@ -136,6 +140,7 @@ public class ConfigParser {
private HashMap<String, Vector<Vector<String>>> options = new HashMap<>();
private HashMap<String, Vector<String>> meta = new HashMap<String, Vector<String>>();
private String auth_user_pass_file;
+ private DispatcherOptions dispatcherOptions;
static public void useEmbbedUserAuth(VpnProfile np, String inlinedata) {
String data = VpnProfile.getEmbeddedContent(inlinedata);
@@ -346,9 +351,9 @@ public class ConfigParser {
// This method is far too long
@SuppressWarnings("ConstantConditions")
- public VpnProfile convertProfile() throws ConfigParseError, IOException {
+ public VpnProfile convertProfile(Connection.TransportType transportType) throws ConfigParseError, IOException {
boolean noauthtypeset = true;
- VpnProfile np = new VpnProfile(CONVERTED_PROFILE);
+ VpnProfile np = new VpnProfile(CONVERTED_PROFILE, transportType);
// Pull, client, tls-client
np.clearDefaults();
@@ -451,6 +456,7 @@ public class ConfigParser {
if (redirectPrivate != null) {
checkRedirectParameters(np, redirectPrivate, false);
}
+
Vector<String> dev = getOption("dev", 1, 1);
Vector<String> devtype = getOption("dev-type", 1, 1);
@@ -476,7 +482,6 @@ public class ConfigParser {
}
}
-
Vector<String> tunmtu = getOption("tun-mtu", 1, 1);
if (tunmtu != null) {
@@ -487,14 +492,12 @@ public class ConfigParser {
}
}
-
Vector<String> mode = getOption("mode", 1, 1);
if (mode != null) {
if (!mode.get(1).equals("p2p"))
throw new ConfigParseError("Invalid mode for --mode specified, need p2p");
}
-
Vector<Vector<String>> dhcpoptions = getAllOption("dhcp-option", 2, 2);
if (dhcpoptions != null) {
for (Vector<String> dhcpoption : dhcpoptions) {
@@ -529,8 +532,10 @@ public class ConfigParser {
if (getOption("float", 0, 0) != null)
np.mUseFloat = true;
- if (getOption("comp-lzo", 0, 1) != null)
- np.mUseLzo = true;
+ Vector<String> useLzo = getOption("comp-lzo", 0, 1);
+ if (useLzo != null) {
+ np.mUseLzo = Boolean.valueOf(useLzo.get(1));
+ }
Vector<String> cipher = getOption("cipher", 1, 1);
if (cipher != null)
@@ -540,7 +545,6 @@ public class ConfigParser {
if (auth != null)
np.mAuth = auth.get(1);
-
Vector<String> ca = getOption("ca", 1, 1);
if (ca != null) {
np.mCaFilename = ca.get(1);
@@ -552,6 +556,7 @@ public class ConfigParser {
np.mAuthenticationType = VpnProfile.TYPE_CERTIFICATES;
noauthtypeset = false;
}
+
Vector<String> key = getOption("key", 1, 1);
if (key != null)
np.mClientKeyFilename = key.get(1);
@@ -612,7 +617,6 @@ public class ConfigParser {
np.mVerb = verb.get(1);
}
-
if (getOption("nobind", 0, 1) != null)
np.mNobind = true;
@@ -682,8 +686,7 @@ public class ConfigParser {
}
-
- Pair<Connection, Connection[]> conns = parseConnectionOptions(null);
+ Pair<Connection, Connection[]> conns = parseConnectionOptions(null, transportType);
np.mConnections = conns.second;
Vector<Vector<String>> connectionBlocks = getAllOption("connection", 1, 1);
@@ -706,6 +709,7 @@ public class ConfigParser {
connIndex++;
}
}
+
if (getOption("remote-random", 0, 0) != null)
np.mRemoteRandom = true;
@@ -748,20 +752,21 @@ public class ConfigParser {
return TextUtils.join(s, str);
}
+ public void setDispatcherOptions(DispatcherOptions dispatcherOptions) {
+ this.dispatcherOptions = dispatcherOptions;
+ }
+
private Pair<Connection, Connection[]> parseConnection(String connection, Connection defaultValues) throws IOException, ConfigParseError {
// Parse a connection Block as a new configuration file
-
ConfigParser connectionParser = new ConfigParser();
StringReader reader = new StringReader(connection.substring(VpnProfile.INLINE_TAG.length()));
connectionParser.parseConfig(reader);
- Pair<Connection, Connection[]> conn = connectionParser.parseConnectionOptions(defaultValues);
-
- return conn;
+ return connectionParser.parseConnectionOptions(defaultValues, defaultValues.getTransportType());
}
- private Pair<Connection, Connection[]> parseConnectionOptions(Connection connDefault) throws ConfigParseError {
+ private Pair<Connection, Connection[]> parseConnectionOptions(Connection connDefault, Connection.TransportType transportType) throws ConfigParseError {
Connection conn;
if (connDefault != null)
try {
@@ -771,7 +776,7 @@ public class ConfigParser {
return null;
}
else
- conn = new OpenvpnConnection();
+ conn = transportType == OBFS4 ? new Obfs4Connection(dispatcherOptions) : new OpenvpnConnection();
Vector<String> port = getOption("port", 1, 1);
if (port != null) {
@@ -825,8 +830,6 @@ public class ConfigParser {
// Parse remote config
Vector<Vector<String>> remotes = getAllOption("remote", 1, 3);
-
-
Vector <String> optionsToRemove = new Vector<>();
// Assume that we need custom options if connectionDefault are set or in the connection specific set
for (Map.Entry<String, Vector<Vector<String>>> option : options.entrySet()) {
diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
index b775921c..4a33fd49 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -48,7 +48,6 @@ import se.leap.bitmaskclient.VpnNotificationManager;
import se.leap.bitmaskclient.pluggableTransports.Dispatcher;
import de.blinkt.openvpn.core.connection.Obfs4Connection;
-import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4;
import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_CONNECTED;
import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT;
import static de.blinkt.openvpn.core.NetworkSpace.IpAddress;
@@ -386,13 +385,9 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
VpnStatus.logInfo("Setting up dispatcher.");
Connection connection = mProfile.mConnections[0];
- if (connection.getTransportType() == OBFS4) {
+ if (mProfile.mUsePluggableTransports) {
Obfs4Connection obfs4Connection = (Obfs4Connection) connection;
- dispatcher = new Dispatcher(this,
- obfs4Connection.getmObfs4RemoteProxyName(),
- obfs4Connection.getmObfs4RemoteProxyPort(),
- obfs4Connection.getmObfs4Certificate(),
- obfs4Connection.getmObfs4IatMode());
+ dispatcher = new Dispatcher(this, obfs4Connection.getDispatcherOptions());
dispatcher.initSync();
if (dispatcher.isRunning()) {
diff --git a/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java b/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java
index f333a13e..a318e55d 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java
@@ -35,10 +35,22 @@ public abstract class Connection implements Serializable, Cloneable {
}
public enum TransportType {
- OBFS4,
- OPENVPN
+ OBFS4("obfs4"),
+ OPENVPN("openvpn");
+
+ String transport;
+
+ TransportType(String transportType) {
+ this.transport = transportType;
+ }
+
+ @Override
+ public String toString() {
+ return transport;
+ }
}
+
private static final long serialVersionUID = 92031902903829089L;
diff --git a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java
index 790b8b1a..4f6be276 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java
@@ -1,6 +1,9 @@
package de.blinkt.openvpn.core.connection;
-import org.json.JSONObject;
+import se.leap.bitmaskclient.pluggableTransports.DispatcherOptions;
+
+import static se.leap.bitmaskclient.pluggableTransports.Dispatcher.DISPATCHER_IP;
+import static se.leap.bitmaskclient.pluggableTransports.Dispatcher.DISPATCHER_PORT;
/**
* Created by cyberta on 08.03.19.
@@ -9,46 +12,38 @@ import org.json.JSONObject;
public class Obfs4Connection extends Connection {
private static final String TAG = Obfs4Connection.class.getName();
+ private DispatcherOptions options;
-
- private String mObfs4RemoteProxyName = "";
- private String mObfs4RemoteProxyPort = "";
- private String mObfs4Certificate = "";
- private String mObfs4IatMode = "";
-
- public Obfs4Connection() {
- setDefaults();
- }
-
- public Obfs4Connection(Connection connection) {
- mObfs4RemoteProxyName = connection.getServerName();
- setConnectTimeout(connection.getConnectTimeout());
- setCustomConfiguration(connection.getCustomConfiguration());
- setUseCustomConfig(connection.isUseCustomConfig());
-
- setDefaults();
- }
-
- private void setDefaults() {
+ public Obfs4Connection(DispatcherOptions options) {
setUseUdp(false);
- setServerName("127.0.0.1");
- setServerPort("");
+ setServerName(DISPATCHER_IP);
+ setServerPort(DISPATCHER_PORT);
setProxyName("");
setProxyPort("");
setProxyAuthUser(null);
setProxyAuthPassword(null);
setProxyType(ProxyType.NONE);
setUseProxyAuth(false);
+ this.options = options;
}
- public void setTransportOptions(JSONObject jsonObject) {
- mObfs4Certificate = jsonObject.optString("cert");
- mObfs4IatMode = jsonObject.optString("iat-mode");
- }
+ @Deprecated
+ public Obfs4Connection() {
+ setUseUdp(false);
+ setServerName(DISPATCHER_IP);
+ setServerPort(DISPATCHER_PORT);
+ setProxyName("");
+ setProxyPort("");
+ setProxyAuthUser(null);
+ setProxyAuthPassword(null);
+ setProxyType(ProxyType.NONE);
+ setUseProxyAuth(false); }
@Override
public Connection clone() throws CloneNotSupportedException {
- return super.clone();
+ Obfs4Connection connection = (Obfs4Connection) super.clone();
+ connection.options = this.options;
+ return connection;
}
@Override
@@ -56,28 +51,9 @@ public class Obfs4Connection extends Connection {
return TransportType.OBFS4;
}
- public String getmObfs4RemoteProxyName() {
- return mObfs4RemoteProxyName;
- }
-
- public void setObfs4RemoteProxyName(String mObfs4RemoteProxyName) {
- this.mObfs4RemoteProxyName = mObfs4RemoteProxyName;
- }
-
- public String getmObfs4RemoteProxyPort() {
- return mObfs4RemoteProxyPort;
- }
-
- public void setObfs4RemoteProxyPort(String mObfs4RemoteProxyPort) {
- this.mObfs4RemoteProxyPort = mObfs4RemoteProxyPort;
- }
-
- public String getmObfs4Certificate() {
- return mObfs4Certificate;
- }
- public String getmObfs4IatMode() {
- return mObfs4IatMode;
+ public DispatcherOptions getDispatcherOptions() {
+ return options;
}
}
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;
+ }
+
+}