diff options
Diffstat (limited to 'app/src/main/java')
31 files changed, 564 insertions, 362 deletions
diff --git a/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java b/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java index a424a489..d7f3e110 100644 --- a/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java +++ b/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn; import se.leap.bitmaskclient.R; @@ -113,27 +118,25 @@ public class LaunchVPN extends Activity { } } - @Override protected void onActivityResult (int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - - if(requestCode==START_VPN_PROFILE) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - boolean showlogwindow = prefs.getBoolean("showlogwindow", true); - - if(!mhideLog && showlogwindow) - showLogWindow(); - new startOpenVpnThread().start(); - } else if (resultCode == Activity.RESULT_CANCELED) { - // User does not want us to start, so we just vanish - VpnStatus.updateStateString("USER_VPN_PERMISSION_CANCELLED", "", R.string.state_user_vpn_permission_cancelled, - ConnectionStatus.LEVEL_NOTCONNECTED); - - finish(); - } + super.onActivityResult(requestCode, resultCode, data); + + if(requestCode==START_VPN_PROFILE) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + boolean showLogWindow = prefs.getBoolean("showlogwindow", true); + + if(!mhideLog && showLogWindow) + showLogWindow(); + new startOpenVpnThread().start(); + } else if (resultCode == Activity.RESULT_CANCELED) { + // User does not want us to start, so we just vanish + VpnStatus.updateStateString("USER_VPN_PERMISSION_CANCELLED", "", R.string.state_user_vpn_permission_cancelled, + ConnectionStatus.LEVEL_NOTCONNECTED); + + finish(); + } } - void showLogWindow() { Intent startLW = new Intent(getBaseContext(),LogWindow.class); diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java index 6fec5f46..65214c4f 100644 --- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java +++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn; import se.leap.bitmaskclient.R; @@ -40,6 +45,7 @@ import java.util.Collection; import java.util.Locale; import java.util.UUID; import java.util.Vector; +import java.util.concurrent.Future; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; @@ -166,6 +172,12 @@ public class VpnProfile implements Serializable { return VpnProfile.MININONPIEVPN; } + public static String[] replacePieWithNoPie(String[] mArgv) + { + mArgv[0] = mArgv[0].replace(MINIPIEVPN, MININONPIEVPN); + return mArgv; + } + public static String openVpnEscape(String unescaped) { if (unescaped == null) return null; @@ -174,7 +186,8 @@ public class VpnProfile implements Serializable { escapedString = escapedString.replace("\n", "\\n"); if (escapedString.equals(unescaped) && !escapedString.contains(" ") && - !escapedString.contains("#") && !escapedString.contains(";")) + !escapedString.contains("#") && !escapedString.contains(";") + && !escapedString.equals("")) return unescaped; else return '"' + escapedString + '"'; @@ -579,21 +592,15 @@ public class VpnProfile implements Serializable { - public Intent prepareIntent(Context context) { - String prefix = context.getPackageName(); + public Intent prepareStartService(Context context) { + Intent intent = getStartServiceIntent(context); - Intent intent = new Intent(context, OpenVPNService.class); if (mAuthenticationType == VpnProfile.TYPE_KEYSTORE || mAuthenticationType == VpnProfile.TYPE_USERPASS_KEYSTORE) { if (getKeyStoreCertificates(context) == null) return null; } - intent.putExtra(prefix + ".ARGV", buildOpenvpnArgv(context.getCacheDir())); - intent.putExtra(prefix + ".profileUUID", mUuid.toString()); - - ApplicationInfo info = context.getApplicationInfo(); - intent.putExtra(prefix + ".nativelib", info.nativeLibraryDir); try { FileWriter cfg = new FileWriter(context.getCacheDir().getAbsolutePath() + "/" + OVPNCONFIGFILE); @@ -607,6 +614,18 @@ public class VpnProfile implements Serializable { return intent; } + public Intent getStartServiceIntent(Context context) { + String prefix = context.getPackageName(); + + Intent intent = new Intent(context, OpenVPNService.class); + intent.putExtra(prefix + ".ARGV", buildOpenvpnArgv(context.getCacheDir())); + intent.putExtra(prefix + ".profileUUID", mUuid.toString()); + + ApplicationInfo info = context.getApplicationInfo(); + intent.putExtra(prefix + ".nativelib", info.nativeLibraryDir); + return intent; + } + public String[] getKeyStoreCertificates(Context context) { return getKeyStoreCertificates(context, 5); } @@ -635,6 +654,21 @@ public class VpnProfile implements Serializable { return false; } + public void checkForRestart(final Context context) { + /* This method is called when OpenVPNService is restarted */ + + if ((mAuthenticationType == VpnProfile.TYPE_KEYSTORE || mAuthenticationType == VpnProfile.TYPE_USERPASS_KEYSTORE) + && mPrivateKey==null) { + new Thread( new Runnable() { + @Override + public void run() { + getKeyStoreCertificates(context); + + } + }).start(); + } + } + class NoCertReturnedException extends Exception { public NoCertReturnedException (String msg) { @@ -841,21 +875,23 @@ public class VpnProfile implements Serializable { return false; } - public int needUserPWInput() { + public int needUserPWInput(boolean ignoreTransient) { if ((mAuthenticationType == TYPE_PKCS12 || mAuthenticationType == TYPE_USERPASS_PKCS12) && (mPKCS12Password == null || mPKCS12Password.equals(""))) { - if (mTransientPCKS12PW == null) + if (ignoreTransient || mTransientPCKS12PW == null) return R.string.pkcs12_file_encryption_key; } if (mAuthenticationType == TYPE_CERTIFICATES || mAuthenticationType == TYPE_USERPASS_CERTIFICATES) { if (requireTLSKeyPassword() && TextUtils.isEmpty(mKeyPassword)) - if (mTransientPCKS12PW == null) { + if (ignoreTransient || mTransientPCKS12PW == null) { return R.string.private_key_password; } } - if (isUserPWAuth() && !(!TextUtils.isEmpty(mUsername) && (!TextUtils.isEmpty(mPassword) || mTransientPW != null))) { + if (isUserPWAuth() && + (TextUtils.isEmpty(mUsername) || + (TextUtils.isEmpty(mPassword) && (mTransientPW == null || ignoreTransient)))) { return R.string.password; } return 0; diff --git a/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java b/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java index 5910173a..e6b73a48 100644 --- a/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java +++ b/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.activities; import android.app.Activity; diff --git a/app/src/main/java/de/blinkt/openvpn/activities/LogWindow.java b/app/src/main/java/de/blinkt/openvpn/activities/LogWindow.java index 7ed09dd2..5e4f9517 100644 --- a/app/src/main/java/de/blinkt/openvpn/activities/LogWindow.java +++ b/app/src/main/java/de/blinkt/openvpn/activities/LogWindow.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.activities; import android.app.Activity; diff --git a/app/src/main/java/de/blinkt/openvpn/core/CIDRIP.java b/app/src/main/java/de/blinkt/openvpn/core/CIDRIP.java index 960e7d11..ac9a8ccb 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/CIDRIP.java +++ b/app/src/main/java/de/blinkt/openvpn/core/CIDRIP.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import java.util.Locale; diff --git a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java index 9c3621e0..0d8230b7 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import java.io.BufferedReader; @@ -553,8 +558,13 @@ public class ConfigParser { noauthtypeset=false; } + Vector<String> cryptoapicert = getOption("cryptoapicert",1,1); + if(cryptoapicert!=null) { + np.mAuthenticationType = VpnProfile.TYPE_KEYSTORE; + noauthtypeset=false; + } - Vector<String> compatnames = getOption("compat-names",1,2); + Vector<String> compatnames = getOption("compat-names",1,2); Vector<String> nonameremapping = getOption("no-name-remapping",1,1); Vector<String> tlsremote = getOption("tls-remote",1,1); if(tlsremote!=null){ diff --git a/app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java b/app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java index 0126d08e..0d75ae51 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java +++ b/app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.content.BroadcastReceiver; diff --git a/app/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java b/app/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java index 485e5369..83e760ca 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.app.Application; diff --git a/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java b/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java index a2c4796d..6d7ffdf2 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java +++ b/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import java.security.InvalidKeyException; diff --git a/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java b/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java index 8c6cb1f5..35f46513 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java +++ b/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.os.Build; diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java index a5a3e9f4..e90c16d1 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; public interface OpenVPNManagement { diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java index 743e7cc5..ada065ba 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.Manifest.permission; @@ -19,6 +24,7 @@ import android.os.Message; import android.os.ParcelFileDescriptor; import android.preference.PreferenceManager; import android.text.TextUtils; +import android.util.Log; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -309,26 +315,32 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac return START_REDELIVER_INTENT; } - String UUID = "UUID"; + /* The intent is null when the service has been restarted */ if (intent == null) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - android.util.Log.d("bitmaskclient", "UUID is " + prefs.getString(UUID, "")); - mProfile = ProfileManager.get(this, prefs.getString(UUID, "")); - android.util.Log.d("bitmaskclient", "mProfile is null? " + (mProfile == null)); - if(mProfile != null) - intent = mProfile.prepareIntent(getBaseContext()); - else + mProfile = ProfileManager.getLastConnectedProfile(this, false); + + /* Got no profile, just stop */ + if (mProfile==null) { + Log.d("OpenVPN", "Got no last connected profile on null intent. Stopping"); + stopSelf(startId); return START_NOT_STICKY; - } - if(mProfile != null) - android.util.Log.d("bitmaskclient", "mProfile != null"); + } + /* Do the asynchronous keychain certificate stuff */ + mProfile.checkForRestart(this); + + /* Recreate the intent */ + intent = mProfile.getStartServiceIntent(this); + + } else { + String profileUUID = intent.getStringExtra(getPackageName() + ".profileUUID"); + mProfile = ProfileManager.get(this, profileUUID); + } + + // Extract information from the intent. String prefix = getPackageName(); String[] argv = intent.getStringArrayExtra(prefix + ".ARGV"); - String nativelibdir = intent.getStringExtra(prefix + ".nativelib"); - String profileUUID = intent.getStringExtra(prefix + ".profileUUID"); - - mProfile = ProfileManager.get(this, profileUUID); + String nativeLibraryDirectory = intent.getStringExtra(prefix + ".nativelib"); String startTitle = getString(R.string.start_vpn_title, mProfile.mName); String startTicker = getString(R.string.start_vpn_ticker, mProfile.mName); @@ -361,13 +373,12 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac // Start a new session by creating a new thread. SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - + mOvpn3 = prefs.getBoolean("ovpn3", false); if (!"ovpn3".equals(BuildConfig.FLAVOR)) mOvpn3 = false; - prefs.edit().putString(UUID, profileUUID).commit(); // Open the Management Interface if (!mOvpn3) { @@ -395,7 +406,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac } else { HashMap<String, String> env = new HashMap<String, String>(); - processThread = new OpenVPNThread(this, argv, env, nativelibdir); + processThread = new OpenVPNThread(this, argv, env, nativeLibraryDirectory); } synchronized (mProcessLock) { @@ -409,11 +420,12 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac ProfileManager.setConnectedVpnProfile(this, mProfile); + /* TODO: At the moment we have no way to handle asynchronous PW input + * Fixing will also allow to handle challenge/responsee authentication */ + if (mProfile.needUserPWInput(true) != 0) + return START_NOT_STICKY; - if (mProfile.mPersistTun) - return START_STICKY; - else - return START_NOT_STICKY; + return START_STICKY; } private OpenVPNManagement instantiateOpenVPN3Core() { @@ -517,7 +529,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac if ((Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT && !release.startsWith("4.4.3") && !release.startsWith("4.4.4") && !release.startsWith("4.4.5") && !release.startsWith("4.4.6")) && mMtu < 1280) { - VpnStatus.logInfo(String.format("Forcing MTU to 1280 instead of %d to workaround Android Bug #70916", mMtu)); + VpnStatus.logInfo(String.format(Locale.US, "Forcing MTU to 1280 instead of %d to workaround Android Bug #70916", mMtu)); builder.setMtu(1280); } else { builder.setMtu(mMtu); @@ -690,7 +702,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac VpnStatus.logWarning(R.string.ip_not_cidr, local, netmask, mode); } } - if (("p2p".equals(mode)) && mLocalIP.len < 32 || "net30".equals("net30") && mLocalIP.len < 30) { + if (("p2p".equals(mode) && mLocalIP.len < 32) || ("net30".equals(mode) && mLocalIP.len < 30)) { VpnStatus.logWarning(R.string.ip_looks_like_subnet, local, netmask, mode); } @@ -738,7 +750,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac String ticker = msg; showNotification(msg, ticker, lowpriority , 0, level); return; - } else { + } else { mDisplayBytecount = false; } diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java index 5fa2ab9e..e3c60854 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.util.Log; @@ -25,6 +30,7 @@ import de.blinkt.openvpn.core.VpnStatus.LogItem; public class OpenVPNThread implements Runnable { private static final String DUMP_PATH_STRING = "Dump path: "; + private static final String BROKEN_PIE_SUPPORT = "/data/data/de.blinkt.openvpn/cache/pievpn[1]: syntax error:"; private static final String TAG = "OpenVPN"; public static final int M_FATAL = (1 << 4); public static final int M_NONFATAL = (1 << 5); @@ -36,8 +42,9 @@ public class OpenVPNThread implements Runnable { private OpenVPNService mService; private String mDumpPath; private Map<String, String> mProcessEnv; + private boolean mBrokenPie=false; - public OpenVPNThread(OpenVPNService service,String[] argv, Map<String,String> processEnv, String nativelibdir) + public OpenVPNThread(OpenVPNService service,String[] argv, Map<String,String> processEnv, String nativelibdir) { mArgv = argv; mNativeDir = nativelibdir; @@ -68,8 +75,22 @@ public class OpenVPNThread implements Runnable { } catch (InterruptedException ie) { VpnStatus.logError("InterruptedException: " + ie.getLocalizedMessage()); } - if( exitvalue != 0) - VpnStatus.logError("Process exited with exit value " + exitvalue); + if( exitvalue != 0) { + VpnStatus.logError("Process exited with exit value " + exitvalue); + if (mBrokenPie) { + String[] noPieArgv = VpnProfile.replacePieWithNoPie(mArgv); + + // We are already noPIE, nothing to gain + if (!noPieArgv.equals(mArgv)) { + mArgv = noPieArgv; + VpnStatus.logInfo("PIE Version could not be executed. Trying no PIE version"); + run(); + return; + } + + } + + } VpnStatus.updateStateString("NOPROCESS", "No process running.", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED); if(mDumpPath!=null) { @@ -123,6 +144,9 @@ public class OpenVPNThread implements Runnable { if (logline.startsWith(DUMP_PATH_STRING)) mDumpPath = logline.substring(DUMP_PATH_STRING.length()); + + if (logline.startsWith(BROKEN_PIE_SUPPORT)) + mBrokenPie = true; // 1380308330.240114 18000002 Send to HTTP proxy: 'X-Online-Host: bla.blabla.com' diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java index e200f210..37094a1b 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.content.Context; diff --git a/app/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java b/app/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java index dd420371..bca0a4ab 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java +++ b/app/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core;/* * This software is provided 'as-is', without any express or implied * warranty. In no event will Google be held liable for any damages diff --git a/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java b/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java index 4cfbcc8e..2a26152e 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import java.io.FileNotFoundException; @@ -23,7 +28,7 @@ public class ProfileManager { - private static final String ONBOOTPROFILE = "onBootProfile"; + private static final String LAST_CONNECTED_PROFILE = "lastConnectedProfile"; @@ -65,7 +70,7 @@ public class ProfileManager { public static void setConntectedVpnProfileDisconnected(Context c) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c); Editor prefsedit = prefs.edit(); - prefsedit.putString(ONBOOTPROFILE, null); + prefsedit.putString(LAST_CONNECTED_PROFILE, null); prefsedit.apply(); } @@ -74,21 +79,23 @@ public class ProfileManager { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c); Editor prefsedit = prefs.edit(); - prefsedit.putString(ONBOOTPROFILE, connectedrofile.getUUIDString()); + prefsedit.putString(LAST_CONNECTED_PROFILE, connectedrofile.getUUIDString()); prefsedit.apply(); mLastConnectedVpn=connectedrofile; } - public static VpnProfile getOnBootProfile(Context c) { + public static VpnProfile getLastConnectedProfile(Context c, boolean onBoot) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c); boolean useStartOnBoot = prefs.getBoolean("restartvpnonboot", false); + if (onBoot && !useStartOnBoot) + return null; - String mBootProfileUUID = prefs.getString(ONBOOTPROFILE,null); - if(useStartOnBoot && mBootProfileUUID!=null) - return get(c, mBootProfileUUID); + String lastConnectedProfile = prefs.getString(LAST_CONNECTED_PROFILE, null); + if(lastConnectedProfile!=null) + return get(c, lastConnectedProfile); else return null; } diff --git a/app/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java b/app/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java index 47d88279..cf953863 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import java.net.InetSocketAddress; diff --git a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java index 57a94ee7..40f9742b 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java +++ b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.content.Context; @@ -70,7 +75,7 @@ public class VPNLaunchHelper { VpnStatus.logInfo(R.string.building_configration); - Intent startVPN = startprofile.prepareIntent(context); + Intent startVPN = startprofile.prepareStartService(context); if(startVPN!=null) context.startService(startVPN); diff --git a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java index c19daeb0..25558f13 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java +++ b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.annotation.SuppressLint; diff --git a/app/src/main/java/de/blinkt/openvpn/core/X509Utils.java b/app/src/main/java/de/blinkt/openvpn/core/X509Utils.java index 35e53c08..ff383e0f 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/X509Utils.java +++ b/app/src/main/java/de/blinkt/openvpn/core/X509Utils.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.core; import android.content.Context; diff --git a/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java b/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java index ca850533..77fc21e6 100644 --- a/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java +++ b/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.fragments; import se.leap.bitmaskclient.R; diff --git a/app/src/main/java/de/blinkt/openvpn/views/SeekBarTicks.java b/app/src/main/java/de/blinkt/openvpn/views/SeekBarTicks.java index 88e8e164..e25c2859 100644 --- a/app/src/main/java/de/blinkt/openvpn/views/SeekBarTicks.java +++ b/app/src/main/java/de/blinkt/openvpn/views/SeekBarTicks.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2012-2014 Arne Schwabe + * Distributed under the GNU GPL v2. For full terms see the file doc/LICENSE.txt + */ + package de.blinkt.openvpn.views; import android.content.Context; diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 761afc0a..547e4179 100644 --- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java +++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java @@ -21,13 +21,14 @@ import org.json.JSONObject; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver; +import se.leap.bitmaskclient.FragmentManagerEnhanced; import se.leap.bitmaskclient.SignUpDialog; + import de.blinkt.openvpn.activities.LogWindow; + import android.app.Activity; import android.app.AlertDialog; import android.app.DialogFragment; -import android.app.Fragment; -import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.Context; import android.content.DialogInterface; @@ -65,6 +66,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf public static final String START_ON_BOOT = "dashboard start on boot"; final public static String ON_BOOT = "dashboard on boot"; public static final String APP_VERSION = "bitmask version"; + final public static String TAG = Dashboard.class.getSimpleName(); private EipServiceFragment eipFragment; @@ -74,11 +76,10 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf protected static SharedPreferences preferences; private static Provider provider; - private TextView providerNameTV; - private boolean authed_eip = false; public ProviderAPIResultReceiver providerAPI_result_receiver; + private FragmentManagerEnhanced fragment_manager; @Override protected void onCreate(Bundle savedInstanceState) { @@ -91,6 +92,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf mProgressBar = (ProgressBar) findViewById(R.id.eipProgress); preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + fragment_manager = new FragmentManagerEnhanced(getFragmentManager()); handleVersion(); authed_eip = preferences.getBoolean(EIP.AUTHED_EIP, false); @@ -110,11 +112,13 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf switch(versionCode) { case 91: // 0.6.0 without Bug #5999 + case 94: // 0.8.0 with if(!preferences.getString(EIP.KEY, "").isEmpty()) { Intent rebuildVpnProfiles = new Intent(getApplicationContext(), EIP.class); rebuildVpnProfiles.setAction(EIP.ACTION_REBUILD_PROFILES); startService(rebuildVpnProfiles); } + break; } } catch (NameNotFoundException e) { } @@ -142,7 +146,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf startService(updateEIP); buildDashboard(false); invalidateOptionsMenu(); - if(data != null && data.hasExtra(LogInDialog.VERB)) { + if(data != null && data.hasExtra(LogInDialog.TAG)) { View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0); logInDialog(Bundle.EMPTY); } @@ -189,13 +193,12 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf setContentView(R.layout.client_dashboard); - providerNameTV = (TextView) findViewById(R.id.providerName); + TextView providerNameTV = (TextView) findViewById(R.id.providerName); providerNameTV.setText(provider.getDomain()); providerNameTV.setTextSize(28); mProgressBar = (ProgressBar) findViewById(R.id.eipProgress); - FragmentManager fragMan = getFragmentManager(); if ( provider.hasEIP()){ eipFragment = new EipServiceFragment(); if (hide_and_turn_on_eip) { @@ -204,7 +207,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf arguments.putBoolean(EipServiceFragment.START_ON_BOOT, true); eipFragment.setArguments(arguments); } - fragMan.beginTransaction().replace(R.id.servicesCollection, eipFragment, EipServiceFragment.TAG).commit(); + fragment_manager.replace(R.id.servicesCollection, eipFragment, EipServiceFragment.TAG); if (hide_and_turn_on_eip) { onBackPressed(); @@ -212,31 +215,35 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } } - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - JSONObject provider_json; - try { - provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); - JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE); - boolean authed_eip = preferences.getBoolean(EIP.AUTHED_EIP, false); - boolean allow_registered_eip = service_description.getBoolean(Provider.ALLOW_REGISTRATION); - preferences.edit().putBoolean(EIP.ALLOWED_REGISTERED, allow_registered_eip); - if(allow_registered_eip) { - if(authed_eip) { - menu.findItem(R.id.login_button).setVisible(false); - menu.findItem(R.id.logout_button).setVisible(true); - } else { - menu.findItem(R.id.login_button).setVisible(true); - menu.findItem(R.id.logout_button).setVisible(false); - } - menu.findItem(R.id.signup_button).setVisible(true); - } - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return true; + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + JSONObject provider_json; + try { + String provider_json_string = preferences.getString(Provider.KEY, ""); + if(provider_json_string.isEmpty() == false) { + provider_json = new JSONObject(provider_json_string); + JSONObject service_description = provider_json.getJSONObject(Provider.SERVICE); + boolean authed_eip = preferences.getBoolean(EIP.AUTHED_EIP, false); + boolean allow_registered_eip = service_description.getBoolean(Provider.ALLOW_REGISTRATION); + preferences.edit().putBoolean(EIP.ALLOWED_REGISTERED, allow_registered_eip); + + if(allow_registered_eip) { + if(authed_eip) { + menu.findItem(R.id.login_button).setVisible(false); + menu.findItem(R.id.logout_button).setVisible(true); + } else { + menu.findItem(R.id.login_button).setVisible(true); + menu.findItem(R.id.logout_button).setVisible(false); + } + menu.findItem(R.id.signup_button).setVisible(true); + } + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); } + return true; + } @Override public boolean onCreateOptionsMenu(Menu menu) { @@ -268,14 +275,13 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf startActivityForResult(new Intent(this,ConfigurationWizard.class), SWITCH_PROVIDER); return true; case R.id.login_button: - View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0); logInDialog(Bundle.EMPTY); return true; case R.id.logout_button: logOut(); return true; case R.id.signup_button: - signUpDialog(((ViewGroup)findViewById(android.R.id.content)).getChildAt(0), Bundle.EMPTY); + signUpDialog(Bundle.EMPTY); return true; default: return super.onOptionsItemSelected(item); @@ -283,38 +289,48 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } - @Override - public void authenticate(String username, String password) { - mProgressBar = (ProgressBar) findViewById(R.id.eipProgress); - eipStatus = (TextView) findViewById(R.id.eipStatus); + private Intent prepareProviderAPICommand() { + mProgressBar = (ProgressBar) findViewById(R.id.eipProgress); + eipStatus = (TextView) findViewById(R.id.eipStatus); - providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); - providerAPI_result_receiver.setReceiver(this); + providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); + providerAPI_result_receiver.setReceiver(this); - Intent provider_API_command = new Intent(this, ProviderAPI.class); + Intent command = new Intent(this, ProviderAPI.class); - Bundle parameters = new Bundle(); - parameters.putString(LogInDialog.USERNAME, username); - parameters.putString(LogInDialog.PASSWORD, password); - - JSONObject provider_json; - try { - provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); - parameters.putString(Provider.API_URL, provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION)); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); + return command; + } + + /** + * Shows the log in dialog. + */ + public void logInDialog(Bundle resultData) { + FragmentTransaction transaction = fragment_manager.removePreviousFragment(LogInDialog.TAG); + + DialogFragment newFragment = LogInDialog.newInstance(); + if(resultData != null && !resultData.isEmpty()) + newFragment.setArguments(resultData); + newFragment.show(transaction, LogInDialog.TAG); + } - provider_API_command.setAction(ProviderAPI.SRP_AUTH); - provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); - provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); - - mProgressBar.setVisibility(ProgressBar.VISIBLE); - eipStatus.setText(R.string.authenticating_message); - //mProgressBar.setMax(4); - startService(provider_API_command); - } + @Override + public void logIn(String username, String password) { + Intent provider_API_command = prepareProviderAPICommand(); + Bundle parameters = provider_API_command.getExtras().getBundle(ProviderAPI.PARAMETERS); + if(parameters == null) + parameters = new Bundle(); + + parameters.putString(SessionDialogInterface.USERNAME, username); + parameters.putString(SessionDialogInterface.PASSWORD, password); + + mProgressBar.setVisibility(ProgressBar.VISIBLE); + eipStatus.setText(R.string.authenticating_message); + + provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); + provider_API_command.setAction(ProviderAPI.SRP_AUTH); + startService(provider_API_command); + } public void cancelAuthedEipOn() { EipServiceFragment eipFragment = (EipServiceFragment) getFragmentManager().findFragmentByTag(EipServiceFragment.TAG); @@ -322,125 +338,59 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } public void cancelLoginOrSignup() { - if(mProgressBar == null) mProgressBar = (ProgressBar) findViewById(R.id.eipProgress); - if(mProgressBar != null) { - mProgressBar.setVisibility(ProgressBar.GONE); - if(eipStatus == null) eipStatus = (TextView) findViewById(R.id.eipStatus); - if(eipStatus != null) eipStatus.setText(""); - } - cancelAuthedEipOn(); + hideProgressBar(); } - /** - * Asks ProviderAPI to log out. - */ - public void logOut() { - providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); - providerAPI_result_receiver.setReceiver(this); - Intent provider_API_command = new Intent(this, ProviderAPI.class); - - Bundle parameters = new Bundle(); - - JSONObject provider_json; - try { - provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); - parameters.putString(Provider.API_URL, provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION)); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - provider_API_command.setAction(ProviderAPI.LOG_OUT); - provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); - provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); - - if(mProgressBar == null) mProgressBar = (ProgressBar) findViewById(R.id.eipProgress); - mProgressBar.setVisibility(ProgressBar.VISIBLE); - if(eipStatus == null) eipStatus = (TextView) findViewById(R.id.eipStatus); - eipStatus.setText(R.string.logout_message); - // eipStatus.setText("Starting to logout"); - - startService(provider_API_command); - //mProgressBar.setMax(1); - - } - - /** - * Shows the log in dialog. - */ - public void logInDialog(Bundle resultData) { - Log.d("Dashboard", "Log In Dialog"); - FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction(); - Fragment previous_log_in_dialog = getFragmentManager().findFragmentByTag(LogInDialog.TAG); - if (previous_log_in_dialog != null) { - fragment_transaction.remove(previous_log_in_dialog); - } - fragment_transaction.addToBackStack(null); - - DialogFragment newFragment = LogInDialog.newInstance(); - if(resultData != null && !resultData.isEmpty()) { - newFragment.setArguments(resultData); - } - newFragment.show(fragment_transaction, LogInDialog.TAG); - } - - @Override - public void signUp(String username, String password) { - mProgressBar = (ProgressBar) findViewById(R.id.eipProgress); - eipStatus = (TextView) findViewById(R.id.eipStatus); - - providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); - providerAPI_result_receiver.setReceiver(this); - - Intent provider_API_command = new Intent(this, ProviderAPI.class); - - Bundle parameters = new Bundle(); - parameters.putString(SignUpDialog.USERNAME, username); - parameters.putString(SignUpDialog.PASSWORD, password); - - JSONObject provider_json; - try { - provider_json = new JSONObject(preferences.getString(Provider.KEY, "")); - parameters.putString(Provider.API_URL, provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION)); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - provider_API_command.setAction(ProviderAPI.SRP_REGISTER); - provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); - provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver); + /** + * Asks ProviderAPI to log out. + */ + public void logOut() { + Intent provider_API_command = prepareProviderAPICommand(); + + if(mProgressBar == null) mProgressBar = (ProgressBar) findViewById(R.id.eipProgress); + mProgressBar.setVisibility(ProgressBar.VISIBLE); + if(eipStatus == null) eipStatus = (TextView) findViewById(R.id.eipStatus); + eipStatus.setText(R.string.logout_message); - mProgressBar.setVisibility(ProgressBar.VISIBLE); - eipStatus.setText(R.string.signingup_message); - //mProgressBar.setMax(4); - startService(provider_API_command); - } + provider_API_command.setAction(ProviderAPI.LOG_OUT); + startService(provider_API_command); + } - /** - * Shows the sign up dialog. - * @param view from which the dialog is created. - */ - public void signUpDialog(View view, Bundle resultData) { - FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction(); - Fragment previous_sign_up_dialog = getFragmentManager().findFragmentByTag(SignUpDialog.TAG); - if (previous_sign_up_dialog != null) { - fragment_transaction.remove(previous_sign_up_dialog); - } - fragment_transaction.addToBackStack(null); - - DialogFragment newFragment = SignUpDialog.newInstance(); - if(resultData != null && !resultData.isEmpty()) { - newFragment.setArguments(resultData); - } - newFragment.show(fragment_transaction, SignUpDialog.TAG); + /** + * Shows the sign up dialog. + */ + public void signUpDialog(Bundle resultData) { + FragmentTransaction transaction = fragment_manager.removePreviousFragment(SignUpDialog.TAG); + + DialogFragment newFragment = SignUpDialog.newInstance(); + if(resultData != null && !resultData.isEmpty()) { + newFragment.setArguments(resultData); } + newFragment.show(transaction, SignUpDialog.TAG); + } + + @Override + public void signUp(String username, String password) { + Intent provider_API_command = prepareProviderAPICommand(); + Bundle parameters = provider_API_command.getExtras().getBundle(ProviderAPI.PARAMETERS); + if(parameters == null) + parameters = new Bundle(); + + parameters.putString(SessionDialogInterface.USERNAME, username); + parameters.putString(SessionDialogInterface.PASSWORD, password); + + mProgressBar.setVisibility(ProgressBar.VISIBLE); + eipStatus.setText(R.string.signingup_message); + + provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); + provider_API_command.setAction(ProviderAPI.SRP_REGISTER); + startService(provider_API_command); + } /** * Asks ProviderAPI to download an authenticated OpenVPN certificate. - * @param session_id cookie for the server to allow us to download the certificate. */ - private void downloadAuthedUserCertificate(/*Cookie session_id*/) { + private void downloadAuthedUserCertificate() { providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); providerAPI_result_receiver.setReceiver(this); @@ -448,8 +398,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf Bundle parameters = new Bundle(); parameters.putString(ConfigurationWizard.TYPE_OF_CERTIFICATE, ConfigurationWizard.AUTHED_CERTIFICATE); - /*parameters.putString(ConfigHelper.SESSION_ID_COOKIE_KEY, session_id.getName()); - parameters.putString(ConfigHelper.SESSION_ID_KEY, session_id.getValue());*/ provider_API_command.setAction(ProviderAPI.DOWNLOAD_CERTIFICATE); provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters); @@ -460,53 +408,55 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf @Override public void onReceiveResult(int resultCode, Bundle resultData) { - if(resultCode == ProviderAPI.SRP_REGISTRATION_SUCCESSFUL){ - authenticate(resultData.getString(LogInDialog.USERNAME), resultData.getString(LogInDialog.PASSWORD)); - } else if(resultCode == ProviderAPI.SRP_REGISTRATION_FAILED){ - signUpDialog(((ViewGroup)findViewById(android.R.id.content)).getChildAt(0), resultData); - } else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL){ - String session_id_cookie_key = resultData.getString(ProviderAPI.SESSION_ID_COOKIE_KEY); - String session_id_string = resultData.getString(ProviderAPI.SESSION_ID_KEY); - setResult(RESULT_OK); - - authed_eip = true; - preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit(); - - invalidateOptionsMenu(); - mProgressBar.setVisibility(ProgressBar.GONE); - changeStatusMessage(resultCode); + if(resultCode == ProviderAPI.SRP_REGISTRATION_SUCCESSFUL) { + String username = resultData.getString(SessionDialogInterface.USERNAME); + String password = resultData.getString(SessionDialogInterface.PASSWORD); + logIn(username, password); + } else if(resultCode == ProviderAPI.SRP_REGISTRATION_FAILED) { + changeStatusMessage(resultCode); + hideProgressBar(); + + signUpDialog(resultData); + } else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL) { + changeStatusMessage(resultCode); + hideProgressBar(); + + invalidateOptionsMenu(); + + authed_eip = true; + preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit(); - //Cookie session_id = new BasicClientCookie(session_id_cookie_key, session_id_string); - downloadAuthedUserCertificate(/*session_id*/); - } else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_FAILED) { - logInDialog(resultData); - } else if(resultCode == ProviderAPI.LOGOUT_SUCCESSFUL) { - authed_eip = false; - preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit(); - mProgressBar.setVisibility(ProgressBar.GONE); - mProgressBar.setProgress(0); - invalidateOptionsMenu(); - setResult(RESULT_OK); - changeStatusMessage(resultCode); - - } else if(resultCode == ProviderAPI.LOGOUT_FAILED) { - setResult(RESULT_CANCELED); - changeStatusMessage(resultCode); - mProgressBar.setVisibility(ProgressBar.GONE); - } else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) { + downloadAuthedUserCertificate(); + } else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_FAILED) { + changeStatusMessage(resultCode); + hideProgressBar(); + + logInDialog(resultData); + } else if(resultCode == ProviderAPI.LOGOUT_SUCCESSFUL) { + changeStatusMessage(resultCode); + hideProgressBar(); + + invalidateOptionsMenu(); + + authed_eip = false; + preferences.edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit(); + + } else if(resultCode == ProviderAPI.LOGOUT_FAILED) { + changeStatusMessage(resultCode); + hideProgressBar(); + + setResult(RESULT_CANCELED); + } else if(resultCode == ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE) { + changeStatusMessage(resultCode); + hideProgressBar(); + setResult(RESULT_OK); + eipStart(); + } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) { changeStatusMessage(resultCode); - if(mProgressBar != null) - mProgressBar.setVisibility(ProgressBar.GONE); - if(EipServiceFragment.isEipSwitchChecked()) - eipStart(); - else - eipStatus.setText(R.string.eip_state_not_connected); - } else if(resultCode == ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE) { + hideProgressBar(); setResult(RESULT_CANCELED); - changeStatusMessage(resultCode); - mProgressBar.setVisibility(ProgressBar.GONE); - } + } } private void changeStatusMessage(final int previous_result_code) { @@ -515,6 +465,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf protected void onReceiveResult(int resultCode, Bundle resultData){ super.onReceiveResult(resultCode, resultData); String request = resultData.getString(EIP.REQUEST_TAG); + if(eipStatus == null) eipStatus = (TextView) findViewById(R.id.eipStatus); if (request.equalsIgnoreCase(EIP.ACTION_IS_EIP_RUNNING)){ if (resultCode == Activity.RESULT_OK){ @@ -534,6 +485,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf case ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL: eipStatus.setText(R.string.succesful_authentication_message); break; case ProviderAPI.SRP_AUTHENTICATION_FAILED: eipStatus.setText(R.string.authentication_failed_message); break; + case ProviderAPI.SRP_REGISTRATION_FAILED: eipStatus.setText(R.string.registration_failed_message); break; case ProviderAPI.CORRECTLY_DOWNLOADED_CERTIFICATE: break; case ProviderAPI.INCORRECTLY_DOWNLOADED_CERTIFICATE: eipStatus.setText(R.string.incorrectly_downloaded_certificate_message); break; case ProviderAPI.LOGOUT_SUCCESSFUL: eipStatus.setText(R.string.logged_out_message); break; @@ -547,6 +499,14 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf eipIsRunning(eip_status_receiver); } + private void hideProgressBar() { + if(mProgressBar == null) + mProgressBar = (ProgressBar) findViewById(R.id.eipProgress); + + mProgressBar.setProgress(0); + mProgressBar.setVisibility(ProgressBar.GONE); + } + /** * For retrieving the base application Context in classes that don't extend * Android's Activity class @@ -558,11 +518,12 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } - @Override + @Override public void startActivityForResult(Intent intent, int requestCode) { intent.putExtra(Dashboard.REQUEST_CODE, requestCode); super.startActivityForResult(intent, requestCode); } + /** * Send a command to EIP * @@ -577,30 +538,19 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf startService(eip_intent); } - /** - * Send a command to EIP - * - */ - private void eipStop(){ - // TODO validate "action"...how do we get the list of intent-filters for a class via Android API? - Intent eip_intent = new Intent(this, EIP.class); - eip_intent.setAction(EIP.ACTION_STOP_EIP); - // eip_intent.putExtra(EIP.RECEIVER_TAG, eip_receiver);fi - startService(eip_intent); - - } - - private void eipStart(){ - Intent eip_intent = new Intent(this, EIP.class); - eip_intent.setAction(EIP.ACTION_START_EIP); - eip_intent.putExtra(EIP.RECEIVER_TAG, EipServiceFragment.getReceiver()); - startService(eip_intent); + private void eipStop(){ + EipServiceFragment eipFragment = (EipServiceFragment) getFragmentManager().findFragmentByTag(EipServiceFragment.TAG); + eipFragment.stopEIP(); + } + private void eipStart() { + EipServiceFragment eipFragment = (EipServiceFragment) getFragmentManager().findFragmentByTag(EipServiceFragment.TAG); + eipFragment.startEipFromScratch(); } - protected void setProgressBarVisibility(int visibility) { + protected void showProgressBar() { if(mProgressBar == null) mProgressBar = (ProgressBar) findViewById(R.id.eipProgress); - mProgressBar.setVisibility(visibility); + mProgressBar.setVisibility(ProgressBar.VISIBLE); } } diff --git a/app/src/main/java/se/leap/bitmaskclient/EIP.java b/app/src/main/java/se/leap/bitmaskclient/EIP.java index 4a8bae46..ad7552c8 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/EIP.java @@ -87,7 +87,7 @@ public final class EIP extends IntentService { public final static String SERVICE_API_PATH = "config/eip-service.json"; public final static String RECEIVER_TAG = "receiverTag"; public final static String REQUEST_TAG = "requestTag"; - public final static String TAG = "se.leap.bitmaskclient.EIP"; + public final static String TAG = EIP.class.getSimpleName(); public final static SimpleDateFormat certificate_date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US); @@ -113,8 +113,9 @@ public final class EIP extends IntentService { super.onCreate(); context = getApplicationContext(); - - updateEIPService(); + + // Log.d(TAG, "Update EIP Service onCreate EIP"); + // updateEIPService(); } @Override @@ -130,7 +131,7 @@ public final class EIP extends IntentService { protected void onHandleIntent(Intent intent) { String action = intent.getAction(); mReceiver = intent.getParcelableExtra(RECEIVER_TAG); - + if ( action == ACTION_START_EIP ) startEIP(); else if ( action == ACTION_STOP_EIP ) @@ -155,6 +156,7 @@ public final class EIP extends IntentService { activeGateway = selectGateway(); if(activeGateway != null && activeGateway.mVpnProfile != null) { + mReceiver = EipServiceFragment.getReceiver(); launchActiveGateway(); } } @@ -318,8 +320,11 @@ public final class EIP extends IntentService { */ private void updateEIPService() { try { - eipDefinition = new JSONObject(getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(KEY, "")); - parsedEipSerial = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getInt(PARSED_SERIAL, 0); + String eip_definition_string = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getString(KEY, ""); + if(eip_definition_string.isEmpty() == false) { + eipDefinition = new JSONObject(eip_definition_string); + } + parsedEipSerial = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).getInt(PARSED_SERIAL, 0); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -327,16 +332,14 @@ public final class EIP extends IntentService { if(parsedEipSerial == 0) { deleteAllVpnProfiles(); } - if (eipDefinition != null && eipDefinition.optInt("serial") > parsedEipSerial) + if (eipDefinition != null && eipDefinition.optInt("serial") >= parsedEipSerial) updateGateways(); } private void deleteAllVpnProfiles() { ProfileManager vpl = ProfileManager.getInstance(context); - VpnProfile[] profiles = (VpnProfile[]) vpl.getProfiles().toArray(new VpnProfile[vpl.getProfiles().size()]); - for (int current_profile = 0; current_profile < profiles.length; current_profile++){ - vpl.removeProfile(context, profiles[current_profile]); - } + Collection<VpnProfile> profiles = vpl.getProfiles(); + profiles.removeAll(profiles); } /** @@ -346,8 +349,8 @@ public final class EIP extends IntentService { */ private void updateGateways(){ JSONArray gatewaysDefined = null; - try { + if(eipDefinition == null) updateEIPService(); gatewaysDefined = eipDefinition.getJSONArray("gateways"); for ( int i=0 ; i < gatewaysDefined.length(); i++ ){ JSONObject gw = null; @@ -360,7 +363,6 @@ public final class EIP extends IntentService { // TODO Auto-generated catch block e.printStackTrace(); } - getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putInt(PARSED_SERIAL, eipDefinition.optInt(Provider.API_RETURN_SERIAL)).commit(); } @@ -483,6 +485,7 @@ public final class EIP extends IntentService { cp.parseConfig(new StringReader(certSecretFromSharedPreferences())); cp.parseConfig(new StringReader("remote-cert-tls server")); cp.parseConfig(new StringReader("persist-tun")); + cp.parseConfig(new StringReader("auth-retry nointeract")); VpnProfile vp = cp.convertProfile(); //vp.mAuthenticationType=VpnProfile.TYPE_STATICKEYS; mVpnProfile = vp; diff --git a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java index 18ee0262..a7d68198 100644 --- a/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/EipServiceFragment.java @@ -195,7 +195,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe eipCommand(EIP.ACTION_START_EIP); } - private void stopEIP() { + protected void stopEIP() { EIP.mIsStarting = false; View eipProgressBar = getActivity().findViewById(R.id.eipProgress); if(eipProgressBar != null) @@ -236,7 +236,8 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe } else if(justDecidedOnDisconnect && level == ConnectionStatus.LEVEL_CONNECTED) { EIP.lastConnectionStatusLevel = ConnectionStatus.LEVEL_NOTCONNECTED; updateState(state, logmessage, localizedResId, level); - } + } // else if(isNewLevel || level == ConnectionStatus.LEVEL_AUTH_FAILED) + // handleNewState(state, logmessage, localizedResId, level); } private void handleNewState(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) { @@ -248,6 +249,8 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe setNoServerReplyUI(localizedResId, logmessage); else if (level == ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED) setServerReplyUI(state, localizedResId, logmessage); + // else if (level == ConnectionStatus.LEVEL_AUTH_FAILED) + // handleSwitchOn(); } private boolean isDisconnectedLevel(final ConnectionStatus level) { @@ -380,7 +383,7 @@ public class EipServiceFragment extends Fragment implements StateListener, OnChe case Activity.RESULT_CANCELED: Dashboard dashboard = (Dashboard) getActivity(); - dashboard.setProgressBarVisibility(ProgressBar.VISIBLE); + dashboard.showProgressBar(); String status = getResources().getString(R.string.updating_certificate_message); setEipStatus(status); diff --git a/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java b/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java new file mode 100644 index 00000000..c4844be9 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/FragmentManagerEnhanced.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2013 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package se.leap.bitmaskclient; + +import android.app.Fragment; +import android.app.FragmentManager; +import android.app.FragmentTransaction; + +public class FragmentManagerEnhanced { + + private FragmentManager generic_fragment_manager; + + public FragmentManagerEnhanced(FragmentManager generic_fragment_manager) { + this.generic_fragment_manager = generic_fragment_manager; + } + + public FragmentTransaction removePreviousFragment(String tag) { + FragmentTransaction transaction = generic_fragment_manager.beginTransaction(); + Fragment previous_fragment = generic_fragment_manager.findFragmentByTag(tag); + if (previous_fragment != null) { + transaction.remove(previous_fragment); + } + transaction.addToBackStack(null); + + return transaction; + } + + public void replace(int containerViewId, Fragment fragment, String tag) { + FragmentTransaction transaction = generic_fragment_manager.beginTransaction(); + + transaction.replace(containerViewId, fragment, tag).commit(); + } + + public Fragment findFragmentByTag(String tag) { + return generic_fragment_manager.findFragmentByTag(tag); + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java b/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java index 45d3a373..5a0c9a6d 100644 --- a/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java @@ -42,15 +42,10 @@ import android.widget.TextView; * @author parmegv * */ -public class LogInDialog extends DialogFragment { +public class LogInDialog extends SessionDialogInterface { - final public static String TAG = "logInDialog"; - final public static String VERB = "log in"; - final public static String USERNAME = "username"; - final public static String PASSWORD = "password"; - final public static String USERNAME_MISSING = "username missing"; - final public static String PASSWORD_INVALID_LENGTH = "password_invalid_length"; + final public static String TAG = LogInDialog.class.getSimpleName(); private static boolean is_eip_pending = false; @@ -93,7 +88,7 @@ public class LogInDialog extends DialogFragment { String username = username_field.getText().toString(); String password = password_field.getText().toString(); dialog.dismiss(); - interface_with_Dashboard.authenticate(username, password); + interface_with_Dashboard.logIn(username, password); } }) .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { @@ -120,7 +115,7 @@ public class LogInDialog extends DialogFragment { * */ public interface LogInDialogInterface { - public void authenticate(String username, String password); + public void logIn(String username, String password); public void cancelAuthedEipOn(); public void signUp(String username, String password); public void cancelLoginOrSignup(); @@ -149,8 +144,8 @@ public class LogInDialog extends DialogFragment { @Override public void onCancel(DialogInterface dialog) { + super.onCancel(dialog); if(is_eip_pending) interface_with_Dashboard.cancelAuthedEipOn(); - super.onCancel(dialog); } } diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java b/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java index 7b256124..7e4e95d3 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderAPIResultReceiver.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
- package se.leap.bitmaskclient;
+package se.leap.bitmaskclient;
import android.os.Bundle;
import android.os.Handler;
diff --git a/app/src/main/java/se/leap/bitmaskclient/SessionDialogInterface.java b/app/src/main/java/se/leap/bitmaskclient/SessionDialogInterface.java new file mode 100644 index 00000000..7b08a4d1 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/SessionDialogInterface.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2013 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package se.leap.bitmaskclient; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.DialogFragment; +import android.content.DialogInterface; +import android.os.Bundle; + +/** + * @author parmegv + */ +public abstract class SessionDialogInterface extends DialogFragment { + final public static String USERNAME = "username"; + final public static String PASSWORD = "password"; + final public static String USERNAME_MISSING = "username missing"; + final public static String PASSWORD_INVALID_LENGTH = "password_invalid_length"; + + @Override + public void onAttach(Activity activity) { super.onAttach(activity); } + + @Override + public void onCancel(DialogInterface dialog) { super.onCancel(dialog); } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java b/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java index 120d4eec..3cb41f4f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java @@ -42,14 +42,9 @@ import android.widget.TextView; * @author parmegv * */ -public class SignUpDialog extends DialogFragment { - - final public static String TAG = "signUpDialog"; - final public static String VERB = "log in"; - final public static String USERNAME = "username"; - final public static String PASSWORD = "password"; - final public static String USERNAME_MISSING = "username missing"; - final public static String PASSWORD_INVALID_LENGTH = "password_invalid_length"; +public class SignUpDialog extends SessionDialogInterface { + + final public static String TAG = SignUpDialog.class.getSimpleName(); private static boolean is_eip_pending = false; diff --git a/app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java b/app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java index b7289c23..7b597554 100644 --- a/app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java +++ b/app/src/main/java/se/leap/bitmaskclient/VoidVpnService.java @@ -1,10 +1,11 @@ package se.leap.bitmaskclient; import android.content.Intent; +import android.os.Process; import android.net.VpnService; import android.util.Log; -public class VoidVpnService extends VpnService { +public class VoidVpnService extends VpnService { static final String START_BLOCKING_VPN_PROFILE = "se.leap.bitmaskclient.START_BLOCKING_VPN_PROFILE"; static final String TAG = VoidVpnService.class.getSimpleName(); @@ -14,29 +15,22 @@ public class VoidVpnService extends VpnService { String action = intent.getAction(); if (action == START_BLOCKING_VPN_PROFILE) { new Thread(new Runnable() { - public void run() { - blockConnections(); + public void run() { + Builder builder = new Builder(); + builder.setSession("Blocking until running"); + builder.addAddress("10.42.0.8",16); + builder.addRoute("0.0.0.0", 1); + builder.addRoute("192.168.1.0", 24); + builder.addDnsServer("10.42.0.1"); + try { + builder.establish(); + } catch (Exception e) { + e.printStackTrace(); + } + android.util.Log.d(TAG, "VoidVpnService set up"); } }).run(); } return 0; } - - public void blockConnections() { - Builder builder = new Builder(); - builder.setSession("Blocking until running"); - builder.addAddress("10.42.0.8",16); - builder.addRoute("0.0.0.0", 1); - builder.addRoute("128.0.0.0", 1); - builder.addRoute("192.168.1.0", 24); - builder.addDnsServer("10.42.0.1"); - builder.establish(); - android.util.Log.d(TAG, "VoidVpnService set up"); - try { - new java.net.Socket("sdf.org", 80); - Log.d(TAG, "VoidVpnService doesn's stop traffic"); - } catch (Exception e) { - e.printStackTrace(); - } - } } |