summaryrefslogtreecommitdiff
path: root/app/src/main/java/de
diff options
context:
space:
mode:
authorcyBerta <cyberta@riseup.net>2019-05-24 18:01:03 +0200
committercyBerta <cyberta@riseup.net>2019-08-02 01:49:37 +0200
commitdb1e1a2045a2e6456d54765be3cf95186ce987f7 (patch)
tree0fc04949eba47e99d7fe7f711fb00bf1c16e3e0a /app/src/main/java/de
parent8ffbb96d908fdc5a17255ec3fbdc807f663ade38 (diff)
squashed commit for Pluggable Transports
* implement handling of different provider API version (v1 and v2) * detect provider's obfs support * shapeshifter-dispatcher installation * necessary changes to control shapeshifter-dispatcher from Bitmask * route openvpn traffic over shapeshifter-dispatcher
Diffstat (limited to 'app/src/main/java/de')
-rw-r--r--app/src/main/java/de/blinkt/openvpn/VpnProfile.java33
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java56
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/ConnectionInterface.java15
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java13
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java44
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java16
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java207
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java83
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/connection/OpenvpnConnection.java13
9 files changed, 432 insertions, 48 deletions
diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
index 7b9003aa..9f18b8ed 100644
--- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
+++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
@@ -5,6 +5,11 @@
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;
@@ -189,7 +194,7 @@ public class VpnProfile implements Serializable, Cloneable {
mProfileVersion = CURRENT_PROFILE_VERSION;
mConnections = new Connection[1];
- mConnections[0] = new Connection();
+ mConnections[0] = new OpenvpnConnection();
mLastUsed = System.currentTimeMillis();
}
@@ -314,8 +319,8 @@ public class VpnProfile implements Serializable, Cloneable {
}
if (mProfileVersion < 7) {
for (Connection c : mConnections)
- if (c.mProxyType == null)
- c.mProxyType = Connection.ProxyType.NONE;
+ if (c.getProxyType() == null)
+ c.setProxyType(Connection.ProxyType.NONE);
}
mProfileVersion = CURRENT_PROFILE_VERSION;
@@ -324,12 +329,12 @@ public class VpnProfile implements Serializable, Cloneable {
private void moveOptionsToConnection() {
mConnections = new Connection[1];
- Connection conn = new Connection();
+ Connection conn = new OpenvpnConnection();
- conn.mServerName = mServerName;
- conn.mServerPort = mServerPort;
- conn.mUseUdp = mUseUdp;
- conn.mCustomConfiguration = "";
+ conn.setServerName(mServerName);
+ conn.setServerPort(mServerPort);
+ conn.setUseUdp(mUseUdp);
+ conn.setCustomConfiguration("");
mConnections[0] = conn;
@@ -425,7 +430,7 @@ public class VpnProfile implements Serializable, Cloneable {
if (canUsePlainRemotes) {
for (Connection conn : mConnections) {
- if (conn.mEnabled) {
+ if (conn.isEnabled()) {
cfg.append(conn.getConnectionBlock(configForOvpn3));
}
}
@@ -586,7 +591,7 @@ public class VpnProfile implements Serializable, Cloneable {
if (mAuthenticationType != TYPE_STATICKEYS) {
if (mCheckRemoteCN) {
if (mRemoteCN == null || mRemoteCN.equals(""))
- cfg.append("verify-x509-name ").append(openVpnEscape(mConnections[0].mServerName)).append(" name\n");
+ cfg.append("verify-x509-name ").append(openVpnEscape(mConnections[0].getServerName())).append(" name\n");
else
switch (mX509AuthType) {
@@ -660,7 +665,7 @@ public class VpnProfile implements Serializable, Cloneable {
if (!canUsePlainRemotes) {
cfg.append("# Connection Options are at the end to allow global options (and global custom options) to influence connection blocks\n");
for (Connection conn : mConnections) {
- if (conn.mEnabled) {
+ if (conn.isEnabled()) {
cfg.append("<connection>\n");
cfg.append(conn.getConnectionBlock(configForOvpn3));
cfg.append("</connection>\n");
@@ -985,7 +990,7 @@ public class VpnProfile implements Serializable, Cloneable {
boolean noRemoteEnabled = true;
for (Connection c : mConnections) {
- if (c.mEnabled)
+ if (c.isEnabled())
noRemoteEnabled = false;
}
@@ -1000,12 +1005,12 @@ public class VpnProfile implements Serializable, Cloneable {
return R.string.openvpn3_pkcs12;
}
for (Connection conn : mConnections) {
- if (conn.mProxyType == Connection.ProxyType.ORBOT || conn.mProxyType == Connection.ProxyType.SOCKS5)
+ if (conn.getProxyType() == Connection.ProxyType.ORBOT || conn.getProxyType() == Connection.ProxyType.SOCKS5)
return R.string.openvpn3_socksproxy;
}
}
for (Connection c : mConnections) {
- if (c.mProxyType == Connection.ProxyType.ORBOT) {
+ if (c.getProxyType() == Connection.ProxyType.ORBOT) {
if (usesExtraProxyOptions())
return R.string.error_orbot_and_proxy_options;
if (!OrbotHelper.checkTorReceier(context))
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 0148bfb7..0e9b1bc4 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
@@ -6,16 +6,24 @@
package de.blinkt.openvpn.core;
import android.os.Build;
-import android.support.v4.util.Pair;
import android.text.TextUtils;
+import android.support.v4.util.Pair;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
-import java.util.*;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Vector;
import de.blinkt.openvpn.VpnProfile;
+import de.blinkt.openvpn.core.connection.Connection;
+import de.blinkt.openvpn.core.connection.OpenvpnConnection;
//! Openvpn Config FIle Parser, probably not 100% accurate but close enough
@@ -142,9 +150,9 @@ public class ConfigParser {
String data = VpnProfile.getEmbeddedContent(inlinedata);
String[] parts = data.split("\n");
if (parts.length >= 2) {
- c.mProxyAuthUser = parts[0];
- c.mProxyAuthPassword = parts[1];
- c.mUseProxyAuth = true;
+ c.setProxyAuthUser(parts[0]);
+ c.setProxyAuthPassword(parts[1]);
+ c.setUseProxyAuth(true);
}
}
@@ -605,7 +613,7 @@ public class ConfigParser {
}
- if (getOption("nobind", 0, 0) != null)
+ if (getOption("nobind", 0, 1) != null)
np.mNobind = true;
if (getOption("persist-tun", 0, 0) != null)
@@ -713,8 +721,8 @@ public class ConfigParser {
throw new ConfigParseError(String.format("Unknown protocol %s in proto-force", protoToDisable));
for (Connection conn : np.mConnections)
- if (conn.mUseUdp == disableUDP)
- conn.mEnabled = false;
+ if (conn.isUseUdp() == disableUDP)
+ conn.setEnabled(false);
}
// Parse OpenVPN Access Server extra
@@ -763,27 +771,27 @@ public class ConfigParser {
return null;
}
else
- conn = new Connection();
+ conn = new OpenvpnConnection();
Vector<String> port = getOption("port", 1, 1);
if (port != null) {
- conn.mServerPort = port.get(1);
+ conn.setServerPort(port.get(1));
}
Vector<String> rport = getOption("rport", 1, 1);
if (rport != null) {
- conn.mServerPort = rport.get(1);
+ conn.setServerPort(rport.get(1));
}
Vector<String> proto = getOption("proto", 1, 1);
if (proto != null) {
- conn.mUseUdp = isUdpProto(proto.get(1));
+ conn.setUseUdp(isUdpProto(proto.get(1)));
}
Vector<String> connectTimeout = getOption("connect-timeout", 1, 1);
if (connectTimeout != null) {
try {
- conn.mConnectTimeout = Integer.parseInt(connectTimeout.get(1));
+ conn.setConnectTimeout(Integer.parseInt(connectTimeout.get(1)));
} catch (NumberFormatException nfe) {
throw new ConfigParseError(String.format("Argument to connect-timeout (%s) must to be an integer: %s",
connectTimeout.get(1), nfe.getLocalizedMessage()));
@@ -797,16 +805,16 @@ public class ConfigParser {
if (proxy != null) {
if (proxy.get(0).equals("socks-proxy")) {
- conn.mProxyType = Connection.ProxyType.SOCKS5;
+ conn.setProxyType(Connection.ProxyType.SOCKS5);
// socks defaults to 1080, http always sets port
- conn.mProxyPort = "1080";
+ conn.setProxyPort("1080");
} else {
- conn.mProxyType = Connection.ProxyType.HTTP;
+ conn.setProxyType(Connection.ProxyType.HTTP);
}
- conn.mProxyName = proxy.get(1);
+ conn.setProxyName(proxy.get(1));
if (proxy.size() >= 3)
- conn.mProxyPort = proxy.get(2);
+ conn.setProxyPort(proxy.get(2));
}
Vector<String> httpproxyauthhttp = getOption("http-proxy-user-pass", 1, 1);
@@ -823,15 +831,15 @@ public class ConfigParser {
// 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()) {
if (connDefault != null || connectionOptionsSet.contains(option.getKey())) {
- conn.mCustomConfiguration += getOptionStrings(option.getValue());
+ conn.setCustomConfiguration(conn.getCustomConfiguration() + getOptionStrings(option.getValue()));
optionsToRemove.add(option.getKey());
}
}
for (String o: optionsToRemove)
options.remove(o);
- if (!(conn.mCustomConfiguration == null || "".equals(conn.mCustomConfiguration.trim())))
- conn.mUseCustomConfig = true;
+ if (!(conn.getCustomConfiguration() == null || "".equals(conn.getCustomConfiguration().trim())))
+ conn.setUseCustomConfig(true);
// Make remotes empty to simplify code
if (remotes == null)
@@ -849,11 +857,11 @@ public class ConfigParser {
}
switch (remote.size()) {
case 4:
- connections[i].mUseUdp = isUdpProto(remote.get(3));
+ connections[i].setUseUdp(isUdpProto(remote.get(3)));
case 3:
- connections[i].mServerPort = remote.get(2);
+ connections[i].setServerPort(remote.get(2));
case 2:
- connections[i].mServerName = remote.get(1);
+ connections[i].setServerName(remote.get(1));
}
i++;
}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/ConnectionInterface.java b/app/src/main/java/de/blinkt/openvpn/core/ConnectionInterface.java
new file mode 100644
index 00000000..70b4b4ec
--- /dev/null
+++ b/app/src/main/java/de/blinkt/openvpn/core/ConnectionInterface.java
@@ -0,0 +1,15 @@
+package de.blinkt.openvpn.core;
+
+import java.io.Serializable;
+
+/**
+ * Created by cyberta on 11.03.19.
+ */
+
+public interface ConnectionInterface {
+
+ String getConnectionBlock(boolean isOpenVPN3);
+ boolean usesExtraProxyOptions();
+ boolean isOnlyRemote();
+ int getTimeout();
+}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java b/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java
index 6b633c34..a66b7b51 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java
@@ -20,6 +20,8 @@ public class NativeUtils {
{
if (isRoboUnitTest())
return "ROBO";
+ else if (isUnitTest())
+ return "JUNIT";
else
return getJNIAPI();
}
@@ -34,7 +36,7 @@ public class NativeUtils {
public static native double[] getOpenSSLSpeed(String algorithm, int testnum);
static {
- if (!isRoboUnitTest()) {
+ if (!isRoboUnitTest() && !isUnitTest()) {
System.loadLibrary("opvpnutil");
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN)
System.loadLibrary("jbcrypto");
@@ -44,4 +46,13 @@ public class NativeUtils {
public static boolean isRoboUnitTest() {
return "robolectric".equals(Build.FINGERPRINT);
}
+
+ public static boolean isUnitTest() {
+ try {
+ Class.forName("se.leap.bitmaskclient.testutils.MockHelper");
+ return true;
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
}
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 82c4e1df..55a92cb0 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -42,9 +42,13 @@ import java.util.Vector;
import de.blinkt.openvpn.VpnProfile;
import de.blinkt.openvpn.core.VpnStatus.ByteCountListener;
import de.blinkt.openvpn.core.VpnStatus.StateListener;
+import de.blinkt.openvpn.core.connection.Connection;
import se.leap.bitmaskclient.R;
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;
@@ -52,6 +56,7 @@ import static se.leap.bitmaskclient.Constants.PROVIDER_PROFILE;
public class OpenVPNService extends VpnService implements StateListener, Callback, ByteCountListener, IOpenVPNServiceInternal, VpnNotificationManager.VpnServiceCallback {
+ public static final String TAG = OpenVPNService.class.getSimpleName();
public static final String START_SERVICE = "de.blinkt.openvpn.START_SERVICE";
public static final String START_SERVICE_STICKY = "de.blinkt.openvpn.START_SERVICE_STICKY";
public static final String ALWAYS_SHOW_NOTIFICATION = "de.blinkt.openvpn.NOTIFICATION_ALWAYS_VISIBLE";
@@ -85,6 +90,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
private Toast mlastToast;
private Runnable mOpenVPNThread;
private VpnNotificationManager notificationManager;
+ private Dispatcher dispatcher;
private static final int PRIORITY_MIN = -2;
private static final int PRIORITY_DEFAULT = 0;
@@ -242,6 +248,9 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
if(isVpnRunning()) {
if (getManagement() != null && getManagement().stopVPN(replaceConnection)) {
if (!replaceConnection) {
+ if (dispatcher.isRunning()) {
+ dispatcher.stop();
+ }
VpnStatus.updateStateString("NOPROCESS", "VPN STOPPED", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED);
}
return true;
@@ -249,6 +258,9 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
return false;
} else {
if (!replaceConnection) {
+ if (dispatcher.isRunning()) {
+ dispatcher.stop();
+ }
VpnStatus.updateStateString("NOPROCESS", "VPN STOPPED", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED);
return true;
}
@@ -366,6 +378,36 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
/**
* see change above (l. 292 ff)
*/
+ //TODO: investigate how connections[n] with n>0 get called during vpn setup (on connection refused?)
+ // Do we need to check if there's any obfs4 connection in mProfile.mConnections and start
+ // the dispatcher here? Can we start the dispatcher at a later point of execution, e.g. when
+ // connections[n], n>0 gets choosen?
+
+ VpnStatus.logInfo("Setting up dispatcher.");
+ Connection connection = mProfile.mConnections[0];
+
+ if (connection.getTransportType() == OBFS4) {
+ Obfs4Connection obfs4Connection = (Obfs4Connection) connection;
+ dispatcher = new Dispatcher(this,
+ obfs4Connection.getmObfs4RemoteProxyName(),
+ obfs4Connection.getmObfs4RemoteProxyPort(),
+ obfs4Connection.getmObfs4Certificate(),
+ obfs4Connection.getmObfs4IatMode());
+ dispatcher.initSync();
+
+ if (dispatcher.getPort() != null && dispatcher.getPort().length() > 0) {
+ connection.setServerPort(dispatcher.getPort());
+ Log.d(TAG, "Dispatcher running. Profile server name and port: " +
+ connection.getServerName() + ":" + connection.getServerPort());
+ VpnStatus.logInfo("Dispatcher running. Profile server name and port: " +
+ connection.getServerName() + ":" + connection.getServerPort());
+ } else {
+ Log.e(TAG, "Cannot initialize dispatcher for obfs4 connection. Shutting down.");
+ VpnStatus.logError("Cannot initialize dispatcher for obfs4 connection. Shutting down.");
+ }
+ }
+
+
VpnStatus.logInfo(R.string.building_configration);
VpnStatus.updateStateString("VPN_GENERATE_CONFIG", "", R.string.building_configration, ConnectionStatus.LEVEL_START);
@@ -743,7 +785,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
boolean profileUsesOrBot = false;
for (Connection c : mProfile.mConnections) {
- if (c.mProxyType == Connection.ProxyType.ORBOT)
+ if (c.getProxyType() == Connection.ProxyType.ORBOT)
profileUsesOrBot = true;
}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java
index 4f7a5bda..91cc66bc 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java
@@ -15,9 +15,10 @@ import android.os.Handler;
import android.os.ParcelFileDescriptor;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
-import android.system.ErrnoException;
import android.system.Os;
import android.util.Log;
+
+import de.blinkt.openvpn.core.connection.Connection;
import se.leap.bitmaskclient.R;
import de.blinkt.openvpn.VpnProfile;
@@ -452,10 +453,10 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {
if (mProfile.mConnections.length > connectionEntryNumber) {
Connection connection = mProfile.mConnections[connectionEntryNumber];
- proxyType = connection.mProxyType;
- proxyname = connection.mProxyName;
- proxyport = connection.mProxyPort;
- proxyUseAuth = connection.mUseProxyAuth;
+ proxyType = connection.getProxyType();
+ proxyname = connection.getProxyName();
+ proxyport = connection.getProxyPort();
+ proxyUseAuth = connection.isUseProxyAuth();
// Use transient variable to remember http user/password
mCurrentProxyConnection = connection;
@@ -696,8 +697,8 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {
} else if (needed.equals("HTTP Proxy")) {
if( mCurrentProxyConnection != null) {
- pw = mCurrentProxyConnection.mProxyAuthPassword;
- username = mCurrentProxyConnection.mProxyAuthUser;
+ pw = mCurrentProxyConnection.getProxyAuthPassword();
+ username = mCurrentProxyConnection.getProxyAuthUser();
}
}
if (pw != null) {
@@ -782,7 +783,6 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {
boolean stopSucceed = stopOpenVPN();
if (stopSucceed) {
mShuttingDown = true;
-
}
return stopSucceed;
}
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
new file mode 100644
index 00000000..f333a13e
--- /dev/null
+++ b/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2012-2016 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
+package de.blinkt.openvpn.core.connection;
+
+import android.text.TextUtils;
+
+import java.io.Serializable;
+import java.util.Locale;
+
+public abstract class Connection implements Serializable, Cloneable {
+ private String mServerName = "openvpn.example.com";
+ private String mServerPort = "1194";
+ private boolean mUseUdp = true;
+ private String mCustomConfiguration = "";
+ private boolean mUseCustomConfig = false;
+ private boolean mEnabled = true;
+ private int mConnectTimeout = 0;
+ private static final int CONNECTION_DEFAULT_TIMEOUT = 120;
+ private ProxyType mProxyType = ProxyType.NONE;
+ private String mProxyName = "proxy.example.com";
+ private String mProxyPort = "8080";
+
+ private boolean mUseProxyAuth;
+ private String mProxyAuthUser = null;
+ private String mProxyAuthPassword = null;
+
+ public enum ProxyType {
+ NONE,
+ HTTP,
+ SOCKS5,
+ ORBOT
+ }
+
+ public enum TransportType {
+ OBFS4,
+ OPENVPN
+ }
+
+ private static final long serialVersionUID = 92031902903829089L;
+
+
+ public String getConnectionBlock(boolean isOpenVPN3) {
+ String cfg = "";
+
+ // Server Address
+ cfg += "remote ";
+ cfg += mServerName;
+ cfg += " ";
+ cfg += mServerPort;
+ if (mUseUdp)
+ cfg += " udp\n";
+ else
+ cfg += " tcp-client\n";
+
+ if (mConnectTimeout != 0)
+ cfg += String.format(Locale.US, " connect-timeout %d\n", mConnectTimeout);
+
+ // OpenVPN 2.x manages proxy connection via management interface
+ if ((isOpenVPN3 || usesExtraProxyOptions()) && mProxyType == ProxyType.HTTP)
+ {
+ cfg+=String.format(Locale.US,"http-proxy %s %s\n", mProxyName, mProxyPort);
+ if (mUseProxyAuth)
+ cfg+=String.format(Locale.US, "<http-proxy-user-pass>\n%s\n%s\n</http-proxy-user-pass>\n", mProxyAuthUser, mProxyAuthPassword);
+ }
+ if (usesExtraProxyOptions() && mProxyType == ProxyType.SOCKS5) {
+ cfg+=String.format(Locale.US,"socks-proxy %s %s\n", mProxyName, mProxyPort);
+ }
+
+ if (!TextUtils.isEmpty(mCustomConfiguration) && mUseCustomConfig) {
+ cfg += mCustomConfiguration;
+ cfg += "\n";
+ }
+
+
+ return cfg;
+ }
+
+ public boolean usesExtraProxyOptions() {
+ return (mUseCustomConfig && mCustomConfiguration.contains("http-proxy-option "));
+ }
+
+
+ @Override
+ public Connection clone() throws CloneNotSupportedException {
+ return (Connection) super.clone();
+ }
+
+ public boolean isOnlyRemote() {
+ return TextUtils.isEmpty(mCustomConfiguration) || !mUseCustomConfig;
+ }
+
+ public int getTimeout() {
+ if (mConnectTimeout <= 0)
+ return CONNECTION_DEFAULT_TIMEOUT;
+ else
+ return mConnectTimeout;
+ }
+
+ public String getServerName() {
+ return mServerName;
+ }
+
+ public void setServerName(String mServerName) {
+ this.mServerName = mServerName;
+ }
+
+ public String getServerPort() {
+ return mServerPort;
+ }
+
+ public void setServerPort(String serverPort) {
+ this.mServerPort = serverPort;
+ }
+
+ public boolean isUseUdp() {
+ return mUseUdp;
+ }
+
+ public void setUseUdp(boolean useUdp) {
+ this.mUseUdp = useUdp;
+ }
+
+ public String getCustomConfiguration() {
+ return mCustomConfiguration;
+ }
+
+ public void setCustomConfiguration(String customConfiguration) {
+ this.mCustomConfiguration = customConfiguration;
+ }
+
+ public boolean isUseCustomConfig() {
+ return mUseCustomConfig;
+ }
+
+ public void setUseCustomConfig(boolean useCustomConfig) {
+ this.mUseCustomConfig = useCustomConfig;
+ }
+
+ public boolean isEnabled() {
+ return mEnabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.mEnabled = enabled;
+ }
+
+ public int getConnectTimeout() {
+ return mConnectTimeout;
+ }
+
+ public void setConnectTimeout(int connectTimeout) {
+ this.mConnectTimeout = connectTimeout;
+ }
+
+ public ProxyType getProxyType() {
+ return mProxyType;
+ }
+
+ public void setProxyType(ProxyType proxyType) {
+ this.mProxyType = proxyType;
+ }
+
+ public String getProxyName() {
+ return mProxyName;
+ }
+
+ public void setProxyName(String proxyName) {
+ this.mProxyName = proxyName;
+ }
+
+ public String getProxyPort() {
+ return mProxyPort;
+ }
+
+ public void setProxyPort(String proxyPort) {
+ this.mProxyPort = proxyPort;
+ }
+
+ public boolean isUseProxyAuth() {
+ return mUseProxyAuth;
+ }
+
+ public void setUseProxyAuth(boolean useProxyAuth) {
+ this.mUseProxyAuth = useProxyAuth;
+ }
+
+ public String getProxyAuthUser() {
+ return mProxyAuthUser;
+ }
+
+ public void setProxyAuthUser(String proxyAuthUser) {
+ this.mProxyAuthUser = proxyAuthUser;
+ }
+
+ public String getProxyAuthPassword() {
+ return mProxyAuthPassword;
+ }
+
+ public void setProxyAuthPassword(String proxyAuthPassword) {
+ this.mProxyAuthPassword = proxyAuthPassword;
+ }
+
+ public abstract TransportType getTransportType();
+}
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
new file mode 100644
index 00000000..790b8b1a
--- /dev/null
+++ b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java
@@ -0,0 +1,83 @@
+package de.blinkt.openvpn.core.connection;
+
+import org.json.JSONObject;
+
+/**
+ * Created by cyberta on 08.03.19.
+ */
+
+public class Obfs4Connection extends Connection {
+
+ private static final String TAG = Obfs4Connection.class.getName();
+
+
+ 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() {
+ setUseUdp(false);
+ setServerName("127.0.0.1");
+ setServerPort("");
+ setProxyName("");
+ setProxyPort("");
+ setProxyAuthUser(null);
+ setProxyAuthPassword(null);
+ setProxyType(ProxyType.NONE);
+ setUseProxyAuth(false);
+ }
+
+ public void setTransportOptions(JSONObject jsonObject) {
+ mObfs4Certificate = jsonObject.optString("cert");
+ mObfs4IatMode = jsonObject.optString("iat-mode");
+ }
+
+ @Override
+ public Connection clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+ @Override
+ public TransportType getTransportType() {
+ 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;
+ }
+
+}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/connection/OpenvpnConnection.java b/app/src/main/java/de/blinkt/openvpn/core/connection/OpenvpnConnection.java
new file mode 100644
index 00000000..3a3fd0c3
--- /dev/null
+++ b/app/src/main/java/de/blinkt/openvpn/core/connection/OpenvpnConnection.java
@@ -0,0 +1,13 @@
+package de.blinkt.openvpn.core.connection;
+
+/**
+ * Created by cyberta on 11.03.19.
+ */
+
+public class OpenvpnConnection extends Connection {
+
+ @Override
+ public TransportType getTransportType() {
+ return TransportType.OPENVPN;
+ }
+}