summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2012-05-10 10:53:21 +0200
committerArne Schwabe <arne@rfc2549.org>2012-05-10 10:53:21 +0200
commit6008ca11d6c8cbad981f114ec231295800a4489f (patch)
treed6f1f285dc422b51dc3374138ec0fff36fd30193 /src
parent82b3869f5d2e7cc3b67e272ebf3565df58c922cf (diff)
parentc7c118c07a00c6a8c1f44e1736dfe75d55b92884 (diff)
Version 0.5.2
Fix minivpn vs openvpn. (closes issue #16) If minivpn binary is already available don't write it (closes issue #15)
Diffstat (limited to 'src')
-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
5 files changed, 310 insertions, 12 deletions
diff --git a/src/de/blinkt/openvpn/ConfigParser.java b/src/de/blinkt/openvpn/ConfigParser.java
new file mode 100644
index 00000000..8497330f
--- /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 858c8d38..8aeb9960 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 a3df9fde..9f0f7326 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 57d99417..4124783b 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 26cf50bd..63d6876e 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");