summaryrefslogtreecommitdiff
path: root/src/de/blinkt/openvpn
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2012-05-06 23:52:22 +0200
committerArne Schwabe <arne@rfc2549.org>2012-05-06 23:52:22 +0200
commitef42511eb479c40dc205e21c70e0871f35490e72 (patch)
tree48c8f08d3f2ce778a28f17f0abd25f5c75d67814 /src/de/blinkt/openvpn
parent49c3df575626efefe85b2fe14cad2dac6509d10d (diff)
All control of openvpn is now over the unix socket. JNI is only used for starting openvpn.
Fix configuration if no DNS information is available. (closes issue #7 hopefully) Version 0.5.0
Diffstat (limited to 'src/de/blinkt/openvpn')
-rw-r--r--src/de/blinkt/openvpn/OpenVPN.java16
-rw-r--r--src/de/blinkt/openvpn/OpenVpnManagementThread.java70
-rw-r--r--src/de/blinkt/openvpn/OpenVpnService.java43
-rw-r--r--src/de/blinkt/openvpn/VpnProfile.java65
4 files changed, 94 insertions, 100 deletions
diff --git a/src/de/blinkt/openvpn/OpenVPN.java b/src/de/blinkt/openvpn/OpenVPN.java
index cc827aae..e524da1c 100644
--- a/src/de/blinkt/openvpn/OpenVPN.java
+++ b/src/de/blinkt/openvpn/OpenVPN.java
@@ -8,7 +8,6 @@ import android.util.Log;
public class OpenVPN {
private static OpenVpnService mOpenVpnService;
private static final int MAXLOGENTRIES = 500;
- public static native int startOpenVPNThread();
public static native int startOpenVPNThreadArgs(String argv[]);
private static final String TAG = "OpenVpn";
@@ -30,14 +29,9 @@ public class OpenVPN {
System.loadLibrary("openvpn");
}
- static void addRoute(String dest,String mask, String gw) {
- Log.i("openvpn" ,"Got Routing information " + dest + " " + mask + " " + gw );
- mOpenVpnService.addRoute(dest,mask);
- }
-
synchronized static void logMessage(int level,String prefix, String message)
{
- logbuffer.addLast(prefix + " " + message);
+ logbuffer.addLast(prefix + message);
if(logbuffer.size()>MAXLOGENTRIES)
logbuffer.removeFirst();
@@ -49,7 +43,7 @@ public class OpenVPN {
}
for (LogListener ll : logListener) {
- ll.newLog(prefix + " " + message);
+ ll.newLog(prefix + message);
}
}
@@ -72,11 +66,7 @@ public class OpenVPN {
public static void setCallback(OpenVpnService openVpnService) {
mOpenVpnService = openVpnService;
}
-
- public static int openTunDevice() {
- Log.d(TAG,"Opening tun device");
- return mOpenVpnService.openTun();
- }
+
//! Dummy method being called to force loading of JNI Libraries
public static void foo() { }
diff --git a/src/de/blinkt/openvpn/OpenVpnManagementThread.java b/src/de/blinkt/openvpn/OpenVpnManagementThread.java
index fcdb6046..fd7fe8a8 100644
--- a/src/de/blinkt/openvpn/OpenVpnManagementThread.java
+++ b/src/de/blinkt/openvpn/OpenVpnManagementThread.java
@@ -34,7 +34,6 @@ public class OpenVpnManagementThread implements Runnable {
mSocket.getOutputStream().write(cmd.getBytes());
mSocket.getOutputStream().flush();
} catch (IOException e) {
- e.printStackTrace();
}
}
@@ -94,7 +93,7 @@ public class OpenVpnManagementThread implements Runnable {
try {
Method getInt = FileDescriptor.class.getDeclaredMethod("getInt$");
int fdint = (Integer) getInt.invoke(fd);
-
+
Log.d("Openvpn", "Got FD from socket: " + fd + " " + fdint);
ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(fdint);
mOpenVPNService.protect(fdint);
@@ -146,13 +145,17 @@ public class OpenVpnManagementThread implements Runnable {
} else if (cmd.equals("NEED-OK")) {
processNeedCommand(argument);
} else {
+ OpenVPN.logMessage(0, "MGMT:", "Got unrecognized command" + command);
Log.i(TAG, "Got unrecognized command" + command);
}
+ } else if (command.startsWith("SUCCESS:")) {
+ // ignore
} else {
Log.i(TAG, "Got unrecognized line from managment" + command);
+ OpenVPN.logMessage(0, "MGMT:", "Got unrecognized line from management:" + command);
}
}
-
+
private void processNeedCommand(String argument) {
int p1 =argument.indexOf('\'');
int p2 = argument.indexOf('\'',p1+1);
@@ -160,6 +163,9 @@ public class OpenVpnManagementThread implements Runnable {
String needed = argument.substring(p1+1, p2);
String extra = argument.split(":",2)[1];
+ String status = "ok";
+
+
if (needed.equals("PROTECTFD")) {
FileDescriptor fdtoprotect = mFDList.pollFirst();
protectFileDescriptor(fdtoprotect);
@@ -174,16 +180,66 @@ public class OpenVpnManagementThread implements Runnable {
String[] ifconfigparts = extra.split(" ");
int mtu = Integer.parseInt(ifconfigparts[2]);
mOpenVPNService.setLocalIP(ifconfigparts[0], ifconfigparts[1],mtu);
-
+ } else if (needed.equals("OPENTUN")) {
+ if(sendTunFD(needed,extra))
+ return;
+ else
+ status="cancel";
+ // This not nice or anything but setFileDescriptors accepts only FilDescriptor class :(
+
} else {
Log.e(TAG,"Unkown needok command " + argument);
return;
}
-
- String cmd = String.format("needok '%s' %s\n", needed, "ok");
+
+ String cmd = String.format("needok '%s' %s\n", needed, status);
managmentCommand(cmd);
}
+ private boolean sendTunFD (String needed, String extra) {
+ if(!extra.equals("tun")) {
+ // We only support tun
+ String errmsg = String.format("Devicetype %s requested, but only tun is possible with the Android API, sorry!",extra);
+ OpenVPN.logMessage(0, "", errmsg );
+
+ return false;
+ }
+ ParcelFileDescriptor pfd = mOpenVPNService.openTun();
+ if(pfd==null)
+ return false;
+
+ Method setInt;
+ int fdint = pfd.getFd();
+ try {
+ setInt = FileDescriptor.class.getDeclaredMethod("setInt$",int.class);
+ FileDescriptor fdtosend = new FileDescriptor();
+
+ setInt.invoke(fdtosend,fdint);
+
+ FileDescriptor[] fds = {fdtosend};
+ mSocket.setFileDescriptorsForSend(fds);
+
+ Log.d("Openvpn", "Sending FD tosocket: " + fdtosend + " " + fdint);
+ // Trigger a send so we can close the fd on our side of the channel
+ String cmd = String.format("needok '%s' %s\n", needed, "ok");
+ managmentCommand(cmd);
+ pfd.close();
+ return true;
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+
private void processPWCommand(String argument) {
//argument has the form Need 'Private Key' password
int p1 =argument.indexOf('\'');
@@ -192,7 +248,7 @@ public class OpenVpnManagementThread implements Runnable {
String needed = argument.substring(p1+1, p2);
String pw=null;
-
+
if(needed.equals("Private Key")) {
pw = mProfile.getPasswordPrivateKey();
diff --git a/src/de/blinkt/openvpn/OpenVpnService.java b/src/de/blinkt/openvpn/OpenVpnService.java
index 5937f48e..5c9df8b4 100644
--- a/src/de/blinkt/openvpn/OpenVpnService.java
+++ b/src/de/blinkt/openvpn/OpenVpnService.java
@@ -65,7 +65,7 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
// Add 33. bit to ensure the loop terminates
netmask += 1l << 32;
-
+
int lenZeros = 0;
while((netmask & 0x1) == 0) {
lenZeros++;
@@ -78,13 +78,13 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
} else {
len =32 -lenZeros;
}
-
+
}
@Override
public String toString() {
return String.format("%s/%d",mIp,len);
}
-
+
public boolean normalise(){
long ip=0;
@@ -94,7 +94,7 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
ip += Integer.parseInt(ipt[1])<< 16;
ip += Integer.parseInt(ipt[2])<< 8;
ip += Integer.parseInt(ipt[3]);
-
+
long newip = ip & (0xffffffffl << (32 -len));
if (newip != ip){
mIp = String.format("%d.%d.%d.%d", (newip & 0xff000000) >> 24,(newip & 0xff0000) >> 16, (newip & 0xff00) >> 8 ,newip & 0xff);
@@ -213,7 +213,7 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
- public int openTun() {
+ public ParcelFileDescriptor openTun() {
Builder builder = new Builder();
builder.addAddress(mLocalIP.mIp, mLocalIP.len);
@@ -221,7 +221,7 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
for (String dns : mDnslist ) {
builder.addDnsServer(dns);
}
-
+
builder.setMtu(mMtu);
@@ -237,46 +237,47 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
builder.addSearchDomain(mDomain);
String bconfig[] = new String[5];
-
+
bconfig[0]= getString(R.string.last_openvpn_tun_config);
bconfig[1] = String.format(getString(R.string.local_ip_info,mLocalIP.mIp,mLocalIP.len,mMtu));
bconfig[2] = String.format(getString(R.string.dns_server_info, joinString(mDnslist)));
bconfig[3] = String.format(getString(R.string.dns_domain_info, mDomain));
bconfig[4] = String.format(getString(R.string.routes_info, joinString(mRoutes)));
-
-
+
+
OpenVPN.logBuilderConfig(bconfig);
-
+
mDnslist.clear();
mRoutes.clear();
builder.setSession(mProfile.mName + " - " + mLocalIP);
-
+
// Let the configure Button show the Log
Intent intent = new Intent(getBaseContext(),LogWindow.class);
PendingIntent startLW = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);
builder.setConfigureIntent(startLW);
try {
ParcelFileDescriptor pfd = builder.establish();
- return pfd.detachFd();
+ return pfd;
} catch (Exception e) {
OpenVPN.logMessage(0, "", getString(R.string.tun_open_error));
OpenVPN.logMessage(0, "", getString(R.string.error) + e.getLocalizedMessage());
OpenVPN.logMessage(0, "", getString(R.string.tun_error_helpful));
- return -1;
+ return null;
}
}
-
+
// Ugly, but java has no such method
private <T> String joinString(Vector<T> vec) {
String ret = "";
- if(vec.size() > 0);
- ret = vec.get(0).toString();
- for(int i=1;i < vec.size();i++) {
- ret = ret + ", " + vec.get(i).toString();
+ if(vec.size() > 0){
+ ret = vec.get(0).toString();
+ for(int i=1;i < vec.size();i++) {
+ ret = ret + ", " + vec.get(i).toString();
+ }
}
return ret;
}
@@ -303,10 +304,10 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
if(route.len == 32 && !mask.equals("255.255.255.255")) {
OpenVPN.logMessage(0, "", String.format(getString(R.string.route_not_cidr,dest,mask)));
}
-
+
if(route.normalise())
OpenVPN.logMessage(0, "", String.format(getString(R.string.route_not_netip,dest,route.len,route.mIp)));
-
+
mRoutes.add(route);
}
@@ -314,7 +315,7 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
public void setLocalIP(String local, String netmask,int mtu) {
mLocalIP = new CIDRIP(local, netmask);
mMtu = mtu;
-
+
if(mLocalIP.len == 32 && !netmask.equals("255.255.255.255")) {
OpenVPN.logMessage(0, "", String.format(getString(R.string.ip_not_cidr, local,netmask)));
}
diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java
index 75f0235d..3cbac8d7 100644
--- a/src/de/blinkt/openvpn/VpnProfile.java
+++ b/src/de/blinkt/openvpn/VpnProfile.java
@@ -92,62 +92,6 @@ public class VpnProfile implements Serializable{
public String mVerb="1";
-
- public int describeContents() {
- return 0;
- }
-
- // Not used
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(mAuthenticationType);
- out.writeLong(mUuid.getMostSignificantBits());
- out.writeLong(mUuid.getLeastSignificantBits());
- out.writeString(mName);
- out.writeString(mAlias);
- out.writeString(mClientCertFilename);
- out.writeString(mTLSAuthDirection);
- out.writeString(mTLSAuthFilename);
- out.writeString(mClientKeyFilename);
- out.writeString(mCaFilename);
- out.writeValue(mUseLzo);
- out.writeString(mServerPort);
- out.writeValue(mUseUdp);
- out.writeString(mPKCS12Filename);
- out.writeString(mPKCS12Password);
- out.writeValue(mUseTLSAuth);
- out.writeString(mServerName);
- }
-
- private VpnProfile(Parcel in) {
- mAuthenticationType = in.readInt();
- mUuid = new UUID(in.readLong(), in.readLong());
- mName = in.readString();
- mAlias = in.readString();
- mClientCertFilename = in.readString();
- mTLSAuthDirection = in.readString();
- mTLSAuthFilename = in.readString();
- mClientKeyFilename = in.readString();
- mCaFilename = in.readString();
- mUseLzo = (Boolean) in.readValue(null);
- mServerPort = in.readString();
- mUseUdp = (Boolean) in.readValue(null);
- mPKCS12Filename = in.readString();
- mPKCS12Password = in.readString();
- mUseTLSAuth = (Boolean) in.readValue(null);
- mServerName = in.readString();
- }
-
- public static final Parcelable.Creator<VpnProfile> CREATOR
- = new Parcelable.Creator<VpnProfile>() {
- public VpnProfile createFromParcel(Parcel in) {
- return new VpnProfile(in);
- }
-
- public VpnProfile[] newArray(int size) {
- return new VpnProfile[size];
- }
- };
-
public static String openVpnEscape(String unescape) {
String escapedString = unescape.replace("\\", "\\\\");
escapedString = escapedString.replace("\"","\\\"");
@@ -180,19 +124,22 @@ public class VpnProfile implements Serializable{
String cfg="";
- // Enable managment interface
+ // Enable managment interface
+ cfg += "# Enables connection to GUI\n";
cfg += "management ";
cfg +=cacheDir.getAbsolutePath() + "/" + "mgmtsocket";
cfg += " unix\n";
cfg += "management-hold\n\n";
- /* only needed if client is compiled with P2MP Server support as early version
- * accidently were */
cfg+="# /tmp does not exist on Android\n";
cfg+="tmp-dir ";
cfg+=cacheDir.getAbsolutePath();
cfg+="\n\n";
+
+ cfg+="# Silences script security warning\n";
+ cfg+="script-security 0\n\n";
+
boolean useTLSClient = (mAuthenticationType != TYPE_STATICKEYS);