summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2012-05-09 02:06:17 +0200
committerArne Schwabe <arne@rfc2549.org>2012-05-09 02:06:17 +0200
commit95d6e0331e2db3404475efb91b5a7535b843099a (patch)
tree8612dfd7101b3fe8b527367090e4818184b6bb2d
parent379ae9173874ebe7d3811f0fde9b75221c349386 (diff)
Openvpn as external external program is coming nearer ....
-rw-r--r--AndroidManifest.xml4
-rw-r--r--jni/Android.mk3
-rw-r--r--openvpn/Android.mk8
-rw-r--r--openvpn/src/openvpn/error.c5
-rw-r--r--openvpn/src/openvpn/jniglue.c130
-rw-r--r--openvpn/src/openvpn/jniglue.h3
-rw-r--r--openvpn/src/openvpn/manage.c10
-rw-r--r--src/de/blinkt/openvpn/OpenVPN.java9
-rw-r--r--src/de/blinkt/openvpn/OpenVPNThread.java50
-rw-r--r--src/de/blinkt/openvpn/OpenVpnManagementThread.java30
-rw-r--r--src/de/blinkt/openvpn/OpenVpnService.java6
-rw-r--r--src/de/blinkt/openvpn/VpnProfile.java3
12 files changed, 99 insertions, 162 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7c1e07b9..843da00b 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="20"
- android:versionName="0.4.10" >
+ android:versionCode="21"
+ android:versionName="0.5.0" >
<uses-permission android:name="android.permission.INTERNET" />
diff --git a/jni/Android.mk b/jni/Android.mk
index 83b84c81..ff17b27b 100644
--- a/jni/Android.mk
+++ b/jni/Android.mk
@@ -7,6 +7,3 @@ include lzo/Android.mk
include openssl/Android.mk
include openvpn/Android.mk
-
-
-
diff --git a/openvpn/Android.mk b/openvpn/Android.mk
index 13f23a78..78849702 100644
--- a/openvpn/Android.mk
+++ b/openvpn/Android.mk
@@ -8,8 +8,9 @@ LOCAL_C_INCLUDES := openssl/include lzo/include openssl/crypto openssl openvpn/s
-LOCAL_SHARED_LIBRARIES := libssl libcrypto liblzo
-#LOCAL_STATIC_LIBRARIES := libssl libcrypto liblzo
+#LOCAL_SHARED_LIBRARIES := libssl libcrypto liblzo
+LOCAL_STATIC_LIBRARIES := libssl_static libcrypto_static liblzo-static
+
LOCAL_CFLAGS= -DHAVE_CONFIG_H
LOCAL_MODULE = openvpn
@@ -87,4 +88,5 @@ LOCAL_SRC_FILES:= src/openvpn/jniglue.c \
src/openvpn/status.c \
src/openvpn/tun.c
-include $(BUILD_SHARED_LIBRARY)
+#include $(BUILD_SHARED_LIBRARY)
+include $(BUILD_EXECUTABLE)
diff --git a/openvpn/src/openvpn/error.c b/openvpn/src/openvpn/error.c
index 68497941..83a9eb4b 100644
--- a/openvpn/src/openvpn/error.c
+++ b/openvpn/src/openvpn/error.c
@@ -714,10 +714,7 @@ 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/openvpn/src/openvpn/jniglue.c b/openvpn/src/openvpn/jniglue.c
index e11cabd4..c79272d7 100644
--- a/openvpn/src/openvpn/jniglue.c
+++ b/openvpn/src/openvpn/jniglue.c
@@ -5,144 +5,14 @@
#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);
-}
-
-
-// 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);
-
-}
-
-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/openvpn/src/openvpn/jniglue.h b/openvpn/src/openvpn/jniglue.h
index 236c0323..a86d52da 100644
--- a/openvpn/src/openvpn/jniglue.h
+++ b/openvpn/src/openvpn/jniglue.h
@@ -8,8 +8,5 @@
#ifndef xcopenvpn_jniglue_h
#define xcopenvpn_jniglue_h
-
-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/openvpn/src/openvpn/manage.c b/openvpn/src/openvpn/manage.c
index 96ca6eaa..f7ca8e15 100644
--- a/openvpn/src/openvpn/manage.c
+++ b/openvpn/src/openvpn/manage.c
@@ -58,6 +58,9 @@
#define MANAGEMENT_ECHO_FLAGS 0
#endif
+#include <android/log.h>
+
+
/* tag for blank username/password */
static const char blank_up[] = "[[BLANK]]";
@@ -1808,6 +1811,7 @@ man_io_error (struct management *man, const char *prefix)
return false;
}
+
static int
man_read (struct management *man)
{
@@ -1820,8 +1824,12 @@ man_read (struct management *man)
#ifdef TARGET_ANDROID
len = read_fd (man->connection.sd_cli, buf, sizeof (buf), MSG_NOSIGNAL, &fd);
- if(fd >= 0)
+ __android_log_print(ANDROID_LOG_DEBUG,"openvpn-dbg","read_fd %d %d", len, fd);
+ if(fd >= 0) {
man->connection.lastfdreceived = fd;
+ if(len == 0) // No data message but a fd, return without resetting socket...
+ return 0;
+ }
#else
len = recv (man->connection.sd_cli, buf, sizeof (buf), MSG_NOSIGNAL);
#endif
diff --git a/src/de/blinkt/openvpn/OpenVPN.java b/src/de/blinkt/openvpn/OpenVPN.java
index e524da1c..58187df2 100644
--- a/src/de/blinkt/openvpn/OpenVPN.java
+++ b/src/de/blinkt/openvpn/OpenVPN.java
@@ -8,7 +8,7 @@ import android.util.Log;
public class OpenVPN {
private static OpenVpnService mOpenVpnService;
private static final int MAXLOGENTRIES = 500;
- public static native int startOpenVPNThreadArgs(String argv[]);
+ //public static native int startOpenVPNThreadArgs(String argv[]);
private static final String TAG = "OpenVpn";
@@ -21,13 +21,14 @@ public class OpenVPN {
public interface LogListener {
void newLog(String logmessage);
}
-
+
+ /*
static {
System.loadLibrary("crypto");
System.loadLibrary("ssl");
System.loadLibrary("lzo");
System.loadLibrary("openvpn");
- }
+ }*/
synchronized static void logMessage(int level,String prefix, String message)
{
@@ -39,7 +40,7 @@ public class OpenVPN {
// but kills me for logging 100 messages with too many references :(
// Force GC how and then to kill loose ends
if(counter++ % 50==0) {
- System.gc();
+ //System.gc();
}
for (LogListener ll : logListener) {
diff --git a/src/de/blinkt/openvpn/OpenVPNThread.java b/src/de/blinkt/openvpn/OpenVPNThread.java
index a5b3e5e4..a8cb8430 100644
--- a/src/de/blinkt/openvpn/OpenVPNThread.java
+++ b/src/de/blinkt/openvpn/OpenVPNThread.java
@@ -1,6 +1,12 @@
package de.blinkt.openvpn;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
import java.util.Arrays;
+import java.util.LinkedList;
import android.util.Log;
@@ -8,12 +14,17 @@ public class OpenVPNThread implements Runnable {
private static final String TAG = "OpenVPN";
private OpenVpnService mService;
private String[] mArgv;
+ private Process mProcess;
public OpenVPNThread(OpenVpnService service,String[] argv)
{
mService = service;
mArgv = argv;
}
+
+ public void stopProcess() {
+ mProcess.destroy();
+ }
@Override
public void run() {
@@ -35,12 +46,9 @@ public class OpenVPNThread implements Runnable {
OpenVPN.logMessage(0, "argv:" , Arrays.toString(mArgv));
- OpenVPN.startOpenVPNThreadArgs(mArgv);
-
+ startOpenVPNThreadArgs(mArgv);
-
- // Sleep for a while. This also checks if we got interrupted.
- Thread.sleep(3000);
+
//}
Log.i(TAG, "Giving up");
} catch (Exception e) {
@@ -60,4 +68,36 @@ public class OpenVPNThread implements Runnable {
Log.i(TAG, "Exiting");
}
}
+
+ private void startOpenVPNThreadArgs(String[] argv) {
+ LinkedList<String> argvlist = new LinkedList<String>();
+
+ for(String arg:argv)
+ argvlist.add(arg);
+
+ ProcessBuilder pb = new ProcessBuilder(argvlist);
+ pb.redirectErrorStream(true);
+ try {
+ mProcess = pb.start();
+ // Close the output, since we don't need it
+ mProcess.getOutputStream().close();
+ InputStream in = mProcess.getInputStream();
+ BufferedReader br = new BufferedReader(new InputStreamReader(in));
+
+
+ while(true) {
+ String logline = br.readLine();
+ if(logline==null)
+ return;
+ OpenVPN.logMessage(0, "P:", logline);
+ }
+
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ stopProcess();
+ }
+
+
+ }
}
diff --git a/src/de/blinkt/openvpn/OpenVpnManagementThread.java b/src/de/blinkt/openvpn/OpenVpnManagementThread.java
index fd7fe8a8..31ea49e8 100644
--- a/src/de/blinkt/openvpn/OpenVpnManagementThread.java
+++ b/src/de/blinkt/openvpn/OpenVpnManagementThread.java
@@ -30,10 +30,12 @@ public class OpenVpnManagementThread implements Runnable {
public void managmentCommand(String cmd) {
+ Log.d("openvpn", "mgmt cmd" + mSocket + " " +cmd + " " );
try {
mSocket.getOutputStream().write(cmd.getBytes());
mSocket.getOutputStream().flush();
} catch (IOException e) {
+ e.printStackTrace();
}
}
@@ -94,10 +96,14 @@ public class OpenVpnManagementThread implements Runnable {
Method getInt = FileDescriptor.class.getDeclaredMethod("getInt$");
int fdint = (Integer) getInt.invoke(fd);
+ // You can even get more evil by parsing toString() and extract the int from that :)
+
Log.d("Openvpn", "Got FD from socket: " + fd + " " + fdint);
- ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(fdint);
+
mOpenVPNService.protect(fdint);
- pfd.close();
+
+ //ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(fdint);
+ //pfd.close();
return;
} catch (NoSuchMethodException e) {
e.printStackTrace();
@@ -107,8 +113,6 @@ public class OpenVpnManagementThread implements Runnable {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
}
Log.d("Openvpn", "Failed to retrieve fd from socket: " + fd);
}
@@ -142,10 +146,15 @@ public class OpenVpnManagementThread implements Runnable {
processPWCommand(argument);
} else if (cmd.equals("HOLD")) {
managmentCommand("hold release\n");
+ managmentCommand("log on\n");
+ managmentCommand("bytecount 13\n");
} else if (cmd.equals("NEED-OK")) {
processNeedCommand(argument);
+ } else if (cmd.equals("LOG")) {
+ OpenVPN.logMessage(0, "", command);
} else {
OpenVPN.logMessage(0, "MGMT:", "Got unrecognized command" + command);
+ managmentCommand("log 1\n");
Log.i(TAG, "Got unrecognized command" + command);
}
} else if (command.startsWith("SUCCESS:")) {
@@ -219,11 +228,17 @@ public class OpenVpnManagementThread implements Runnable {
FileDescriptor[] fds = {fdtosend};
mSocket.setFileDescriptorsForSend(fds);
- Log.d("Openvpn", "Sending FD tosocket: " + fdtosend + " " + fdint);
+ Log.d("Openvpn", "Sending FD tosocket: " + fdtosend + " " + fdint + " " + pfd);
// Trigger a send so we can close the fd on our side of the channel
+ // The API documentation fails to mention that it will not reset the file descriptor to
+ // be send and will happily send the file descriptor on every write ...
String cmd = String.format("needok '%s' %s\n", needed, "ok");
managmentCommand(cmd);
+
+ // Set the FileDescriptor to null to stop this mad behavior
+ mSocket.setFileDescriptorsForSend(null);
pfd.close();
+
return true;
} catch (NoSuchMethodException e) {
e.printStackTrace();
@@ -278,6 +293,11 @@ public class OpenVpnManagementThread implements Runnable {
for (OpenVpnManagementThread mt: active){
mt.managmentCommand("signal SIGINT\n");
sendCMD=true;
+ try {
+ mt.mSocket.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
return sendCMD;
}
diff --git a/src/de/blinkt/openvpn/OpenVpnService.java b/src/de/blinkt/openvpn/OpenVpnService.java
index 5c9df8b4..a3df9fde 100644
--- a/src/de/blinkt/openvpn/OpenVpnService.java
+++ b/src/de/blinkt/openvpn/OpenVpnService.java
@@ -151,13 +151,17 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
if(OpenVpnManagementThread.stopOpenVPN()){
// an old was asked to exit, wait 2s
try {
- Thread.sleep(2000);
+ Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
if (mServiceThread!=null) {
mServiceThread.interrupt();
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
}
diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java
index 3cbac8d7..ca5d99f6 100644
--- a/src/de/blinkt/openvpn/VpnProfile.java
+++ b/src/de/blinkt/openvpn/VpnProfile.java
@@ -345,7 +345,8 @@ public class VpnProfile implements Serializable{
Vector<String> args = new Vector<String>();
// Add fixed paramenters
- args.add("openvpn");
+ //args.add("/data/data/de.blinkt.openvpn/lib/openvpn");
+ args.add(cacheDir.getAbsolutePath() +"/" +"openvpn");
args.add("--config");
args.add(cacheDir.getAbsolutePath() + "/" + OVPNCONFIGFILE);