diff options
author | Arne Schwabe <arne@rfc2549.org> | 2014-03-11 16:04:47 +0100 |
---|---|---|
committer | Arne Schwabe <arne@rfc2549.org> | 2014-03-11 16:04:47 +0100 |
commit | 9fed5954c68119d05be09951f209c452a45a00c3 (patch) | |
tree | 8737a6d0b5177ed8ef451122a9af236e3f41b6dd /main/src | |
parent | a52f8dcdaa9274a65b93699a65849e355b8b3df6 (diff) | |
parent | 76355e501a513a66329b062cf3bebd9eff81c0ba (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')
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); + } + +} |