summaryrefslogtreecommitdiff
path: root/src/de/blinkt/openvpn
diff options
context:
space:
mode:
Diffstat (limited to 'src/de/blinkt/openvpn')
-rw-r--r--src/de/blinkt/openvpn/OpenVPN.java16
-rw-r--r--src/de/blinkt/openvpn/OpenVpnService.java69
-rw-r--r--src/de/blinkt/openvpn/Settings_Authentication.java6
-rw-r--r--src/de/blinkt/openvpn/Settings_IP.java11
-rw-r--r--src/de/blinkt/openvpn/ShowConfigFragment.java12
-rw-r--r--src/de/blinkt/openvpn/VPNPreferences.java4
-rw-r--r--src/de/blinkt/openvpn/VPNProfileList.java2
-rw-r--r--src/de/blinkt/openvpn/VpnProfile.java113
8 files changed, 182 insertions, 51 deletions
diff --git a/src/de/blinkt/openvpn/OpenVPN.java b/src/de/blinkt/openvpn/OpenVPN.java
index bca276c9..c3d92a4c 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 String localip;
private static final int MAXLOGENTRIES = 500;
public static native int startOpenVPNThread();
public static native int startOpenVPNThreadArgs(String argv[]);
@@ -32,14 +31,15 @@ public class OpenVPN {
}
static void addRoute(String dest,String mask, String gw) {
- Log.i("openvpn" ,"Got Routing information " + dest + " " + mask + " " + 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.addFirst(prefix + " " + message);
+ logbuffer.addLast(prefix + " " + message);
if(logbuffer.size()>MAXLOGENTRIES)
- logbuffer.removeLast();
+ logbuffer.removeFirst();
// The garbage collector does not collect the String from native
// but kills me for logging 100 messages with too many references :(
@@ -62,10 +62,10 @@ public class OpenVPN {
}
- static void addInterfaceInfo(int mtu, String local, String remote)
+ static void addInterfaceInfo(int mtu, String local, String netmask)
{
- Log.i("openvpn","Got interface info M" + mtu + " L: " + local + "R: " + remote);
- localip=local;
+ Log.i("openvpn","Got interface info M" + mtu + " L: " + local + "NM: " + netmask);
+ mOpenVpnService.setLocalIP(local,netmask);
}
static void addDns(String dns) {
@@ -96,7 +96,7 @@ public class OpenVPN {
public static int openTunDevice() {
Log.d(TAG,"Opening tun device");
- ParcelFileDescriptor pfd = mOpenVpnService.openTun(localip);
+ ParcelFileDescriptor pfd = mOpenVpnService.openTun();
return pfd.detachFd();
}
//! Dummy method being called to force loading of JNI Libraries
diff --git a/src/de/blinkt/openvpn/OpenVpnService.java b/src/de/blinkt/openvpn/OpenVpnService.java
index 1cc5b2ec..39d73adb 100644
--- a/src/de/blinkt/openvpn/OpenVpnService.java
+++ b/src/de/blinkt/openvpn/OpenVpnService.java
@@ -21,6 +21,8 @@ import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Vector;
+import de.blinkt.openvpn.OpenVpnService.CIDRIP;
+
import android.app.PendingIntent;
import android.content.Intent;
import android.net.LocalSocket;
@@ -38,7 +40,8 @@ public class OpenVpnService extends VpnService implements Handler.Callback, Runn
private String[] mArgv;
private Handler mHandler;
- private Thread mThread;
+ // Only one VPN, make this thread shared between all instances
+ private static Thread mThread;
private ParcelFileDescriptor mInterface;
@@ -48,6 +51,36 @@ public class OpenVpnService extends VpnService implements Handler.Callback, Runn
private String mDomain=null;
+ private Vector<CIDRIP> mRoutes=new Vector<CIDRIP>();
+
+ private CIDRIP mLocalIP;
+
+
+ class CIDRIP{
+ String mIp;
+ int len;
+ public CIDRIP(String ip, String mask){
+ mIp=ip;
+ String[] ipt = mask.split("\\.");
+ long netmask=0;
+
+ netmask += Integer.parseInt(ipt[0]);
+ netmask += Integer.parseInt(ipt[1])<< 8;
+ netmask += Integer.parseInt(ipt[2])<< 16;
+ netmask += Integer.parseInt(ipt[3])<< 24;
+
+ len =0;
+ while((netmask & 0x1) == 1) {
+ len++;
+ netmask = netmask >> 1;
+ }
+ }
+ @Override
+ public String toString() {
+ return String.format("%s/%d",mIp,len);
+ }
+ }
+
@Override
public void onRevoke() {
managmentCommand("signal SIGINT\n");
@@ -216,19 +249,31 @@ public class OpenVpnService extends VpnService implements Handler.Callback, Runn
}
- public ParcelFileDescriptor openTun(String localip) {
- // FIXME: hardcoded assumptions
+ public ParcelFileDescriptor openTun() {
Builder builder = new Builder();
- builder.addRoute("0.0.0.0", 0);
- builder.addAddress(localip, 24 );
+
+ builder.addAddress(mLocalIP.mIp, mLocalIP.len);
+
for (String dns : mDnslist ) {
builder.addDnsServer(dns);
}
-
+
+
+ for (CIDRIP route:mRoutes) {
+ builder.addRoute(route.mIp, route.len);
+ }
+
if(mDomain!=null)
builder.addSearchDomain(mDomain);
- builder.setSession(mProfile.mName + " - " + localip);
+
+ 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);
@@ -248,4 +293,14 @@ public class OpenVpnService extends VpnService implements Handler.Callback, Runn
mDomain=domain;
}
}
+
+
+ public void addRoute(String dest, String mask) {
+ mRoutes.add(new CIDRIP(dest, mask));
+ }
+
+
+ public void setLocalIP(String local, String netmask) {
+ mLocalIP = new CIDRIP(local, netmask);
+ }
}
diff --git a/src/de/blinkt/openvpn/Settings_Authentication.java b/src/de/blinkt/openvpn/Settings_Authentication.java
index f3ebb36d..4c70344d 100644
--- a/src/de/blinkt/openvpn/Settings_Authentication.java
+++ b/src/de/blinkt/openvpn/Settings_Authentication.java
@@ -58,7 +58,7 @@ public class Settings_Authentication extends PreferenceFragment implements OnPre
mUseTLSAuth.setChecked(mProfile.mUseTLSAuth);
mTLSAuthFile.setSummary(mProfile.mTLSAuthFilename);
- //mTLSAuthDirection.setValue(mProfile.mTLSAuthDirection);
+ mTLSAuthDirection.setValue(mProfile.mTLSAuthDirection);
}
private void saveSettings() {
@@ -72,10 +72,10 @@ public class Settings_Authentication extends PreferenceFragment implements OnPre
else
mProfile.mTLSAuthFilename = mTLSAuthFile.getSummary().toString();
- if(mTLSAuthDirection.getEntry()==null)
+ if(mTLSAuthDirection.getValue()==null)
mProfile.mTLSAuthDirection=null;
else
- mProfile.mTLSAuthDirection = mTLSAuthDirection.getEntry().toString();
+ mProfile.mTLSAuthDirection = mTLSAuthDirection.getValue().toString();
}
@Override
diff --git a/src/de/blinkt/openvpn/Settings_IP.java b/src/de/blinkt/openvpn/Settings_IP.java
index c2b1ed71..de625d22 100644
--- a/src/de/blinkt/openvpn/Settings_IP.java
+++ b/src/de/blinkt/openvpn/Settings_IP.java
@@ -19,6 +19,7 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang
private EditTextPreference mCustomRoutes;
private CheckBoxPreference mUseDefaultRoute;
private VpnProfile mProfile;
+ private CheckBoxPreference mRouteNoPull;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -45,6 +46,7 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang
mDNS2 = (EditTextPreference) findPreference("dns2");
mCustomRoutes = (EditTextPreference) findPreference("customRoutes");
mUseDefaultRoute = (CheckBoxPreference) findPreference("useDefaultRoute");
+ mRouteNoPull = (CheckBoxPreference) findPreference("routenopull");
mIPv4.setOnPreferenceChangeListener(this);
mIPv6.setOnPreferenceChangeListener(this);
@@ -72,6 +74,7 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang
mSearchdomain.setText(mProfile.mSearchDomain);
mUseDefaultRoute.setChecked(mProfile.mUseDefaultRoute);
mCustomRoutes.setText(mProfile.mCustomRoutes);
+ mRouteNoPull.setChecked(mProfile.mRoutenopull);
// Sets Summary
onPreferenceChange(mIPv4, mIPv4.getText());
@@ -105,7 +108,7 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang
mProfile.mSearchDomain = mSearchdomain.getText();
mProfile.mUseDefaultRoute = mUseDefaultRoute.isChecked();
mProfile.mCustomRoutes = mCustomRoutes.getText();
-
+ mProfile.mRoutenopull = mRouteNoPull.isChecked();
}
@@ -120,10 +123,10 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang
preference.setSummary((String)newValue);
if(preference== mUsePull || preference == mOverrideDNS)
- if(preference==mOverrideDNS)
+ if(preference==mOverrideDNS) {
// Set so the function gets the right value
mOverrideDNS.setChecked((Boolean) newValue);
-
+ }
setDNSState();
saveSettings();
@@ -133,6 +136,7 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang
private void setDNSState() {
boolean enabled;
mOverrideDNS.setEnabled(mUsePull.isChecked());
+ mRouteNoPull.setEnabled(mUsePull.isChecked());
if(!mUsePull.isChecked())
enabled =true;
else if (mOverrideDNS.isChecked())
@@ -143,6 +147,7 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang
mDNS1.setEnabled(enabled);
mDNS2.setEnabled(enabled);
mSearchdomain.setEnabled(enabled);
+
}
diff --git a/src/de/blinkt/openvpn/ShowConfigFragment.java b/src/de/blinkt/openvpn/ShowConfigFragment.java
index a69d835a..68898e07 100644
--- a/src/de/blinkt/openvpn/ShowConfigFragment.java
+++ b/src/de/blinkt/openvpn/ShowConfigFragment.java
@@ -13,10 +13,18 @@ public class ShowConfigFragment extends Fragment {
{
String profileUUID = getArguments().getString(getActivity().getPackageName() + ".profileUUID");
VpnProfile vp = ProfileManager.get(profileUUID);
- String cfg=vp.getConfigFile(getActivity().getCacheDir());
View v=inflater.inflate(R.layout.viewconfig, container,false);
TextView cv = (TextView) v.findViewById(R.id.configview);
- cv.setText(cfg);
+
+ int check=vp.checkProfile();
+ if(check!=R.string.no_error_found) {
+ cv.setText(check);
+ }
+ else {
+ String cfg=vp.getConfigFile(getActivity().getCacheDir());
+
+ cv.setText(cfg);
+ }
return v;
};
}
diff --git a/src/de/blinkt/openvpn/VPNPreferences.java b/src/de/blinkt/openvpn/VPNPreferences.java
index 4b1c7377..771cd902 100644
--- a/src/de/blinkt/openvpn/VPNPreferences.java
+++ b/src/de/blinkt/openvpn/VPNPreferences.java
@@ -44,11 +44,11 @@ public class VPNPreferences extends PreferenceActivity {
- if (hasHeaders()) {
+ /* if (hasHeaders()) {
Button button = new Button(this);
button.setText("Save");
setListFooter(button);
- }
+ } */
}
diff --git a/src/de/blinkt/openvpn/VPNProfileList.java b/src/de/blinkt/openvpn/VPNProfileList.java
index f77c8639..8f4304dc 100644
--- a/src/de/blinkt/openvpn/VPNProfileList.java
+++ b/src/de/blinkt/openvpn/VPNProfileList.java
@@ -184,7 +184,7 @@ public class VPNProfileList extends PreferenceFragment implements VpnPreference
startActivity(startLW);
- OpenVPN.logMessage(0, "", "Building confugration...");
+ OpenVPN.logMessage(0, "", "Building configration...");
Intent startVPN = mSelectedVPN.prepareIntent(getActivity());
diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java
index e17fb8ff..2df4ec39 100644
--- a/src/de/blinkt/openvpn/VpnProfile.java
+++ b/src/de/blinkt/openvpn/VpnProfile.java
@@ -12,6 +12,7 @@ import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
+import java.util.Collection;
import java.util.Random;
import java.util.UUID;
import java.util.Vector;
@@ -35,7 +36,7 @@ public class VpnProfile implements Serializable{
static final int TYPE_KEYSTORE=2;
public static final int TYPE_USERPASS = 3;
public static final int TYPE_STATICKEYS = 4;
-
+
private static final String OVPNCONFIGFILE = "android.conf";
// Keep in order of parceling
@@ -71,6 +72,7 @@ public class VpnProfile implements Serializable{
public String mRemoteCN="";
private String mPassword;
private String mUsername;
+ public boolean mRoutenopull=false;
public int describeContents() {
@@ -145,27 +147,27 @@ public class VpnProfile implements Serializable{
return mName;
}
-
+
public String getConfigFile(File cacheDir)
{
String cfg="";
-
-
+
+
// TODO "--remote-cert-eku", "TLS Web Server Authentication"
-
+
boolean useTLSClient = (mAuthenticationType != TYPE_STATICKEYS);
-
+
if(useTLSClient && mUsePull)
cfg+="client\n";
else if (mUsePull)
cfg+="pull\n";
else if(useTLSClient)
- cfg+="tls-client";
-
-
+ cfg+="tls-client\n";
+
+
cfg+="verb 2\n";
@@ -240,19 +242,30 @@ public class VpnProfile implements Serializable{
// Basic Settings
if(!mUsePull ) {
- cfg +="ifconfig " + mIPv4Address + " 255.255.255.255\n";
+ cfg +="ifconfig " + cidrToIPAndNetmask(mIPv4Address) + "\n";
}
-
+
+ if(mUsePull && mRoutenopull)
+ cfg += "route-nopull\n";
+
+ if(mUseDefaultRoute)
+ cfg += "route 0.0.0.0 0.0.0.0\n";
+ else
+ for(String route:getCustomRoutes()) {
+ cfg += "route " + route + "\n";
+ }
+
+
if(mOverrideDNS || !mUsePull) {
if(!mDNS1.equals("") && mDNS1!=null)
cfg+="dhcp-option DNS " + mDNS1 + "\n";
if(!mDNS2.equals("") && mDNS2!=null)
cfg+="dhcp-option DNS " + mDNS2 + "\n";
-
+
}
-
-
+
+
// Authentication
if(mCheckRemoteCN) {
if(mRemoteCN == null || mRemoteCN.equals("") )
@@ -262,9 +275,52 @@ public class VpnProfile implements Serializable{
}
if(mExpectTLSCert)
cfg += "remote-cert-tls server\n";
-
+
return cfg;
}
+
+ private Collection<String> getCustomRoutes() {
+ Vector<String> cidrRoutes=new Vector<String>();
+ for(String route:mCustomRoutes.split("[\n \t]")) {
+ if(!route.equals("")) {
+ String cidrroute = cidrToIPAndNetmask(route);
+ if(cidrRoutes == null)
+ return null;
+
+ cidrRoutes.add(cidrroute);
+ }
+ }
+
+ return cidrRoutes;
+ }
+
+ private String cidrToIPAndNetmask(String route) {
+ String[] parts = route.split("/");
+
+ // No /xx, return verbatim
+ if (parts.length ==1)
+ return route;
+
+ if (parts.length!=2)
+ return null;
+ int len;
+ try {
+ len = Integer.parseInt(parts[1]);
+ } catch(NumberFormatException ne) {
+ return null;
+ }
+ if (len <0 || len >32)
+ return null;
+
+
+ long nm = 0xffffffffl;
+ nm = (nm << len) & 0xffffffffl;
+
+ String netmask =String.format("%d.%d.%d.%d", (nm & 0xff000000) >> 24,(nm & 0xff0000) >> 16, (nm & 0xff00) >> 8 ,nm & 0xff );
+ return parts[0] + " " + netmask;
+ }
+
+
private String[] buildOpenvpnArgv(File cacheDir)
{
@@ -290,8 +346,8 @@ public class VpnProfile implements Serializable{
public Intent prepareIntent(Activity activity) {
String prefix = activity.getPackageName();
-
- Intent intent = new Intent(activity,OpenVpnService.class);
+
+ Intent intent = new Intent(activity,OpenVpnService.class);
intent.putExtra(prefix + ".ARGV" , buildOpenvpnArgv(activity.getCacheDir()));
@@ -304,14 +360,14 @@ public class VpnProfile implements Serializable{
String pkcs12pw = savePKCS12(activity);
intent.putExtra(prefix + ".PKCS12PASS", pkcs12pw);
}
-
+
if(mAuthenticationType == VpnProfile.TYPE_USERPASS) {
intent.putExtra(prefix + ".USERNAME", mUsername);
intent.putExtra(prefix + ".PASSWORD", mPassword);
}
-
+
intent.putExtra(prefix + ".profileUUID", mUuid.toString());
-
+
try {
FileWriter cfg = new FileWriter(activity.getCacheDir().getAbsolutePath() + "/" + OVPNCONFIGFILE);
cfg.write(getConfigFile(activity.getCacheDir()));
@@ -320,10 +376,10 @@ public class VpnProfile implements Serializable{
} catch (IOException e) {
e.printStackTrace();
}
-
+
return intent;
}
-
+
private String getRandomPW() {
String pw= "";
// Put enough digits togher to make a password :)
@@ -373,11 +429,18 @@ public class VpnProfile implements Serializable{
int checkProfile() {
if(mAuthenticationType==TYPE_KEYSTORE && mAlias==null)
return R.string.no_keystore_cert_selected;
-
-
+
+ if(!mUsePull) {
+ if(mIPv4Address == null || cidrToIPAndNetmask(mIPv4Address) == null)
+ return R.string.ipv4_format_error;
+
+ }
+ if(!mUseDefaultRoute && getCustomRoutes()==null)
+ return R.string.custom_route_format_error;
+
// Everything okay
return R.string.no_error_found;
-
+
}