diff options
-rw-r--r-- | AndroidManifest.xml | 4 | ||||
-rw-r--r-- | jni/Android.mk | 3 | ||||
-rw-r--r-- | openvpn/Android.mk | 8 | ||||
-rw-r--r-- | openvpn/src/openvpn/error.c | 5 | ||||
-rw-r--r-- | openvpn/src/openvpn/jniglue.c | 130 | ||||
-rw-r--r-- | openvpn/src/openvpn/jniglue.h | 3 | ||||
-rw-r--r-- | openvpn/src/openvpn/manage.c | 10 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVPN.java | 9 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVPNThread.java | 50 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVpnManagementThread.java | 30 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVpnService.java | 6 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/VpnProfile.java | 3 |
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); |