summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.DS_Storebin12292 -> 0 bytes
-rw-r--r--AndroidManifest.xml4
-rw-r--r--openvpn/0001-initial-android-hacks.patch523
-rw-r--r--openvpn/src/openvpn/error.c15
-rw-r--r--openvpn/src/openvpn/socket.c1
-rw-r--r--res/values/strings.xml4
-rw-r--r--res/xml/vpn_authentification.xml12
-rw-r--r--res/xml/vpn_headers.xml3
-rw-r--r--src/de/blinkt/openvpn/ConfigParser.java232
-rw-r--r--src/de/blinkt/openvpn/LaunchVPN.java6
-rw-r--r--src/de/blinkt/openvpn/OpenVpnService.java51
-rw-r--r--src/de/blinkt/openvpn/Settings_Authentication.java14
-rw-r--r--src/de/blinkt/openvpn/VpnProfile.java19
-rw-r--r--todo.txt1
14 files changed, 328 insertions, 557 deletions
diff --git a/.DS_Store b/.DS_Store
deleted file mode 100644
index 2d192e8..0000000
--- a/.DS_Store
+++ /dev/null
Binary files differ
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index bc3f311..b6cdc32 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -17,8 +17,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.blinkt.openvpn"
- android:versionCode="21"
- android:versionName="0.5.0" >
+ android:versionCode="22"
+ android:versionName="0.5.1" >
<uses-permission android:name="android.permission.INTERNET" />
diff --git a/openvpn/0001-initial-android-hacks.patch b/openvpn/0001-initial-android-hacks.patch
deleted file mode 100644
index e78cc7d..0000000
--- a/openvpn/0001-initial-android-hacks.patch
+++ /dev/null
@@ -1,523 +0,0 @@
-From d573932062cb4afd7f001899978e37ce446934e7 Mon Sep 17 00:00:00 2001
-From: Arne Schwabe <arne@rfc2549.org>
-Date: Tue, 10 Apr 2012 00:34:51 +0200
-Subject: [PATCH] initial android hacks
-
----
- src/compat/compat-rsa_generate_key.c | 47 ++++++++++
- src/openvpn/error.c | 19 ++++-
- src/openvpn/jniglue.c | 162 ++++++++++++++++++++++++++++++++++
- src/openvpn/jniglue.h | 19 ++++
- src/openvpn/options.c | 1 +
- src/openvpn/route.c | 7 ++-
- src/openvpn/socket.c | 25 +++++
- src/openvpn/ssl.c | 2 +
- src/openvpn/syshead.h | 2 +-
- src/openvpn/tun.c | 22 ++++-
- src/openvpn/tun.h | 2 +
- 11 files changed, 303 insertions(+), 5 deletions(-)
- create mode 100644 src/compat/compat-rsa_generate_key.c
- create mode 100644 src/openvpn/jniglue.c
- create mode 100644 src/openvpn/jniglue.h
-
-diff --git a/src/compat/compat-rsa_generate_key.c b/src/compat/compat-rsa_generate_key.c
-new file mode 100644
-index 0000000..99725da
---- /dev/null
-+++ b/src/compat/compat-rsa_generate_key.c
-@@ -0,0 +1,47 @@
-+#include <stdio.h>
-+#include <time.h>
-+#include "cryptlib.h"
-+#include <openssl/bn.h>
-+#include <openssl/rsa.h>
-+
-+RSA *RSA_generate_key(int bits, unsigned long e_value,
-+ void (*callback)(int,int,void *), void *cb_arg)
-+{
-+ BN_GENCB cb;
-+ int i;
-+ RSA *rsa = RSA_new();
-+ BIGNUM *e = BN_new();
-+
-+ if(!rsa || !e) goto err;
-+
-+ /* The problem is when building with 8, 16, or 32 BN_ULONG,
-+ * unsigned long can be larger */
-+ for (i=0; i<(int)sizeof(unsigned long)*8; i++)
-+ {
-+ if (e_value & (1UL<<i))
-+ if (BN_set_bit(e,i) == 0)
-+ goto err;
-+ }
-+
-+ BN_GENCB_set_old(&cb, callback, cb_arg);
-+
-+ if(RSA_generate_key_ex(rsa, bits, e, &cb)) {
-+ BN_free(e);
-+ return rsa;
-+ }
-+ err:
-+ if(e) BN_free(e);
-+ if(rsa) RSA_free(rsa);
-+ return 0;
-+}
-+
-+
-+
-+void mlockall(){}
-+char *
-+getpass (prompt)
-+ const char *prompt;
-+{
-+ return "";
-+}
-+
-diff --git a/src/openvpn/error.c b/src/openvpn/error.c
-index d6ad639..d4a3cff 100644
---- a/src/openvpn/error.c
-+++ b/src/openvpn/error.c
-@@ -199,6 +199,16 @@ msg_fp(const unsigned int flags)
-
- int x_msg_line_num; /* GLOBAL */
-
-+#include "android/log.h"
-+void x_msg2(const unsigned int flags, const char *format, ...) {
-+ va_list arglist;
-+ va_start(arglist,format);
-+ // vsnprintf(m1, 100, "foo bbaz",arglist);
-+ __android_log_vprint(ANDROID_LOG_DEBUG, "openvpn",format, arglist);
-+ va_end(arglist);
-+}
-+
-+
- void x_msg (const unsigned int flags, const char *format, ...)
- {
- struct gc_arena gc;
-@@ -350,6 +360,10 @@ void x_msg (const unsigned int flags, const char *format, ...)
- }
- }
-
-+#ifdef TARGET_ANDROID
-+ android_openvpn_log(prefix,prefix_sep,m1);;
-+#endif
-+
- if (flags & M_FATAL)
- msg (M_INFO, "Exiting due to fatal error");
-
-@@ -701,7 +715,10 @@ openvpn_exit (const int status)
- if (status == OPENVPN_EXIT_STATUS_GOOD)
- perf_output_results ();
- }
--
-+#ifdef TARGET_ANDROID
-+ android_openvpn_exit(status);
-+#endif
-+
- exit (status);
- }
-
-diff --git a/src/openvpn/jniglue.c b/src/openvpn/jniglue.c
-new file mode 100644
-index 0000000..2d52936
---- /dev/null
-+++ b/src/openvpn/jniglue.c
-@@ -0,0 +1,162 @@
-+#include <jni.h>
-+#include <android/log.h>
-+#include <stdlib.h>
-+#include <setjmp.h>
-+
-+#include "jniglue.h"
-+
-+JNIEXPORT jint Java_de_blinkt_OpenVPN_startOpenVPNThread(JNIEnv* env, jclass jc);
-+
-+
-+extern int main (int argc, char *argv[]);
-+
-+static jmp_buf jump_buffer;
-+
-+int callmain (int argc, char *argv[]) {
-+ if(!setjmp(jump_buffer))
-+ main(argc,argv);
-+}
-+
-+
-+void android_openvpn_exit(int status) {
-+ longjmp(jump_buffer,status+1);
-+}
-+
-+
-+void testmsg(char* m1, ...) {
-+ va_list arglist;
-+ va_start(arglist,m1);
-+ // vsnprintf(m1, 100, "foo bbaz",arglist);
-+ __android_log_vprint(ANDROID_LOG_DEBUG, "openvpn",m1, arglist);
-+ va_end(arglist);
-+}
-+
-+// Store env and class, we allow only one instance
-+// so make these variables global for now
-+jclass openvpnclass;
-+JNIEnv* openvpnjenv;
-+
-+//Lde/blinkt/openvpn/OpenVPN startOpenVPNThread startOpenVPNThread
-+ jint Java_de_blinkt_openvpn_OpenVPN_startOpenVPNThread(JNIEnv* env, jclass jc){
-+ char* argv[] = {"openvpn", "--client",
-+ "--dev","tun",
-+ "--comp-lzo",
-+// "--redirect-gateway","def1",
-+// "--pkcs12","/mnt/sdcard/Network_Certificate.p12",
-+ "--remote-cert-eku", "TLS Web Server Authentication",
-+ "--remote","openvpn.uni-paderborn.de",
-+ "--ca","/mnt/sdcard/ca.pem",
-+ "--key","/mnt/sdcard/schwabe.key",
-+ "--cert","/mnt/sdcard/schwabe.pem",
-+ "--verb","4"
-+ };
-+
-+ openvpnclass = jc;
-+ openvpnjenv= env;
-+ int argc=17;
-+
-+ return callmain(argc,argv);
-+ }
-+
-+void Java_de_blinkt_openvpn_OpenVPN_startOpenVPNThreadArgs(JNIEnv *env,jclass jc, jobjectArray stringArray) {
-+ openvpnclass = jc;
-+ openvpnjenv= env;
-+
-+ int stringCount = (*env)->GetArrayLength(env, stringArray);
-+
-+
-+ const char** argv = calloc(stringCount,sizeof(const char*));
-+
-+ int i;
-+ for (i=0; i<stringCount; i++) {
-+ jstring string = (jstring) (*env)->GetObjectArrayElement(env, stringArray, i);
-+ jboolean isCopy;
-+ const char* rawString = (*env)->GetStringUTFChars(env, string, &isCopy);
-+
-+ // Copy the string to able to release it
-+ argv[i] = rawString;
-+
-+ }
-+
-+ // Call main
-+ callmain(stringCount,argv);
-+
-+ // Release the Strings
-+ for(i=0; i<stringCount;i++){
-+ jstring string = (jstring) (*env)->GetObjectArrayElement(env, stringArray, i);
-+ (*env)->ReleaseStringUTFChars(env,string,argv[i]);
-+ }
-+ free(argv);
-+}
-+
-+
-+
-+
-+jint JNI_OnLoad(JavaVM *vm, void *reserved) {
-+ __android_log_write(ANDROID_LOG_DEBUG,"openvpn", "Loading openvpn native library $id$ compiled on " __DATE__ " " __TIME__ );
-+ return JNI_VERSION_1_2;
-+}
-+
-+void addInterfaceInformation(int mtu,const char* ifconfig_local, const char* ifconfig_remote)
-+{
-+ jstring jlocal = (*openvpnjenv)->NewStringUTF(openvpnjenv, ifconfig_local);
-+ jstring jremote = (*openvpnjenv)->NewStringUTF(openvpnjenv, ifconfig_remote);
-+
-+ jmethodID aMethodID = (*openvpnjenv)->GetStaticMethodID(openvpnjenv, openvpnclass, "addInterfaceInfo",
-+ "(ILjava/lang/String;Ljava/lang/String;)V");
-+ (*openvpnjenv)->CallStaticVoidMethod(openvpnjenv,openvpnclass,aMethodID,mtu,jlocal,jremote);
-+
-+ (*openvpnjenv)->DeleteLocalRef(openvpnjenv,jlocal);
-+ (*openvpnjenv)->DeleteLocalRef(openvpnjenv,jremote);
-+
-+
-+}
-+
-+void android_openvpn_log(int level,const char* prefix,const char* prefix_sep,const char* m1)
-+{
-+ __android_log_print(ANDROID_LOG_DEBUG,"openvpn","%s%s%s",prefix,prefix_sep,m1);
-+
-+ jstring jprefix = (*openvpnjenv)->NewStringUTF(openvpnjenv, prefix);
-+ jstring jmessage = (*openvpnjenv)->NewStringUTF(openvpnjenv, m1);
-+
-+ jmethodID aMethodID = (*openvpnjenv)->GetStaticMethodID(openvpnjenv, openvpnclass, "logMessage",
-+ "(ILjava/lang/String;Ljava/lang/String;)V");
-+
-+ (*openvpnjenv)->CallStaticVoidMethod(openvpnjenv,openvpnclass,aMethodID,level,jprefix,jmessage);
-+
-+ (*openvpnjenv)->DeleteLocalRef(openvpnjenv,jprefix);
-+ (*openvpnjenv)->DeleteLocalRef(openvpnjenv,jmessage);
-+
-+}
-+
-+
-+unsigned char android_protect_socket(int sockfd) {
-+ jmethodID aMethodID = (*openvpnjenv)->GetStaticMethodID(openvpnjenv, openvpnclass, "protectSocket",
-+ "(I)Z");
-+ return (*openvpnjenv)->CallStaticBooleanMethod(openvpnjenv,openvpnclass,aMethodID,sockfd);
-+
-+}
-+int android_open_tun () {
-+ jmethodID aMethodID = (*openvpnjenv)->GetStaticMethodID(openvpnjenv, openvpnclass, "openTunDevice",
-+ "()I");
-+ return (*openvpnjenv)->CallStaticIntMethod(openvpnjenv,openvpnclass,aMethodID);
-+
-+}
-+
-+void addRouteInformation(const char* dest, const char* mask, const char* gw) {
-+
-+ jstring jmask = (*openvpnjenv)->NewStringUTF(openvpnjenv, mask);
-+ jstring jdest = (*openvpnjenv)->NewStringUTF(openvpnjenv, dest);
-+ jstring jgw = (*openvpnjenv)->NewStringUTF(openvpnjenv, gw);
-+ jmethodID aMethodID = (*openvpnjenv)->GetStaticMethodID(openvpnjenv, openvpnclass, "addRoute",
-+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
-+ (*openvpnjenv)->CallStaticVoidMethod(openvpnjenv,openvpnclass,aMethodID,jdest,jmask,jgw);
-+
-+ (*openvpnjenv)->DeleteLocalRef(openvpnjenv,jmask);
-+ (*openvpnjenv)->DeleteLocalRef(openvpnjenv,jdest);
-+ (*openvpnjenv)->DeleteLocalRef(openvpnjenv,jgw);
-+
-+
-+}
-+
-+
-diff --git a/src/openvpn/jniglue.h b/src/openvpn/jniglue.h
-new file mode 100644
-index 0000000..cb3ae41
---- /dev/null
-+++ b/src/openvpn/jniglue.h
-@@ -0,0 +1,19 @@
-+//
-+// jniglue.h
-+// xcopenvpn
-+//
-+// Created by Arne Schwabe on 29.03.12.
-+// Copyright (c) 2012 Universität Paderborn. All rights reserved.
-+//
-+
-+#ifndef xcopenvpn_jniglue_h
-+#define xcopenvpn_jniglue_h
-+
-+void testmsg(char* m1, ...);
-+void addRouteInformation(const char* dest, const char* mask, const char* gw);
-+void addInterfaceInformation(int mtu,const char* ifconfig_local, const char* ifconfig_remote);
-+void android_openvpn_log(int level,const char* prefix,const char* prefix_sep,const char* m1);
-+void android_openvpn_exit(int status);
-+
-+
-+#endif
-diff --git a/src/openvpn/options.c b/src/openvpn/options.c
-index bd83843..fcf436c 100644
---- a/src/openvpn/options.c
-+++ b/src/openvpn/options.c
-@@ -560,6 +560,7 @@ static const char usage_message[] =
- #if OPENSSL_VERSION_NUMBER >= 0x00907000L
- " and CRLs).\n"
- #else /* OPENSSL_VERSION_NUMBER >= 0x00907000L */
-+#error WTF!
- ").\n"
- " WARNING: no support of CRL available with this version.\n"
- #endif /* OPENSSL_VERSION_NUMBER >= 0x00907000L */
-diff --git a/src/openvpn/route.c b/src/openvpn/route.c
-index 7c25c77..6c3ad90 100644
---- a/src/openvpn/route.c
-+++ b/src/openvpn/route.c
-@@ -1344,6 +1344,11 @@ add_route (struct route *r,
- argv_msg (D_ROUTE, &argv);
- status = openvpn_execve_check (&argv, es, 0, "ERROR: Linux route add command failed");
-
-+#elif defined (TARGET_ANDROID)
-+#include "jniglue.h"
-+
-+ addRouteInformation(network, netmask, gateway);
-+
- #elif defined (WIN32)
- {
- DWORD ai = TUN_ADAPTER_INDEX_INVALID;
-@@ -2371,7 +2376,7 @@ show_routes (int msglev)
- gc_free (&gc);
- }
-
--#elif defined(TARGET_LINUX)
-+#elif defined(TARGET_LINUX) || defined(TARGET_ANDROID)
-
- void
- get_default_gateway (struct route_gateway_info *rgi)
-diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c
-index 6b1f8d2..364b97e 100644
---- a/src/openvpn/socket.c
-+++ b/src/openvpn/socket.c
-@@ -41,6 +41,11 @@
-
- #include "memdbg.h"
-
-+#ifdef TARGET_ANDROID
-+#include "jniglue.h"
-+#endif
-+
-+
- const int proto_overhead[] = { /* indexed by PROTO_x */
- 0,
- IPv4_UDP_HEADER_SIZE, /* IPv4 */
-@@ -858,6 +863,11 @@ create_socket_tcp (void)
- }
- #endif
-
-+#ifdef TARGET_ANDROID
-+ /* Protects the socket from being routed via VPN */
-+ android_protect_socket(sd);
-+#endif
-+
- return sd;
- }
-
-@@ -885,6 +895,12 @@ create_socket_udp (const unsigned int flags)
- #endif
- }
- #endif
-+
-+#ifdef TARGET_ANDROID
-+ /* Protects the socket from being routed via VPN */
-+ android_protect_socket(sd);
-+#endif
-+
- return sd;
- }
-
-@@ -904,6 +920,11 @@ create_socket_udp6 (const unsigned int flags)
- msg(M_SOCKERR, "UDP: failed setsockopt for IPV6_RECVPKTINFO");
- }
- #endif
-+#ifdef TARGET_ANDROID
-+ /* Protects the socket from being routed via VPN */
-+ android_protect_socket(sd);
-+#endif
-+
- return sd;
- }
-
-@@ -922,6 +943,10 @@ create_socket_tcp6 (void)
- (void *) &on, sizeof (on)) < 0)
- msg (M_SOCKERR, "TCP: Cannot setsockopt SO_REUSEADDR on TCP6 socket");
- }
-+#ifdef TARGET_ANDROID
-+ /* Protects the socket from being routed via VPN */
-+ android_protect_socket(sd);
-+#endif
-
- return sd;
- }
-diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
-index 251f8ed..537fc12 100644
---- a/src/openvpn/ssl.c
-+++ b/src/openvpn/ssl.c
-@@ -1645,6 +1645,8 @@ push_peer_info(struct buffer *buf, struct tls_session *session)
- buf_printf (&out, "IV_PLAT=netbsd\n");
- #elif defined(TARGET_FREEBSD)
- buf_printf (&out, "IV_PLAT=freebsd\n");
-+#elif defined(TARGET_ANDROID)
-+ buf_printf(&out, "IV_PLAT=android\n");
- #elif defined(WIN32)
- buf_printf (&out, "IV_PLAT=win\n");
- #endif
-diff --git a/src/openvpn/syshead.h b/src/openvpn/syshead.h
-index 0595b67..56a5429 100644
---- a/src/openvpn/syshead.h
-+++ b/src/openvpn/syshead.h
-@@ -211,7 +211,7 @@
- #include <net/if_tap.h>
- #endif
-
--#ifdef TARGET_LINUX
-+#if defined(TARGET_LINUX) || defined (TARGET_ANDROID)
-
- #if defined(HAVE_NETINET_IF_ETHER_H)
- #include <netinet/if_ether.h>
-diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
-index b99071c..db8104d 100644
---- a/src/openvpn/tun.c
-+++ b/src/openvpn/tun.c
-@@ -49,6 +49,11 @@
-
- #include "memdbg.h"
-
-+#ifdef TARGET_ANDROID
-+#include "jniglue.h"
-+#endif
-+
-+
- #ifdef WIN32
-
- /* #define SIMULATE_DHCP_FAILED */ /* simulate bad DHCP negotiation */
-@@ -768,6 +773,8 @@ do_ifconfig (struct tuntap *tt,
- tt->did_ifconfig = true;
-
- #endif /*ENABLE_IPROUTE*/
-+#elif defined(TARGET_ANDROID)
-+ addInterfaceInformation(tun_mtu,ifconfig_local, ifconfig_remote_netmask);
- #elif defined(TARGET_SOLARIS)
-
- /* Solaris 2.6 (and 7?) cannot set all parameters in one go...
-@@ -1365,7 +1372,16 @@ close_tun_generic (struct tuntap *tt)
-
- #endif
-
--#if defined(TARGET_LINUX)
-+#if defined(TARGET_LINUX) || defined(TARGET_ANDROID)
-+
-+#if defined (TARGET_ANDROID)
-+void
-+open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
-+{
-+ tt->fd = android_open_tun();
-+}
-+
-+#else
-
- #ifdef HAVE_LINUX_IF_TUN_H /* New driver support */
-
-@@ -1373,6 +1389,7 @@ close_tun_generic (struct tuntap *tt)
- #error header file linux/sockios.h required
- #endif
-
-+
- #if defined(HAVE_TUN_PI) && defined(HAVE_IPHDR) && defined(HAVE_IOVEC) && defined(ETH_P_IPV6) && defined(ETH_P_IP) && defined(HAVE_READV) && defined(HAVE_WRITEV)
- #define LINUX_IPV6 1
- /* #warning IPv6 ON */
-@@ -1426,7 +1443,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
- if (!tt->ipv6)
- ifr.ifr_flags = IFF_NO_PI;
-
--#if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN)
-+#if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN) && !defined(TARGET_ANDROID)
- ifr.ifr_flags |= IFF_ONE_QUEUE;
- #endif
-
-@@ -1516,6 +1533,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
- }
-
- #endif /* HAVE_LINUX_IF_TUN_H */
-+#endif /* TARGET_ANDROID */
-
- #ifdef TUNSETPERSIST
-
-diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h
-index 9bd990f..63ab872 100644
---- a/src/openvpn/tun.h
-+++ b/src/openvpn/tun.h
-@@ -292,6 +292,8 @@ ifconfig_order(void)
- return IFCONFIG_AFTER_TUN_OPEN;
- #elif defined(WIN32)
- return IFCONFIG_BEFORE_TUN_OPEN;
-+#elif defined(TARGET_ANDROID)
-+ return IFCONFIG_BEFORE_TUN_OPEN;
- #else
- return IFCONFIG_DEFAULT;
- #endif
---
-1.7.5.4
-
diff --git a/openvpn/src/openvpn/error.c b/openvpn/src/openvpn/error.c
index 83a9eb4..e2e24b1 100644
--- a/openvpn/src/openvpn/error.c
+++ b/openvpn/src/openvpn/error.c
@@ -199,11 +199,6 @@ msg_fp(const unsigned int flags)
int x_msg_line_num; /* GLOBAL */
-#include "android/log.h"
-
-
-
-
void x_msg (const unsigned int flags, const char *format, ...)
{
struct gc_arena gc;
@@ -219,7 +214,6 @@ void x_msg (const unsigned int flags, const char *format, ...)
const char *prefix_sep;
void usage_small (void);
-
#ifndef HAVE_VARARG_MACROS
/* the macro has checked this otherwise */
@@ -304,12 +298,10 @@ void x_msg (const unsigned int flags, const char *format, ...)
if (!prefix)
prefix_sep = prefix = "";
-
/* virtual output capability used to copy output to management subsystem */
if (!forked)
{
const struct virtual_output *vo = msg_get_virtual_output ();
-
if (vo)
{
openvpn_snprintf (m2, ERR_BUF_SIZE, "%s%s%s",
@@ -331,7 +323,7 @@ void x_msg (const unsigned int flags, const char *format, ...)
m1);
#endif
}
- else // No Syslog
+ else
{
FILE *fp = msg_fp(flags);
const bool show_usec = check_debug_level (DEBUG_LEVEL_USEC_TIME);
@@ -356,13 +348,8 @@ void x_msg (const unsigned int flags, const char *format, ...)
fflush(fp);
++x_msg_line_num;
}
-#ifdef TARGET_ANDROID
- android_openvpn_log(prefix,prefix_sep,m1);;
-#endif
}
-
-
if (flags & M_FATAL)
msg (M_INFO, "Exiting due to fatal error");
diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c
index 7101097..b92c282 100644
--- a/openvpn/src/openvpn/socket.c
+++ b/openvpn/src/openvpn/socket.c
@@ -859,7 +859,6 @@ create_socket_tcp (void)
msg (M_SOCKERR, "TCP: Cannot setsockopt SO_LINGER on TCP socket");
}
#endif
-
return sd;
}
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 90009e8..9073c0b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -185,4 +185,8 @@
<string name="faq_shortcut">Shortcut to start</string>
<string name="faq_howto_shortcut">You can place a shortcut to start OpenVPN on your desktop. Depending on your homescreen program you have to add a shortcut or a widget.</string>
<string name="no_vpn_support_image">Your image does not support the VPNService API,sorry :(</string>
+ <string name="encryption">Encryption</string>
+ <string name="cipher_dialog_title">Enter Encryption method</string>
+ <string name="chipher_dialog_message">Enter the cipher key for openvpn. Leave empty to use default cipher</string>
+ <string name="settings_auth">Authentication/Encryption</string>
</resources>
diff --git a/res/xml/vpn_authentification.xml b/res/xml/vpn_authentification.xml
index bd8d8ca..79d6969 100644
--- a/res/xml/vpn_authentification.xml
+++ b/res/xml/vpn_authentification.xml
@@ -28,14 +28,20 @@
android:title="@string/tls_auth_file" />
<ListPreference
+ android:dependency="useTLSAuth"
android:entries="@array/tls_directions_entries"
- android:dependency="useTLSAuth"
-
android:entryValues="@array/tls_directions_values"
android:key="tls_direction"
android:persistent="false"
android:title="@string/tls_direction" />
</PreferenceCategory>
-/>
+ <PreferenceCategory android:title="@string/encryption" >
+ <EditTextPreference
+ android:dialogMessage="@string/chipher_dialog_message"
+ android:dialogTitle="@string/cipher_dialog_title"
+ android:key="cipher"
+ android:persistent="false"
+ android:title="Encryption cipher" />
+ </PreferenceCategory>
</PreferenceScreen> \ No newline at end of file
diff --git a/res/xml/vpn_headers.xml b/res/xml/vpn_headers.xml
index f755dc8..60ddce7 100644
--- a/res/xml/vpn_headers.xml
+++ b/res/xml/vpn_headers.xml
@@ -15,8 +15,7 @@
android:title="IP Settings" />
<header
android:fragment="de.blinkt.openvpn.Settings_Authentication"
- android:summary="Authentication"
- android:title="Authentication" />
+ android:title="@string/settings_auth" />
<!-- android:icon="@drawable/ic_settings_display" -->
<header
diff --git a/src/de/blinkt/openvpn/ConfigParser.java b/src/de/blinkt/openvpn/ConfigParser.java
new file mode 100644
index 0000000..8497330
--- /dev/null
+++ b/src/de/blinkt/openvpn/ConfigParser.java
@@ -0,0 +1,232 @@
+package de.blinkt.openvpn;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Vector;
+
+//! Openvpn Config FIle Parser, probably not 100% accurate but close enough
+
+// And rember, this is valid :)
+// --<foo>
+// bar
+// </bar>
+public class ConfigParser {
+
+
+ private HashMap<String,Vector<String>> options = new HashMap<String, Vector<String>>();
+ private void parseConfig(String filename) throws IOException, ConfigParseError {
+
+
+ FileReader fr = new FileReader(filename);
+ BufferedReader br =new BufferedReader(fr);
+
+ int lineno=0;
+
+ while (true){
+ String line = br.readLine();
+ if(line==null)
+ break;
+ lineno++;
+ System.out.print("LINE:");
+ System.out.println(line);
+ Vector<String> args = parseline(line);
+ if(args.size() ==0)
+ continue;
+
+
+
+ if(args.get(0).startsWith("--"))
+ args.set(0, args.get(0).substring(2));
+
+ checkinlinefile(args,br);
+
+ options.put(args.get(0), args);
+ }
+ }
+
+ private void checkinlinefile(Vector<String> args, BufferedReader br) throws IOException, ConfigParseError {
+ String arg0 = args.get(0);
+ // CHeck for <foo>
+ if(arg0.startsWith("<") && arg0.endsWith(">")) {
+ String argname = arg0.substring(1, arg0.length()-1);
+ String inlinefile = "";
+
+ String endtag = String.format("</%s>",argname);
+ do {
+ String line = br.readLine();
+ if(line==null){
+ throw new ConfigParseError(String.format("No endtag </%s> for starttag <%s> found",argname,argname));
+ }
+ if(line.equals(endtag))
+ break;
+ else {
+ inlinefile+=line;
+ inlinefile+= "\n";
+ }
+ } while(true);
+
+ args.clear();
+ args.add(argname);
+ args.add(inlinefile);
+ }
+
+ }
+
+ enum linestate {
+ initial,
+ readin_single_quote
+ , reading_quoted, reading_unquoted, done}
+
+ private boolean space(char c) {
+ // I really hope nobody is using zero bytes inside his/her config file
+ // to sperate parameter but here we go:
+ return Character.isSpace(c) || c == '\0';
+
+ }
+
+ public class ConfigParseError extends Exception {
+ private static final long serialVersionUID = -60L;
+
+ public ConfigParseError(String msg) {
+ super(msg);
+ }
+ }
+
+
+ // adapted openvpn's parse function to java
+ private Vector<String> parseline(String line) throws ConfigParseError {
+ Vector<String> parameters = new Vector<String>();
+
+ if (line.length()==0)
+ return parameters;
+
+
+ linestate state = linestate.initial;
+ boolean backslash = false;
+ char out=0;
+
+ int pos=0;
+ String currentarg="";
+
+ do {
+ // Emulate the c parsing ...
+ char in;
+ if(pos < line.length())
+ in = line.charAt(pos);
+ else
+ in = '\0';
+
+ if (!backslash && in == '\\' && state != linestate.readin_single_quote)
+ {
+ backslash = true;
+ }
+ else
+ {
+ if (state == linestate.initial)
+ {
+ if (!space (in))
+ {
+ if (in == ';' || in == '#') /* comment */
+ break;
+ if (!backslash && in == '\"')
+ state = linestate.reading_quoted;
+ else if (!backslash && in == '\'')
+ state = linestate.readin_single_quote;
+ else
+ {
+ out = in;
+ state = linestate.reading_unquoted;
+ }
+ }
+ }
+ else if (state == linestate.reading_unquoted)
+ {
+ if (!backslash && space (in))
+ state = linestate.done;
+ else
+ out = in;
+ }
+ else if (state == linestate.reading_quoted)
+ {
+ if (!backslash && in == '\"')
+ state = linestate.done;
+ else
+ out = in;
+ }
+ else if (state == linestate.readin_single_quote)
+ {
+ if (in == '\'')
+ state = linestate.done;
+ else
+ out = in;
+ }
+
+ if (state == linestate.done)
+ {
+ /* ASSERT (parm_len > 0); */
+ state = linestate.initial;
+ parameters.add(currentarg);
+ currentarg = "";
+ out =0;
+ }
+
+ if (backslash && out!=0)
+ {
+ if (!(out == '\\' || out == '\"' || space (out)))
+ {
+ throw new ConfigParseError("Options warning: Bad backslash ('\\') usage");
+ }
+ }
+ backslash = false;
+ }
+
+ /* store parameter character */
+ if (out!=0)
+ {
+ currentarg+=out;
+ }
+ } while (pos++ < line.length());
+
+ return parameters;
+ }
+
+ void convertProfile() throws ConfigParseError{
+ VpnProfile newprofile = new VpnProfile("converted Profile");
+ // Pull, client, tls-client
+
+ if(options.containsKey("client") || options.containsKey("pull")) {
+ newprofile.mUsePull=true;
+ options.remove("pull");
+ options.remove("client");
+ }
+
+ if(options.containsKey("secret")){
+ newprofile.mAuthenticationType=VpnProfile.TYPE_STATICKEYS;
+ options.remove("secret");
+ }
+
+ if(options.containsKey("redirect-gateway")) {
+ options.remove("redirect-gateway");
+ newprofile.mUseDefaultRoute=true;
+ } else {
+ newprofile.mUseDefaultRoute=true;
+ }
+
+ Vector<String> mode = options.get("mode");
+ if (mode != null){
+ options.remove("mode");
+ if(mode.size() != 2)
+ throw new ConfigParseError("--mode has more than one parameter");
+ if(!mode.get(1).equals("p2p"))
+ throw new ConfigParseError("Invalid mode for --mode specified");
+ }
+
+ }
+
+}
+
+
+
+
diff --git a/src/de/blinkt/openvpn/LaunchVPN.java b/src/de/blinkt/openvpn/LaunchVPN.java
index 858c8d3..8aeb996 100644
--- a/src/de/blinkt/openvpn/LaunchVPN.java
+++ b/src/de/blinkt/openvpn/LaunchVPN.java
@@ -212,11 +212,15 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener {
}
private boolean writeMiniVPN() {
+ File mvpnout = new File(getCacheDir(),"minivpn");
+ if (mvpnout.exists() && mvpnout.canExecute())
+ return true;
+
if(minivpnwritten)
return true;
try {
InputStream mvpn = getAssets().open("minivpn");
- File mvpnout = new File(getCacheDir(),"minivpn");
+
FileOutputStream fout = new FileOutputStream(mvpnout);
byte buf[]= new byte[4096];
diff --git a/src/de/blinkt/openvpn/OpenVpnService.java b/src/de/blinkt/openvpn/OpenVpnService.java
index a3df9fd..9f0f732 100644
--- a/src/de/blinkt/openvpn/OpenVpnService.java
+++ b/src/de/blinkt/openvpn/OpenVpnService.java
@@ -17,9 +17,14 @@
package de.blinkt.openvpn;
import java.io.IOException;
+import java.util.List;
import java.util.Vector;
+import android.R.anim;
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.PendingIntent;
+import android.content.Context;
import android.content.Intent;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
@@ -117,11 +122,10 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
- private LocalSocket openManagmentInterface() {
+ private LocalSocket openManagmentInterface(int tries) {
// Could take a while to open connection
String socketname = (getCacheDir().getAbsolutePath() + "/" + "mgmtsocket");
LocalSocket sock = new LocalSocket();
- int tries = 8;
while(tries > 0 && !sock.isConnected()) {
try {
@@ -142,6 +146,14 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
+ // Extract information from the intent.
+ String prefix = getPackageName();
+ String[] argv = intent.getStringArrayExtra(prefix + ".ARGV");
+
+ String profileUUID = intent.getStringExtra(prefix + ".profileUUID");
+ mProfile = ProfileManager.get(profileUUID);
+
+
// The handler is only used to show messages.
if (mHandler == null) {
mHandler = new Handler(this);
@@ -164,13 +176,19 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
}
}
+ // See if there is a managment socket we can connect to and kill the process too
+ LocalSocket mgmtsocket = openManagmentInterface(1);
+ if(mgmtsocket!=null) {
+ // Fire and forget :)
+ new OpenVpnManagementThread(mProfile,mgmtsocket,this).managmentCommand("signal SIGINT\n");
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ //checkForRemainingMiniVpns();
+ }
- // Extract information from the intent.
- String prefix = getPackageName();
- String[] argv = intent.getStringArrayExtra(prefix + ".ARGV");
- String profileUUID = intent.getStringExtra(prefix + ".profileUUID");
- mProfile = ProfileManager.get(profileUUID);
// Start a new session by creating a new thread.
@@ -181,7 +199,7 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
// Open the Management Interface
- LocalSocket mgmtsocket = openManagmentInterface();
+ mgmtsocket = openManagmentInterface(8);
if(mgmtsocket!=null) {
// start a Thread that handles incoming messages of the managment socket
@@ -197,6 +215,23 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
+ private void checkForRemainingMiniVpns() {
+ ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ if (manager == null)
+ return;
+ List<RunningAppProcessInfo> service= manager.getRunningAppProcesses();
+ // Does not return the minivpn binarys :S
+ for(RunningAppProcessInfo rapi:service){
+ if(rapi.processName.equals("minivpn"))
+ android.os.Process.killProcess(rapi.pid);
+ }
+ }
+
+
+
+
+
+
@Override
public void onDestroy() {
if (mServiceThread != null) {
diff --git a/src/de/blinkt/openvpn/Settings_Authentication.java b/src/de/blinkt/openvpn/Settings_Authentication.java
index 57d9941..4124783 100644
--- a/src/de/blinkt/openvpn/Settings_Authentication.java
+++ b/src/de/blinkt/openvpn/Settings_Authentication.java
@@ -24,6 +24,7 @@ public class Settings_Authentication extends PreferenceFragment implements OnPre
private ListPreference mTLSAuthDirection;
private Preference mTLSAuthFile;
private SwitchPreference mUseTLSAuth;
+ private EditTextPreference mCipher;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -45,6 +46,9 @@ public class Settings_Authentication extends PreferenceFragment implements OnPre
mProfile = ProfileManager.get(profileUUID);
mTLSAuthFile.setOnPreferenceClickListener(this);
+ mCipher =(EditTextPreference) findPreference("cipher");
+ mCipher.setOnPreferenceChangeListener(this);
+
loadSettings();
}
@@ -59,6 +63,8 @@ public class Settings_Authentication extends PreferenceFragment implements OnPre
mUseTLSAuth.setChecked(mProfile.mUseTLSAuth);
mTLSAuthFile.setSummary(mProfile.mTLSAuthFilename);
mTLSAuthDirection.setValue(mProfile.mTLSAuthDirection);
+ mCipher.setText(mProfile.mCipher);
+ onPreferenceChange(mCipher, mProfile.mCipher);
}
private void saveSettings() {
@@ -76,6 +82,12 @@ public class Settings_Authentication extends PreferenceFragment implements OnPre
mProfile.mTLSAuthDirection=null;
else
mProfile.mTLSAuthDirection = mTLSAuthDirection.getValue().toString();
+
+ if(mCipher.getText()==null)
+ mProfile.mCipher=null;
+ else
+ mProfile.mCipher = mCipher.getText();
+
}
@Override
@@ -91,6 +103,8 @@ public class Settings_Authentication extends PreferenceFragment implements OnPre
preference.setSummary(mProfile.mServerName);
else
preference.setSummary((String)newValue);
+ } else if (preference == mCipher) {
+ preference.setSummary((CharSequence) newValue);
}
return true;
}
diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java
index 26cf50b..63d6876 100644
--- a/src/de/blinkt/openvpn/VpnProfile.java
+++ b/src/de/blinkt/openvpn/VpnProfile.java
@@ -90,10 +90,13 @@ public class VpnProfile implements Serializable{
public boolean mUseCustomConfig=false;
public String mCustomConfigOptions="";
public String mVerb="1";
+ public String mCipher="";
- public static String openVpnEscape(String unescape) {
- String escapedString = unescape.replace("\\", "\\\\");
+ public static String openVpnEscape(String unescaped) {
+ if(unescaped==null)
+ return null;
+ String escapedString = unescaped.replace("\\", "\\\\");
escapedString = escapedString.replace("\"","\\\"");
escapedString = escapedString.replace("\n","\\n");
return '"' + escapedString + '"';
@@ -269,6 +272,9 @@ public class VpnProfile implements Serializable{
cfg += "remote-cert-tls server\n";
+ if(nonNull(mCipher)){
+ cfg += "cipher " + mCipher + "\n";
+ }
// Obscure Settings dialog
@@ -291,6 +297,13 @@ public class VpnProfile implements Serializable{
return cfg;
}
+ private boolean nonNull(String val) {
+ if(val == null || val.equals(""))
+ return false;
+ else
+ return true;
+ }
+
private Collection<String> getCustomRoutes() {
Vector<String> cidrRoutes=new Vector<String>();
if(mCustomRoutes==null) {
@@ -343,7 +356,7 @@ public class VpnProfile implements Serializable{
Vector<String> args = new Vector<String>();
// Add fixed paramenters
- //args.add(cacheDir.getAbsolutePath() +"/" +"openvpn");
+ //args.add("/data/data/de.blinkt.openvpn/lib/openvpn");
args.add(cacheDir.getAbsolutePath() +"/" +"minivpn");
args.add("--config");
diff --git a/todo.txt b/todo.txt
index c12a014..49fc9a8 100644
--- a/todo.txt
+++ b/todo.txt
@@ -41,4 +41,5 @@ Requested by users:
cipher
auth
mtu-link
+nobind