diff options
author | cyBerta <cyberta@riseup.net> | 2019-07-05 17:18:30 +0200 |
---|---|---|
committer | cyBerta <cyberta@riseup.net> | 2019-07-12 16:59:26 +0200 |
commit | f5b8dae753448ed698486af8b49b977a58d4fcdc (patch) | |
tree | 06358a7d4e70903b6ce235f16c7e22a4800b8f99 /app/src/main/java/de/blinkt | |
parent | 962e6261e4024cd8191cf2b0c64fc8a34ea3b425 (diff) |
better support for android 8.X always-on killswitch (#8945 & #8928)
Diffstat (limited to 'app/src/main/java/de/blinkt')
3 files changed, 82 insertions, 54 deletions
diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java index bd28ae16..7028bf62 100644 --- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java +++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java @@ -5,9 +5,6 @@ package de.blinkt.openvpn; -import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.BuildConfig; - import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; @@ -15,7 +12,6 @@ import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Build; -import android.os.RemoteException; import android.preference.PreferenceManager; import android.security.KeyChain; import android.security.KeyChainException; @@ -24,7 +20,8 @@ import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Base64; -import de.blinkt.openvpn.core.*; +import com.google.gson.Gson; + import org.spongycastle.util.io.pem.PemObject; import org.spongycastle.util.io.pem.PemWriter; @@ -37,7 +34,11 @@ import java.io.Serializable; import java.io.StringWriter; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.security.*; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.Signature; +import java.security.SignatureException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; @@ -52,6 +53,21 @@ import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; +import de.blinkt.openvpn.core.Connection; +import de.blinkt.openvpn.core.ExtAuthHelper; +import de.blinkt.openvpn.core.NativeUtils; +import de.blinkt.openvpn.core.OpenVPNService; +import de.blinkt.openvpn.core.OrbotHelper; +import de.blinkt.openvpn.core.PasswordCache; +import de.blinkt.openvpn.core.Preferences; +import de.blinkt.openvpn.core.VPNLaunchHelper; +import de.blinkt.openvpn.core.VpnStatus; +import de.blinkt.openvpn.core.X509Utils; +import se.leap.bitmaskclient.BuildConfig; +import se.leap.bitmaskclient.R; + +import static se.leap.bitmaskclient.Constants.PROVIDER_PROFILE; + public class VpnProfile implements Serializable, Cloneable { // Note that this class cannot be moved to core where it belongs since // the profile loading depends on it being here @@ -755,11 +771,8 @@ public class VpnProfile implements Serializable, Cloneable { } public Intent getStartServiceIntent(Context context) { - String prefix = context.getPackageName(); - Intent intent = new Intent(context, OpenVPNService.class); - intent.putExtra(prefix + ".profileUUID", mUuid.toString()); - intent.putExtra(prefix + ".profileVersion", mVersion); + intent.putExtra(PROVIDER_PROFILE, this); return intent; } @@ -1113,6 +1126,25 @@ public class VpnProfile implements Serializable, Cloneable { return mName; } + public String toJson() { + Gson gson = new Gson(); + try { + return gson.toJson(this); + } catch (Exception e) { + return null; + } + } + + public static VpnProfile fromJson(String json) { + try { + Gson gson = new Gson(); + return gson.fromJson(json, VpnProfile.class); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + public String getUUIDString() { return mUuid.toString().toLowerCase(Locale.ENGLISH); } 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 af31e977..ea782e00 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -44,10 +44,12 @@ import de.blinkt.openvpn.core.VpnStatus.ByteCountListener; import de.blinkt.openvpn.core.VpnStatus.StateListener; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.VpnNotificationManager; +import se.leap.bitmaskclient.utils.PreferenceHelper; import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_CONNECTED; import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT; import static de.blinkt.openvpn.core.NetworkSpace.IpAddress; +import static se.leap.bitmaskclient.Constants.PROVIDER_PROFILE; public class OpenVPNService extends VpnService implements StateListener, Callback, ByteCountListener, IOpenVPNServiceInternal, VpnNotificationManager.VpnServiceCallback { @@ -61,6 +63,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac public final static String ORBOT_PACKAGE_NAME = "org.torproject.android"; private static final String PAUSE_VPN = "de.blinkt.openvpn.PAUSE_VPN"; private static final String RESUME_VPN = "se.leap.bitmaskclient.RESUME_VPN"; + private static final String TAG = OpenVPNService.class.getSimpleName(); private static boolean mNotificationAlwaysVisible = false; private final Vector<String> mDnslist = new Vector<>(); private final NetworkSpace mRoutes = new NetworkSpace(); @@ -177,7 +180,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac } VpnStatus.removeByteCountListener(this); unregisterDeviceStateReceiver(); - ProfileManager.setConntectedVpnProfileDisconnected(this); mOpenVPNThread = null; if (!mStarting) { stopForeground(!mNotificationAlwaysVisible); @@ -312,47 +314,35 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac 0, NOTIFICATION_CHANNEL_NEWSTATUS_ID); - if (intent != null && intent.hasExtra(getPackageName() + ".profileUUID")) { - String profileUUID = intent.getStringExtra(getPackageName() + ".profileUUID"); - int profileVersion = intent.getIntExtra(getPackageName() + ".profileVersion", 0); - // Try for 10s to get current version of the profile - mProfile = ProfileManager.get(this, profileUUID, profileVersion, 100); + if (intent != null && intent.hasExtra(PROVIDER_PROFILE)) { + mProfile = (VpnProfile) intent.getSerializableExtra(PROVIDER_PROFILE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { updateShortCutUsage(mProfile); } - + PreferenceHelper.setAlwaysOn(this, false); } else { /* The intent is null when we are set as always-on or the service has been restarted. */ mProfile = ProfileManager.getLastConnectedProfile(this); VpnStatus.logInfo(R.string.service_restarted); - /* Got no profile, just stop */ - if (mProfile == null) { - Log.d("OpenVPN", "Got no last connected profile on null intent. Assuming always on."); - mProfile = ProfileManager.getAlwaysOnVPN(this); - - if (mProfile == null) { - stopSelf(startId); - return START_NOT_STICKY; - } + if (mProfile != null) { + PreferenceHelper.setAlwaysOn(this, true); } - /* Do the asynchronous keychain certificate stuff */ - mProfile.checkForRestart(this); } if (mProfile == null) { - stopSelf(startId); + stopService(startId); + Log.d(TAG, "Stopping service, no profile found"); return START_NOT_STICKY; + } else { + Log.d(TAG, "Found profile: " + mProfile.mName); + /* Do the asynchronous keychain certificate stuff */ + mProfile.checkForRestart(this); } /* start the OpenVPN process itself in a background thread */ - new Thread(new Runnable() { - @Override - public void run() { - startOpenVPN(); - } - }).start(); + new Thread(this::startOpenVPN).start(); ProfileManager.setConnectedVpnProfile(this, mProfile); @@ -369,6 +359,11 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac shortcutManager.reportShortcutUsed(profile.getUUIDString()); } + private void stopService(int startId) { + VpnStatus.updateStateString("NOPROCESS", "VPN STOPPED", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED); + stopSelf(startId); + } + private void startOpenVPN() { /** * see change above (l. 292 ff) @@ -428,21 +423,17 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac } synchronized (mProcessLock) - { mProcessThread = new Thread(processThread, "OpenVPNProcessThread"); mProcessThread.start(); } - new Handler(getMainLooper()).post(new Runnable() { - @Override - public void run() { - if (mDeviceStateReceiver != null) - unregisterDeviceStateReceiver(); - - registerDeviceStateReceiver(mManagement); - } - } + new Handler(getMainLooper()).post(() -> { + if (mDeviceStateReceiver != null) { + unregisterDeviceStateReceiver(); + } + registerDeviceStateReceiver(mManagement); + } ); } @@ -550,8 +541,17 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac VpnStatus.logInfo(R.string.last_openvpn_tun_config); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mProfile.mAllowLocalLAN) { - allowAllAFFamilies(builder); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + if (mProfile.mAllowLocalLAN) { + allowAllAFFamilies(builder); + } + if (PreferenceHelper.isAlwaysOn(this)) { + try { + builder.addDisallowedApplication(this.getPackageName()); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + } } if (mLocalIP == null && mLocalIPv6 == null) { 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 b9edc4b2..d897e91f 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ProfileManager.java @@ -75,7 +75,7 @@ public class ProfileManager { SharedPreferences prefs = Preferences.getDefaultSharedPreferences(c); Editor prefsedit = prefs.edit(); - prefsedit.putString(LAST_CONNECTED_PROFILE, connectedProfile.getUUIDString()); + prefsedit.putString(LAST_CONNECTED_PROFILE, connectedProfile.toJson()); prefsedit.apply(); mLastConnectedVpn = connectedProfile; @@ -87,11 +87,8 @@ public class ProfileManager { public static VpnProfile getLastConnectedProfile(Context c) { SharedPreferences prefs = Preferences.getDefaultSharedPreferences(c); - String lastConnectedProfile = prefs.getString(LAST_CONNECTED_PROFILE, null); - if (lastConnectedProfile != null) - return get(c, lastConnectedProfile); - else - return null; + String lastConnectedProfileJson = prefs.getString(LAST_CONNECTED_PROFILE, null); + return VpnProfile.fromJson(lastConnectedProfileJson); } @@ -255,7 +252,6 @@ public class ProfileManager { String uuid = prefs.getString("alwaysOnVpn", null); return get(uuid); - } public static void updateLRU(Context c, VpnProfile profile) { |