summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2012-05-13 01:16:27 +0200
committerArne Schwabe <arne@rfc2549.org>2012-05-13 01:16:27 +0200
commit9e2afc72b16125f7c365b8d600f6f5df36aa8f48 (patch)
treef2733212c02f8816a6188c70fd0e358876b90d0e
parent5a65e0c5e80d147909acffa14b04d3c99d48de1a (diff)
Config Import useable (closes issue #14)
Correct save/restore state in Basic Settings (closes issue #17)
-rw-r--r--res/drawable-hdpi/ic_menu_archive.pngbin0 -> 1094 bytes
-rw-r--r--res/drawable-mdpi/ic_menu_archive.pngbin0 -> 831 bytes
-rw-r--r--res/drawable-xhdpi/ic_menu_archive.pngbin0 -> 1398 bytes
-rw-r--r--res/values/strings.xml6
-rw-r--r--res/xml/vpn_ipsettings.xml9
-rw-r--r--src/de/blinkt/openvpn/CIDRIP.java56
-rw-r--r--src/de/blinkt/openvpn/ConfigConverter.java41
-rw-r--r--src/de/blinkt/openvpn/ConfigParser.java152
-rw-r--r--src/de/blinkt/openvpn/FileSelect.java11
-rw-r--r--src/de/blinkt/openvpn/FileSelectLayout.java14
-rw-r--r--src/de/blinkt/openvpn/OpenVpnService.java56
-rw-r--r--src/de/blinkt/openvpn/Settings_Basic.java2
-rw-r--r--src/de/blinkt/openvpn/Settings_IP.java8
-rw-r--r--src/de/blinkt/openvpn/VPNProfileList.java22
-rw-r--r--src/de/blinkt/openvpn/VpnProfile.java24
-rw-r--r--todo.txt10
16 files changed, 256 insertions, 155 deletions
diff --git a/res/drawable-hdpi/ic_menu_archive.png b/res/drawable-hdpi/ic_menu_archive.png
new file mode 100644
index 00000000..e2d9bc1a
--- /dev/null
+++ b/res/drawable-hdpi/ic_menu_archive.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_archive.png b/res/drawable-mdpi/ic_menu_archive.png
new file mode 100644
index 00000000..49ac569d
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_archive.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_menu_archive.png b/res/drawable-xhdpi/ic_menu_archive.png
new file mode 100644
index 00000000..b1be9d5b
--- /dev/null
+++ b/res/drawable-xhdpi/ic_menu_archive.png
Binary files differ
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a5a88219..e2121d4b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -206,5 +206,9 @@
<string name="importing_config">Importing config file from source %1$s</string>
<string name="import_pkcs12_to_keystore">Your config file specified a pkcs12 file. Please import the file by selecting select in the Basic Settings configuration of the converted VPN</string>
<string name="import_warning_custom_options">Your configuration had a few configuration options that could be parsed. These options were added as custom configuration options. The custom configuration is displayed below:</string>
- <string name="import_done">Done reading config file.</string>
+ <string name="import_done">Done reading config file.</string>
+ <string name="nobind_summary">Do not bind to local address and port</string>
+ <string name="no_bind">No local binding</string>
+ <string name="import_experimental">Please not that the config importer is an experimental feature.</string>
+ <string name="import_configuration_file">Import configuration file</string>
</resources>
diff --git a/res/xml/vpn_ipsettings.xml b/res/xml/vpn_ipsettings.xml
index 00774b65..fe55e8b4 100644
--- a/res/xml/vpn_ipsettings.xml
+++ b/res/xml/vpn_ipsettings.xml
@@ -18,7 +18,14 @@
android:dependency="usePull"
android:dialogMessage="@string/ipv6_dialog_tile"
android:key="ipv6_address"
- android:title="@string/ipv6_address" />
+ android:title="@string/ipv6_address"
+ android:enabled="false"/>
+ <CheckBoxPreference
+ android:title="@string/no_bind"
+ android:summary="@string/nobind_summary"
+ android:persistent="false"
+ android:key="nobind" />
+
</PreferenceCategory>
<PreferenceCategory android:title="@string/dns" >
<CheckBoxPreference
diff --git a/src/de/blinkt/openvpn/CIDRIP.java b/src/de/blinkt/openvpn/CIDRIP.java
new file mode 100644
index 00000000..c2f0d821
--- /dev/null
+++ b/src/de/blinkt/openvpn/CIDRIP.java
@@ -0,0 +1,56 @@
+package de.blinkt.openvpn;
+
+class CIDRIP{
+ String mIp;
+ int len;
+ public CIDRIP(String ip, String mask){
+ mIp=ip;
+ String[] ipt = mask.split("\\.");
+ long netmask=0;
+
+ netmask += Long.parseLong(ipt[0])<< 24;
+ netmask += Integer.parseInt(ipt[1])<< 16;
+ netmask += Integer.parseInt(ipt[2])<< 8;
+ netmask += Integer.parseInt(ipt[3]);
+
+ // Add 33. bit to ensure the loop terminates
+ netmask += 1l << 32;
+
+ int lenZeros = 0;
+ while((netmask & 0x1) == 0) {
+ lenZeros++;
+ netmask = netmask >> 1;
+ }
+ // Check if rest of netmask is only 1s
+ if(netmask != (0x1ffffffffl >> lenZeros)) {
+ // Asume no CIDR, set /32
+ len=32;
+ } else {
+ len =32 -lenZeros;
+ }
+
+ }
+ @Override
+ public String toString() {
+ return String.format("%s/%d",mIp,len);
+ }
+
+ public boolean normalise(){
+ long ip=0;
+
+ String[] ipt = mIp.split("\\.");
+
+ ip += Long.parseLong(ipt[0])<< 24;
+ 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);
+ return true;
+ } else {
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/blinkt/openvpn/ConfigConverter.java b/src/de/blinkt/openvpn/ConfigConverter.java
index 1973e0ac..686a4e42 100644
--- a/src/de/blinkt/openvpn/ConfigConverter.java
+++ b/src/de/blinkt/openvpn/ConfigConverter.java
@@ -24,7 +24,7 @@ public class ConfigConverter extends ListActivity {
private VpnProfile mResult;
private ArrayAdapter<String> mArrayAdapter;
-
+
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -32,7 +32,7 @@ public class ConfigConverter extends ListActivity {
Toast.makeText(this, "Got called!", Toast.LENGTH_LONG).show();
}
-
+
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId()==R.id.cancel){
@@ -41,6 +41,7 @@ public class ConfigConverter extends ListActivity {
} else if(item.getItemId()==R.id.ok) {
if(mResult==null) {
log("Importing the config had error, cannot save it");
+ return true;
}
Intent result = new Intent();
ProfileManager vpl = ProfileManager.getInstance(this);
@@ -48,6 +49,7 @@ public class ConfigConverter extends ListActivity {
result.putExtra(VpnProfile.EXTRA_PROFILEUUID,mResult.getUUID().toString());
setResult(Activity.RESULT_OK, result);
finish();
+ return true;
}
return super.onOptionsItemSelected(item);
@@ -61,7 +63,7 @@ public class ConfigConverter extends ListActivity {
return true;
}
-
+
private String embedFile(String filename)
{
if(filename == null || filename.equals(""))
@@ -69,7 +71,7 @@ public class ConfigConverter extends ListActivity {
// Already embedded, nothing to do
if(filename.startsWith(VpnProfile.INLINE_TAG))
return filename;
-
+
// Try diffent path relative to /mnt/sdcard
File sdcard = Environment.getExternalStorageDirectory();
File root = new File("/");
@@ -82,15 +84,15 @@ public class ConfigConverter extends ListActivity {
suffix = fileparts[i];
else
suffix = fileparts[i] + "/" + suffix;
-
+
File possibleFile = new File(rootdir,suffix);
if(!possibleFile.canRead())
continue;
-
+
// read the file inline
String filedata = VpnProfile.INLINE_TAG;
byte[] buf =new byte[2048];
-
+
log(R.string.trying_to_read, possibleFile.getAbsolutePath());
try {
FileInputStream fis = new FileInputStream(possibleFile);
@@ -105,25 +107,25 @@ public class ConfigConverter extends ListActivity {
} catch (IOException e) {
log(e.getLocalizedMessage());
}
-
-
+
+
}
}
log(R.string.import_could_not_open,filename);
return null;
}
-
+
void embedFiles() {
// This where I would like to have a c++ style
// void embedFile(std::string & option)
-
+
mResult.mCaFilename = embedFile(mResult.mCaFilename);
mResult.mClientCertFilename = embedFile(mResult.mClientCertFilename);
mResult.mClientKeyFilename = embedFile(mResult.mClientKeyFilename);
mResult.mTLSAuthFilename = embedFile(mResult.mTLSAuthFilename);
}
-
-
+
+
@Override
protected void onStart() {
super.onStart();
@@ -137,6 +139,7 @@ public class ConfigConverter extends ListActivity {
final android.net.Uri data = intent.getData ();
if (data != null)
{
+ log(R.string.import_experimental);
log(R.string.importing_config,data.toString());
try {
InputStream is = getContentResolver().openInputStream(data);
@@ -146,14 +149,14 @@ public class ConfigConverter extends ListActivity {
}
}
}
-
+
return;
}
private void log(String logmessage) {
mArrayAdapter.add(logmessage);
}
-
+
private void doImport(InputStream is) {
ConfigParser cp = new ConfigParser();
try {
@@ -164,7 +167,7 @@ public class ConfigConverter extends ListActivity {
displayWarnings();
log(R.string.import_done);
return;
-
+
} catch (IOException e) {
log(R.string.error_reading_config_file);
log(e.getLocalizedMessage());
@@ -173,7 +176,7 @@ public class ConfigConverter extends ListActivity {
log(e.getLocalizedMessage());
}
mResult=null;
-
+
}
private void displayWarnings() {
@@ -181,11 +184,11 @@ public class ConfigConverter extends ListActivity {
log(R.string.import_warning_custom_options);
log(mResult.mCustomConfigOptions);
}
-
+
if(mResult.mAuthenticationType==VpnProfile.TYPE_KEYSTORE) {
log(R.string.import_pkcs12_to_keystore);
}
-
+
}
diff --git a/src/de/blinkt/openvpn/ConfigParser.java b/src/de/blinkt/openvpn/ConfigParser.java
index 8fde12b8..a64fb403 100644
--- a/src/de/blinkt/openvpn/ConfigParser.java
+++ b/src/de/blinkt/openvpn/ConfigParser.java
@@ -5,7 +5,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
-import java.util.Map.Entry;
import java.util.Vector;
//! Openvpn Config FIle Parser, probably not 100% accurate but close enough
@@ -17,7 +16,7 @@ import java.util.Vector;
public class ConfigParser {
- private HashMap<String,Vector<String>> options = new HashMap<String, Vector<String>>();
+ private HashMap<String, Vector<Vector<String>>> options = new HashMap<String, Vector<Vector<String>>>();
public void parseConfig(InputStream inputStream) throws IOException, ConfigParseError {
@@ -37,13 +36,16 @@ public class ConfigParser {
continue;
-
if(args.get(0).startsWith("--"))
args.set(0, args.get(0).substring(2));
checkinlinefile(args,br);
- options.put(args.get(0), args);
+ String optionname = args.get(0);
+ if(!options.containsKey(optionname)) {
+ options.put(optionname, new Vector<Vector<String>>());
+ }
+ options.get(optionname).add(args);
}
}
@@ -213,12 +215,18 @@ public class ConfigParser {
"route-up",
"ipchange",
"route-up",
- "auth-user-pass-verify"
+ "auth-user-pass-verify",
+ "route-gateway",
+ "topology",
+ "persist-tun",
+ "route-metric"
+
};
- // Missing
- // proto tcp-client|udp
-
+
+
+ // This method is far too long
VpnProfile convertProfile() throws ConfigParseError{
+ boolean noauthtypeset=true;
VpnProfile np = new VpnProfile("converted Profile");
// Pull, client, tls-client
np.clearDefaults();
@@ -228,17 +236,34 @@ public class ConfigParser {
options.remove("pull");
options.remove("client");
}
-
+
Vector<String> secret = getOption("secret", 1, 2);
if(secret!=null)
{
np.mAuthenticationType=VpnProfile.TYPE_STATICKEYS;
+ noauthtypeset=false;
np.mUseTLSAuth=true;
np.mTLSAuthFilename=secret.get(1);
if(secret.size()==3)
np.mTLSAuthDirection=secret.get(2);
+
}
-
+
+ Vector<Vector<String>> routes = getAllOption("route", 1, 4);
+ if(routes!=null) {
+ String routeopt = "";
+ for(Vector<String> route:routes){
+ String netmask = "255.255.255.255";
+ if(route.size() >= 3)
+ netmask = route.get(2);
+ String net = route.get(1);
+
+ CIDRIP cidr = new CIDRIP(net, netmask);
+ routeopt+=cidr.toString() + " ";
+ }
+ np.mCustomRoutes=routeopt;
+ }
+
Vector<String> tlsauth = getOption("tls-auth", 1, 2);
if(tlsauth!=null)
{
@@ -252,12 +277,9 @@ public class ConfigParser {
if(direction!=null)
np.mTLSAuthDirection=direction.get(1);
- if(options.containsKey("redirect-gateway")) {
- options.remove("redirect-gateway");
- np.mUseDefaultRoute=true;
- } else {
+
+ if(getAllOption("redirect-gateway", 0, 5) != null)
np.mUseDefaultRoute=true;
- }
Vector<String> dev =getOption("dev",1,1);
Vector<String> devtype =getOption("dev-type",1,1);
@@ -296,24 +318,41 @@ public class ConfigParser {
np.mServerName = remote.get(1);
}
}
+
+ Vector<String> port = getOption("port", 1,1);
+ if(port!=null){
+ np.mServerPort = port.get(1);
+ }
- Vector<String> proto = getOption("proto, ", 1,1);
+ Vector<String> proto = getOption("proto", 1,1);
if(proto!=null){
if(proto.get(1).equals("udp"))
np.mUseUdp=true;
- else if (proto.get(1).equals("tcp-client"))
+ else if (proto.get(1).equals("tcp-client") ||
+ proto.get(1).equals("tcp"))
np.mUseUdp=false;
else
throw new ConfigParseError("Unsupported option to --proto " + proto.get(1));
-
+
}
-
- Vector<String> dhcpoption = getOption("dhcp-options", 1, 3);
- if(dhcpoption!=null) {
- String type=dhcpoption.get(1);
+ Vector<Vector<String>> dhcpoptions = getAllOption("dhcp-options", 2, 2);
+ if(dhcpoptions!=null) {
+ for(Vector<String> dhcpoption:dhcpoptions) {
+ String type=dhcpoption.get(1);
+ String arg = dhcpoption.get(2);
+ if(type.equals("DOMAIN")) {
+ np.mSearchDomain=dhcpoption.get(2);
+ } else if(type.equals("DNS")) {
+ np.mOverrideDNS=true;
+ if(np.mDNS1.equals(VpnProfile.DEFAULT_DNS1))
+ np.mDNS1=arg;
+ else
+ np.mDNS2=arg;
+ }
+ }
}
-
+
if(getOption("remote-random-hostname", 0, 0)!=null)
np.mUseRandomHostname=true;
@@ -336,6 +375,7 @@ public class ConfigParser {
if(cert!=null){
np.mClientCertFilename = cert.get(1);
np.mAuthenticationType = VpnProfile.TYPE_CERTIFICATES;
+ noauthtypeset=false;
}
Vector<String> key= getOption("key",1,1);
if(key!=null)
@@ -345,6 +385,7 @@ public class ConfigParser {
if(pkcs12!=null) {
np.mPKCS12Filename = pkcs12.get(1);
np.mAuthenticationType = VpnProfile.TYPE_KEYSTORE;
+ noauthtypeset=false;
}
Vector<String> tlsremote = getOption("tls-remote",1,1);
@@ -352,14 +393,36 @@ public class ConfigParser {
np.mRemoteCN = tlsremote.get(1);
np.mCheckRemoteCN=true;
}
-
+
Vector<String> verb = getOption("verb",1,1);
if(verb!=null){
np.mVerb=verb.get(1);
}
+
+ if(getOption("nobind", 0, 0) != null)
+ np.mNobind=true;
+
+ if(getOption("auth-user-pass",0,1) != null) {
+ if(noauthtypeset) {
+ np.mAuthenticationType=VpnProfile.TYPE_USERPASS;
+ } else if(np.mAuthenticationType==VpnProfile.TYPE_CERTIFICATES) {
+ np.mAuthenticationType=VpnProfile.TYPE_USERPASS_CERTIFICATES;
+ } else if(np.mAuthenticationType==VpnProfile.TYPE_KEYSTORE) {
+ np.mAuthenticationType=VpnProfile.TYPE_USERPASS_KEYSTORE;
+ }
+ }
+
+
// Check the other options
+ checkIgnoreAndInvalidOptions(np);
+ fixup(np);
+
+ return np;
+ }
+
+ private void checkIgnoreAndInvalidOptions(VpnProfile np) throws ConfigParseError {
for(String option:unsupportedOptions)
if(options.containsKey(option))
throw new ConfigParseError(String.format("Unsupported Option %s encountered in config file. Aborting",option));
@@ -369,24 +432,23 @@ public class ConfigParser {
options.remove(option);
if(options.size()> 0) {
- String custom = "# These Options were found in the config file but not parsed:\n";
- for(Entry<String, Vector<String>> option:options.entrySet()) {
- for (String arg : option.getValue()) {
- custom+= arg + " ";
+ String custom = "# These Options were found in the config file do not map to config settings:\n";
+
+ for(Vector<Vector<String>> option:options.values()) {
+ for(Vector<String> optionsline: option) {
+ for (String arg : optionsline)
+ custom+= arg + " ";
}
custom+="\n";
+
}
np.mCustomConfigOptions = custom;
np.mUseCustomConfig=true;
}
-
-
- fixup(np);
-
- return np;
}
+
private void fixup(VpnProfile np) {
if(np.mRemoteCN.equals(np.mServerName)) {
np.mRemoteCN="";
@@ -394,14 +456,26 @@ public class ConfigParser {
}
private Vector<String> getOption(String option, int minarg, int maxarg) throws ConfigParseError {
- Vector<String> args = options.get(option);
+ Vector<Vector<String>> alloptions = getAllOption(option, minarg, maxarg);
+ if(alloptions==null)
+ return null;
+ else
+ return alloptions.lastElement();
+ }
+
+
+ private Vector<Vector<String>> getAllOption(String option, int minarg, int maxarg) throws ConfigParseError {
+ Vector<Vector<String>> args = options.get(option);
if(args==null)
return null;
- if(args.size()< (minarg+1) || args.size() > maxarg+1) {
- String err = String.format("Option %s has %d parameters, expected between %d and %d",
- option,args.size()-1,minarg,maxarg );
- throw new ConfigParseError(err);
- }
+
+ for(Vector<String> optionline:args)
+
+ if(optionline.size()< (minarg+1) || optionline.size() > maxarg+1) {
+ String err = String.format("Option %s has %d parameters, expected between %d and %d",
+ option,args.size()-1,minarg,maxarg );
+ throw new ConfigParseError(err);
+ }
options.remove(option);
return args;
}
diff --git a/src/de/blinkt/openvpn/FileSelect.java b/src/de/blinkt/openvpn/FileSelect.java
index 12a3ae01..cc8f55f4 100644
--- a/src/de/blinkt/openvpn/FileSelect.java
+++ b/src/de/blinkt/openvpn/FileSelect.java
@@ -19,6 +19,7 @@ import android.os.Bundle;
public class FileSelect extends Activity {
public static final String RESULT_DATA = "RESULT_PATH";
public static final String START_DATA = "START_DATA";
+ public static final String WINDOW_TITLE = "WINDOW_TILE";
public static final String NO_INLINE_SELECTION = "de.blinkt.openvpn.NO_INLINE_SELECTION";
private FileSelectionFragment mFSFragment;
private InlineFileTab mInlineFragment;
@@ -26,7 +27,8 @@ public class FileSelect extends Activity {
private Tab inlineFileTab;
private Tab fileExplorerTab;
private boolean mNoInline;
-
+
+
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
@@ -36,6 +38,13 @@ public class FileSelect extends Activity {
if(mData==null)
mData="/sdcard";
+ String title = getIntent().getStringExtra(WINDOW_TITLE);
+ int titleId = getIntent().getIntExtra(WINDOW_TITLE, 0);
+ if(titleId!=0)
+ title =getString(titleId);
+ if(title!=null)
+ setTitle(title);
+
mNoInline = getIntent().getBooleanExtra(NO_INLINE_SELECTION, false);
ActionBar bar = getActionBar();
diff --git a/src/de/blinkt/openvpn/FileSelectLayout.java b/src/de/blinkt/openvpn/FileSelectLayout.java
index 0be099af..1a60d135 100644
--- a/src/de/blinkt/openvpn/FileSelectLayout.java
+++ b/src/de/blinkt/openvpn/FileSelectLayout.java
@@ -19,6 +19,8 @@ public class FileSelectLayout extends LinearLayout implements OnClickListener {
private Fragment mFragment;
private int mTaskId;
private Button mSelectButton;
+ private boolean mNoInline;
+ private String mTitle;
public FileSelectLayout( Context context,AttributeSet attrset) {
super(context,attrset);
@@ -26,10 +28,10 @@ public class FileSelectLayout extends LinearLayout implements OnClickListener {
TypedArray ta = context.obtainStyledAttributes(attrset,R.styleable.FileSelectLayout);
- String title = ta.getString(R.styleable.FileSelectLayout_title);
+ mTitle = ta.getString(R.styleable.FileSelectLayout_title);
TextView tview = (TextView) findViewById(R.id.file_title);
- tview.setText(title);
+ tview.setText(mTitle);
mDataView = (TextView) findViewById(R.id.file_selected_item);
mSelectButton = (Button) findViewById(R.id.file_select_button);
@@ -46,7 +48,9 @@ public class FileSelectLayout extends LinearLayout implements OnClickListener {
public void getCertificateFileDialog() {
Intent startFC = new Intent(getContext(),FileSelect.class);
startFC.putExtra(FileSelect.START_DATA, mData);
-
+ startFC.putExtra(FileSelect.WINDOW_TITLE,mTitle);
+ if(mNoInline)
+ startFC.putExtra(FileSelect.NO_INLINE_SELECTION, true);
mFragment.startActivityForResult(startFC,mTaskId);
}
@@ -73,5 +77,9 @@ public class FileSelectLayout extends LinearLayout implements OnClickListener {
}
}
+ public void setNoline() {
+ mNoInline=true;
+ }
+
}
diff --git a/src/de/blinkt/openvpn/OpenVpnService.java b/src/de/blinkt/openvpn/OpenVpnService.java
index fb60d84c..8a884fcc 100644
--- a/src/de/blinkt/openvpn/OpenVpnService.java
+++ b/src/de/blinkt/openvpn/OpenVpnService.java
@@ -20,6 +20,7 @@ import java.io.IOException;
import java.util.List;
import java.util.Vector;
+
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.PendingIntent;
@@ -54,61 +55,6 @@ public class OpenVpnService extends VpnService implements Handler.Callback {
- class CIDRIP{
- String mIp;
- int len;
- public CIDRIP(String ip, String mask){
- mIp=ip;
- String[] ipt = mask.split("\\.");
- long netmask=0;
-
- netmask += Long.parseLong(ipt[0])<< 24;
- netmask += Integer.parseInt(ipt[1])<< 16;
- netmask += Integer.parseInt(ipt[2])<< 8;
- netmask += Integer.parseInt(ipt[3]);
-
- // Add 33. bit to ensure the loop terminates
- netmask += 1l << 32;
-
- int lenZeros = 0;
- while((netmask & 0x1) == 0) {
- lenZeros++;
- netmask = netmask >> 1;
- }
- // Check if rest of netmask is only 1s
- if(netmask != (0x1ffffffffl >> lenZeros)) {
- // Asume no CIDR, set /32
- len=32;
- } else {
- len =32 -lenZeros;
- }
-
- }
- @Override
- public String toString() {
- return String.format("%s/%d",mIp,len);
- }
-
- public boolean normalise(){
- long ip=0;
-
- String[] ipt = mIp.split("\\.");
-
- ip += Long.parseLong(ipt[0])<< 24;
- 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);
- return true;
- } else {
- return false;
- }
- }
- }
-
@Override
public void onRevoke() {
OpenVpnManagementThread.stopOpenVPN();
diff --git a/src/de/blinkt/openvpn/Settings_Basic.java b/src/de/blinkt/openvpn/Settings_Basic.java
index 7586b27d..00663173 100644
--- a/src/de/blinkt/openvpn/Settings_Basic.java
+++ b/src/de/blinkt/openvpn/Settings_Basic.java
@@ -124,6 +124,7 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On
addFileSelectLayout(mClientCert);
addFileSelectLayout(mClientKey);
addFileSelectLayout(mpkcs12);
+ mpkcs12.setNoline();
loadPreferences();
@@ -285,6 +286,7 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
+ savePreferences();
outState.putString(getActivity().getPackageName() + "profileUUID", mProfile.getUUID().toString());
}
diff --git a/src/de/blinkt/openvpn/Settings_IP.java b/src/de/blinkt/openvpn/Settings_IP.java
index de625d22..52dcc5dc 100644
--- a/src/de/blinkt/openvpn/Settings_IP.java
+++ b/src/de/blinkt/openvpn/Settings_IP.java
@@ -20,6 +20,7 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang
private CheckBoxPreference mUseDefaultRoute;
private VpnProfile mProfile;
private CheckBoxPreference mRouteNoPull;
+ private CheckBoxPreference mNobind;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -47,6 +48,7 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang
mCustomRoutes = (EditTextPreference) findPreference("customRoutes");
mUseDefaultRoute = (CheckBoxPreference) findPreference("useDefaultRoute");
mRouteNoPull = (CheckBoxPreference) findPreference("routenopull");
+ mNobind = (CheckBoxPreference) findPreference("nobind");
mIPv4.setOnPreferenceChangeListener(this);
mIPv6.setOnPreferenceChangeListener(this);
@@ -56,10 +58,7 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang
mOverrideDNS.setOnPreferenceChangeListener(this);
mSearchdomain.setOnPreferenceChangeListener(this);
mCustomRoutes.setOnPreferenceChangeListener(this);
-
-
-
-
+
loadSettings();
}
@@ -109,6 +108,7 @@ public class Settings_IP extends PreferenceFragment implements OnPreferenceChang
mProfile.mUseDefaultRoute = mUseDefaultRoute.isChecked();
mProfile.mCustomRoutes = mCustomRoutes.getText();
mProfile.mRoutenopull = mRouteNoPull.isChecked();
+ mProfile.mNobind = mNobind.isChecked();
}
diff --git a/src/de/blinkt/openvpn/VPNProfileList.java b/src/de/blinkt/openvpn/VPNProfileList.java
index a14c835e..beadf53d 100644
--- a/src/de/blinkt/openvpn/VPNProfileList.java
+++ b/src/de/blinkt/openvpn/VPNProfileList.java
@@ -1,6 +1,5 @@
package de.blinkt.openvpn;
-import de.blinkt.openvpn.FileSelect.MyTabsListener;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ListFragment;
@@ -95,6 +94,10 @@ public class VPNProfileList extends ListFragment {
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
+ setListAdapter();
+ }
+
+ private void setListAdapter() {
mArrayadapter = new VPNArrayAdapter(getActivity(),R.layout.vpn_list_item,R.id.vpn_item_title);
mArrayadapter.addAll(getPM().getProfiles());
@@ -112,8 +115,8 @@ public class VPNProfileList extends ListFragment {
| MenuItem.SHOW_AS_ACTION_WITH_TEXT);
menu.add(0, MENU_IMPORT_PROFILE, 0, R.string.menu_import)
- .setIcon(android.R.drawable.ic_menu_myplaces)
- .setAlphabeticShortcut('a')
+ .setIcon(R.drawable.ic_menu_archive)
+ .setAlphabeticShortcut('i')
.setTitleCondensed(getActivity().getString(R.string.menu_import_short))
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM
| MenuItem.SHOW_AS_ACTION_WITH_TEXT );
@@ -129,6 +132,7 @@ public class VPNProfileList extends ListFragment {
} else if (itemId == MENU_IMPORT_PROFILE) {
Intent intent = new Intent(getActivity(),FileSelect.class);
intent.putExtra(FileSelect.NO_INLINE_SELECTION, true);
+ intent.putExtra(FileSelect.WINDOW_TITLE, R.string.import_configuration_file);
startActivityForResult(intent, SELECT_PROFILE);
return true;
} else {
@@ -185,12 +189,7 @@ public class VPNProfileList extends ListFragment {
});
- dialog.setNegativeButton(android.R.string.cancel,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- }
- });
+ dialog.setNegativeButton(android.R.string.cancel, null);
dialog.create().show();
}
@@ -224,8 +223,9 @@ public class VPNProfileList extends ListFragment {
VpnProfile profile = ProfileManager.get(configuredVPN);
getPM().saveProfile(getActivity(), profile);
- // Name could be modified
-
+ // Name could be modified, reset List adapter
+ setListAdapter();
+
} else if(requestCode== SELECT_PROFILE) {
String filedata = data.getStringExtra(FileSelect.RESULT_DATA);
Intent startImport = new Intent(getActivity(),ConfigConverter.class);
diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java
index b7297e89..aed9ca03 100644
--- a/src/de/blinkt/openvpn/VpnProfile.java
+++ b/src/de/blinkt/openvpn/VpnProfile.java
@@ -37,14 +37,10 @@ public class VpnProfile implements Serializable{
public static final int TYPE_USERPASS_CERTIFICATES = 5;
public static final int TYPE_USERPASS_PKCS12 = 6;
public static final int TYPE_USERPASS_KEYSTORE = 7;
-
+
// Don't change this, not all parts of the program use this constant
public static final String EXTRA_PROFILEUUID = "de.blinkt.openvpn.profileUUID";
-
-
-
-
-
+ public static final String INLINE_TAG = "[[INLINE]]";
private static final String OVPNCONFIGFILE = "android.conf";
protected transient String mTransientPW=null;
@@ -52,6 +48,8 @@ public class VpnProfile implements Serializable{
private static transient String mTempPKCS12Password;
+ public static String DEFAULT_DNS1="131.234.137.23";
+ public static String DEFAULT_DNS2="131.234.137.24";
// Public attributes, since I got mad with getter/setter
// set members to default values
@@ -71,8 +69,8 @@ public class VpnProfile implements Serializable{
public String mPKCS12Password;
public boolean mUseTLSAuth = false;
public String mServerName = "openvpn.blinkt.de" ;
- public String mDNS1="131.234.137.23";
- public String mDNS2="131.234.137.24";
+ public String mDNS1=DEFAULT_DNS1;
+ public String mDNS2=DEFAULT_DNS2;
public String mIPv4Address;
public String mIPv6Address;
public boolean mOverrideDNS=false;
@@ -92,9 +90,8 @@ public class VpnProfile implements Serializable{
public String mCustomConfigOptions="";
public String mVerb="1";
public String mCipher="";
- public static final String INLINE_TAG = "[[INLINE]]";
+ public boolean mNobind=false;
-
public void clearDefaults() {
mServerName="unkown";
@@ -266,6 +263,9 @@ public class VpnProfile implements Serializable{
cfg+="dhcp-option DNS " + mDNS2 + "\n";
}
+
+ if(mNobind)
+ cfg+="nobind\n";
@@ -307,7 +307,9 @@ public class VpnProfile implements Serializable{
//! Put inline data inline and other data as normal escaped filename
private String insertFileData(String cfgentry, String filedata) {
- if(filedata.startsWith(VpnProfile.INLINE_TAG)){
+ if(filedata==null) {
+ return String.format("%s %s\n",cfgentry,"missing");
+ }else if(filedata.startsWith(VpnProfile.INLINE_TAG)){
String datawoheader = filedata.substring(VpnProfile.INLINE_TAG.length());
return String.format("<%s>\n%s\n</%s>\n",cfgentry,datawoheader,cfgentry);
} else {
diff --git a/todo.txt b/todo.txt
index 6e3f8b72..2bafaff0 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,9 +1,4 @@
Ideas:
-
-- Implement tabbed filebrowser with
- 1. tab file selection
- 2. tab inline file for safer storage
-
- implement security notice fragment
- explain plain text storage of all data except for android keystore
- explain even more insecure of storage on sd card
@@ -11,9 +6,6 @@ Ideas:
- implement a small app that can do cert+key+ca => p12 or suggest an app on the market
- Implementation in ICS OpenVpn would require SD_WRITE permission which I would like to avoid
-- finish .ovpn -> configuration importer
- - depends on inline file storage, since config files can include inline files
-
- implement an encryption for profiles, so no sensitive data has be stored in plain text
- encrypt/decrypt with android private storage key (+no user input required)
@@ -42,8 +34,6 @@ Tap support:
- need to chose right mac of receiver
Requested by users:
-cipher
auth
mtu-link
-nobind