summaryrefslogtreecommitdiff
path: root/main/src
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2014-03-11 16:04:47 +0100
committerArne Schwabe <arne@rfc2549.org>2014-03-11 16:04:47 +0100
commit9fed5954c68119d05be09951f209c452a45a00c3 (patch)
tree8737a6d0b5177ed8ef451122a9af236e3f41b6dd /main/src
parenta52f8dcdaa9274a65b93699a65849e355b8b3df6 (diff)
parent76355e501a513a66329b062cf3bebd9eff81c0ba (diff)
Resurrect code for OpenVPN C++ core
--HG-- rename : jni/Android.mk => main/jni/Android.mk rename : jni/Application.mk => main/jni/Application.mk rename : ovpn3/Android.mk => main/ovpn3/Android.mk rename : ovpn3/boostsrc/error_code.cpp => main/ovpn3/boostsrc/error_code.cpp rename : src/de/blinkt/openvpn/VpnProfile.java => main/src/main/java/de/blinkt/openvpn/VpnProfile.java rename : src/de/blinkt/openvpn/OpenVpnManagementThread.java => main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java rename : src/de/blinkt/openvpn/OpenVpnService.java => main/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java rename : src/de/blinkt/openvpn/LogWindow.java => main/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java
Diffstat (limited to 'main/src')
-rw-r--r--main/src/main/java/de/blinkt/openvpn/VpnProfile.java12
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java29
-rw-r--r--main/src/main/java/de/blinkt/openvpn/fragments/GeneralSettings.java8
-rw-r--r--main/src/main/res/xml/general_settings.xml10
-rw-r--r--main/src/ovpn3/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java277
5 files changed, 328 insertions, 8 deletions
diff --git a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java
index d816d97e..601fb2df 100644
--- a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java
+++ b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java
@@ -202,7 +202,9 @@ public class VpnProfile implements Serializable {
//cfg += "management-signal\n";
cfg += "management-query-passwords\n";
cfg += "management-hold\n\n";
- cfg += getVersionEnvString(context);
+
+ if (!configForOvpn3)
+ cfg += String.format("setenv IV_GUI_VER %s \n", openVpnEscape(getVersionEnvString(context)));
cfg += "machine-readable-output\n";
@@ -439,7 +441,7 @@ public class VpnProfile implements Serializable {
return cfg;
}
- private String getVersionEnvString(Context c) {
+ public String getVersionEnvString(Context c) {
String version = "unknown";
try {
PackageInfo packageinfo = c.getPackageManager().getPackageInfo(c.getPackageName(), 0);
@@ -447,7 +449,7 @@ public class VpnProfile implements Serializable {
} catch (PackageManager.NameNotFoundException e) {
VpnStatus.logException(e);
}
- return String.format(Locale.US, "setenv IV_GUI_VER \"%s %s\"\n", c.getPackageName(), version);
+ return String.format(Locale.US, "%s %s", c.getPackageName(), version);
}
@@ -573,7 +575,7 @@ public class VpnProfile implements Serializable {
return intent;
}
- String[] getKeyStoreCertificates(Context context) {
+ public String[] getKeyStoreCertificates(Context context) {
return getKeyStoreCertificates(context, 5);
}
@@ -761,7 +763,7 @@ public class VpnProfile implements Serializable {
}
}
- boolean isUserPWAuth() {
+ public boolean isUserPWAuth() {
switch (mAuthenticationType) {
case TYPE_USERPASS:
case TYPE_USERPASS_CERTIFICATES:
diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java
index 0de791d6..ff6ccd15 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java
@@ -15,6 +15,8 @@ import android.os.*;
import android.os.Handler.Callback;
import android.preference.PreferenceManager;
import android.text.TextUtils;
+
+import de.blinkt.openvpn.BuildConfig;
import de.blinkt.openvpn.activities.DisconnectVPN;
import de.blinkt.openvpn.activities.LogWindow;
import de.blinkt.openvpn.R;
@@ -295,7 +297,8 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
return START_REDELIVER_INTENT;
}
- assert (intent != null);
+ if (intent == null)
+ return START_NOT_STICKY;
// Extract information from the intent.
String prefix = getPackageName();
@@ -335,7 +338,8 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
mOvpn3 = prefs.getBoolean("ovpn3", false);
- mOvpn3 = false;
+ if (!"ovpn3".equals(BuildConfig.FLAVOR))
+ mOvpn3 = false;
// Open the Management Interface
@@ -383,6 +387,22 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
}
private OpenVPNManagement instantiateOpenVPN3Core() {
+ try {
+ Class cl = Class.forName("de.blinkt.openvpn.core.OpenVPNThreadv3");
+ return (OpenVPNManagement) cl.getConstructor(OpenVpnService.class,VpnProfile.class).newInstance(this,mProfile);
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (InstantiationException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
return null;
}
@@ -542,6 +562,11 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac
}
}
+ /** Route that is always included, used by the v3 core */
+ public void addRoute (CIDRIP route) {
+ mRoutes.addIP(route, true);
+ }
+
public void addRoute (String dest, String mask, String gateway, String device) {
CIDRIP route = new CIDRIP(dest, mask);
boolean include = isAndroidTunDevice(device);
diff --git a/main/src/main/java/de/blinkt/openvpn/fragments/GeneralSettings.java b/main/src/main/java/de/blinkt/openvpn/fragments/GeneralSettings.java
index 2e486dfe..0c6bb5b4 100644
--- a/main/src/main/java/de/blinkt/openvpn/fragments/GeneralSettings.java
+++ b/main/src/main/java/de/blinkt/openvpn/fragments/GeneralSettings.java
@@ -16,6 +16,8 @@ import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
+
+import de.blinkt.openvpn.BuildConfig;
import de.blinkt.openvpn.R;
import de.blinkt.openvpn.api.ExternalAppDatabase;
@@ -54,6 +56,12 @@ public class GeneralSettings extends PreferenceFragment implements OnPreferenceC
if(devHacks.getPreferenceCount()==0)
getPreferenceScreen().removePreference(devHacks);
+ if (!"ovpn3".equals(BuildConfig.FLAVOR)) {
+ PreferenceCategory appBehaviour = (PreferenceCategory) findPreference("app_behaviour");
+ appBehaviour.removePreference(findPreference("ovpn3"));
+ }
+
+
setClearApiSummary();
}
diff --git a/main/src/main/res/xml/general_settings.xml b/main/src/main/res/xml/general_settings.xml
index d43ab6a3..4eca5243 100644
--- a/main/src/main/res/xml/general_settings.xml
+++ b/main/src/main/res/xml/general_settings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
- <PreferenceCategory android:title="@string/appbehaviour">
+ <PreferenceCategory android:title="@string/appbehaviour" android:key="app_behaviour">
<CheckBoxPreference
android:defaultValue="true"
android:key="showlogwindow"
@@ -8,6 +8,14 @@
android:title="@string/show_log_window"/>
<CheckBoxPreference
+ android:defaultValue="false"
+ android:key="ovpn3"
+ android:summaryOn="Use the C++ OpenVPN library"
+ android:summaryOff="Use OpenVPN 2.3"
+ android:title="OpenVPN 3 Core"/>
+
+
+ <CheckBoxPreference
android:defaultValue="false"
android:key="restartvpnonboot"
android:summary="@string/onbootrestartsummary"
diff --git a/main/src/ovpn3/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java b/main/src/ovpn3/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java
new file mode 100644
index 00000000..6d3dce69
--- /dev/null
+++ b/main/src/ovpn3/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java
@@ -0,0 +1,277 @@
+package de.blinkt.openvpn.core;
+
+import net.openvpn.ovpn3.ClientAPI_Config;
+import net.openvpn.ovpn3.ClientAPI_EvalConfig;
+import net.openvpn.ovpn3.ClientAPI_Event;
+import net.openvpn.ovpn3.ClientAPI_ExternalPKICertRequest;
+import net.openvpn.ovpn3.ClientAPI_ExternalPKISignRequest;
+import net.openvpn.ovpn3.ClientAPI_LogInfo;
+import net.openvpn.ovpn3.ClientAPI_OpenVPNClient;
+import net.openvpn.ovpn3.ClientAPI_ProvideCreds;
+import net.openvpn.ovpn3.ClientAPI_Status;
+import net.openvpn.ovpn3.ClientAPI_TransportStats;
+
+import java.lang.Override;
+
+import de.blinkt.openvpn.VpnProfile;
+import de.blinkt.openvpn.core.OpenVPNManagement;
+import de.blinkt.openvpn.core.OpenVpnService;
+import de.blinkt.openvpn.core.VpnStatus;
+import android.content.Context;
+
+public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable, OpenVPNManagement {
+
+ static {
+ /*System.loadLibrary("crypto");
+ System.loadLibrary("ssl");*/
+ System.loadLibrary("polarssl-dynamic");
+ System.loadLibrary("ovpn3");
+ }
+
+ private VpnProfile mVp;
+ private OpenVpnService mService;
+
+ class StatusPoller implements Runnable
+ {
+ private long mSleeptime;
+
+ boolean mStopped=false;
+
+ public StatusPoller(long sleeptime) {
+ mSleeptime=sleeptime;
+ }
+
+ public void run() {
+ while(!mStopped) {
+ try {
+ Thread.sleep(mSleeptime);
+ } catch (InterruptedException e) {
+ }
+ ClientAPI_TransportStats t = transport_stats();
+ long in = t.getBytesIn();
+ long out = t.getBytesOut();
+ VpnStatus.updateByteCount(in, out);
+ }
+ }
+
+ public void stop() {
+ mStopped=true;
+ }
+ }
+
+ @Override
+ public void run() {
+ String configstr = mVp.getConfigFile((Context)mService,true);
+ if(!setConfig(configstr))
+ return;
+ setUserPW();
+ VpnStatus.logInfo(copyright());
+
+ StatusPoller statuspoller = new StatusPoller(5000);
+ new Thread(statuspoller,"Status Poller").start();
+
+ ClientAPI_Status status = connect();
+ if(status.getError()) {
+ VpnStatus.logError(String.format("connect() error: %s: %s",status.getStatus(),status.getMessage()));
+ } else {
+ VpnStatus.logInfo("OpenVPN3 thread finished");
+ }
+ statuspoller.stop();
+ }
+
+ @Override
+ public boolean tun_builder_set_remote_address(String address, boolean ipv6) {
+ mService.setMtu(1500);
+ return true;
+ }
+
+ @Override
+ public boolean tun_builder_set_mtu(int mtu) {
+ mService.setMtu(mtu);
+ return true;
+ }
+ @Override
+ public boolean tun_builder_add_dns_server(String address, boolean ipv6) {
+ mService.addDNS(address);
+ return true;
+ }
+
+ @Override
+ public boolean tun_builder_add_route(String address, int prefix_length,
+ boolean ipv6) {
+ if (address.equals("remote_host"))
+ return false;
+
+ if(ipv6)
+ mService.addRoutev6(address + "/" + prefix_length,"tun");
+ else
+ mService.addRoute(new CIDRIP(address, prefix_length));
+ return true;
+ }
+
+ @Override
+ public boolean tun_builder_add_search_domain(String domain) {
+ mService.setDomain(domain);
+ return true;
+ }
+
+ @Override
+ public int tun_builder_establish() {
+ return mService.openTun().detachFd();
+ }
+
+ @Override
+ public boolean tun_builder_set_session_name(String name) {
+ VpnStatus.logInfo("We should call this session" + name);
+ return true;
+ }
+
+
+
+ @Override
+ public boolean tun_builder_add_address(String address, int prefix_length,
+ boolean ipv6) {
+ if(!ipv6)
+ mService.setLocalIP(new CIDRIP(address, prefix_length));
+ else
+ mService.setLocalIPv6(address+ "/" + prefix_length);
+ return true;
+ }
+
+ @Override
+ public boolean tun_builder_new() {
+
+ return true;
+ }
+
+ @Override
+ public boolean tun_builder_reroute_gw(String server_address,
+ boolean server_address_ipv6, boolean ipv4, boolean ipv6, long flags) {
+ // ignore
+ return true;
+ }
+
+ @Override
+ public boolean tun_builder_exclude_route(String address, int prefix_length,
+ boolean ipv6) {
+ //ignore
+ return true;
+ }
+
+
+ private boolean setConfig(String vpnconfig) {
+
+ ClientAPI_Config config = new ClientAPI_Config();
+ if(mVp.getPasswordPrivateKey()!=null)
+ config.setPrivateKeyPassword(mVp.getPasswordPrivateKey());
+
+ config.setContent(vpnconfig);
+ config.setTunPersist(mVp.mPersistTun);
+ config.setGuiVersion(mVp.getVersionEnvString(mService));
+ config.setExternalPkiAlias("extpki");
+
+ ClientAPI_EvalConfig ec = eval_config(config);
+ if(ec.getExternalPki()) {
+ VpnStatus.logError("OpenVPN seem to think as external PKI");
+ }
+ if (ec.getError()) {
+ VpnStatus.logError("OpenVPN config file parse error: " + ec.getMessage());
+ return false;
+ } else {
+ config.setContent(vpnconfig);
+ return true;
+ }
+ }
+
+ @Override
+ public void external_pki_cert_request(ClientAPI_ExternalPKICertRequest certreq) {
+ VpnStatus.logError("EXT PKI CERT");
+ String[] ks = mVp.getKeyStoreCertificates((Context) mService);
+ if(ks==null) {
+ certreq.setError(true);
+ certreq.setErrorText("Error in pki cert request");
+ return;
+ }
+
+ String supcerts = ks[0];
+ /* FIXME: How to differentiate between chain and ca certs in OpenVPN 3? */
+ if (ks[1]!=null)
+ supcerts += "\n" + ks[1];
+ certreq.setSupportingChain(supcerts);
+ certreq.setCert(ks[2]);
+ certreq.setError(false);
+ }
+
+ @Override
+ public void external_pki_sign_request(ClientAPI_ExternalPKISignRequest signreq) {
+ signreq.setSig(mVp.getSignedData(signreq.getData()));
+ }
+
+ void setUserPW() {
+ if(mVp.isUserPWAuth()) {
+ ClientAPI_ProvideCreds creds = new ClientAPI_ProvideCreds();
+ creds.setCachePassword(true);
+ creds.setPassword(mVp.getPasswordAuth());
+ creds.setUsername(mVp.mUsername);
+ provide_creds(creds);
+ }
+ }
+
+ @Override
+ public boolean socket_protect(int socket) {
+ boolean b= mService.protect(socket);
+ return b;
+
+ }
+
+ public OpenVPNThreadv3(OpenVpnService openVpnService, VpnProfile vp) {
+ init_process();
+ mVp =vp;
+ mService =openVpnService;
+ }
+
+ @Override
+ public void pause(pauseReason pauseReason)
+ {
+ pause();
+ }
+
+ @Override
+ public void log(ClientAPI_LogInfo arg0) {
+ String logmsg =arg0.getText();
+ while (logmsg.endsWith("\n"))
+ logmsg = logmsg.substring(0, logmsg.length()-1);
+
+ VpnStatus.logInfo(logmsg);
+ }
+
+ @Override
+ public void event(ClientAPI_Event event) {
+ VpnStatus.updateStateString(event.getName(), event.getInfo());
+ if(event.getError())
+ VpnStatus.logError(String.format("EVENT(Error): %s: %s",event.getName(),event.getInfo()));
+ }
+
+
+ // When a connection is close to timeout, the core will call this
+ // method. If it returns false, the core will disconnect with a
+ // CONNECTION_TIMEOUT event. If true, the core will enter a PAUSE
+ // state.
+
+ @Override
+ public boolean pause_on_connection_timeout() {
+ VpnStatus.logInfo("pause on connection timeout?! ");
+ return true;
+ }
+
+ public boolean stopVPN() {
+ stop();
+ return true;
+ }
+
+ @Override
+ public void reconnect() {
+ reconnect(1);
+ }
+
+}