0
0
mirror of https://github.com/schwabe/ics-openvpn.git synced 2024-09-19 19:42:29 +02:00

Clean up extra for VPN start intents and try to avoid replacing VPN on autostarts

This commit is contained in:
Arne Schwabe 2023-11-30 11:56:16 +01:00
parent a85b59e84b
commit b4b37f1531
13 changed files with 71 additions and 46 deletions

View File

@ -5,6 +5,8 @@
package de.blinkt.openvpn;
import static de.blinkt.openvpn.core.OpenVPNService.EXTRA_START_REASON;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
@ -73,7 +75,7 @@ public class LaunchVPN extends Activity {
public static final String EXTRA_KEY = "de.blinkt.openvpn.shortcutProfileUUID";
public static final String EXTRA_NAME = "de.blinkt.openvpn.shortcutProfileName";
public static final String EXTRA_HIDELOG = "de.blinkt.openvpn.showNoLogWindow";
public static final String EXTRA_START_REASON = "de.blinkt.openvpn.start_reason";
public static final String CLEARLOG = "clearlogconnect";
@ -255,7 +257,7 @@ public class LaunchVPN extends Activity {
if (!mhideLog && showLogWindow)
showLogWindow();
ProfileManager.updateLRU(this, mSelectedProfile);
VPNLaunchHelper.startOpenVpn(mSelectedProfile, getBaseContext(), mSelectedProfileReason);
VPNLaunchHelper.startOpenVpn(mSelectedProfile, getBaseContext(), mSelectedProfileReason, true);
finish();
}
} else if (resultCode == Activity.RESULT_CANCELED) {

View File

@ -36,6 +36,6 @@ public class OnBootReceiver extends BroadcastReceiver {
}
void launchVPN(VpnProfile profile, Context context) {
VPNLaunchHelper.startOpenVpn(profile, context.getApplicationContext(), "on Boot receiver");
VPNLaunchHelper.startOpenVpn(profile, context.getApplicationContext(), "on Boot receiver", false);
}
}

View File

@ -5,6 +5,8 @@
package de.blinkt.openvpn;
import static de.blinkt.openvpn.core.OpenVPNService.EXTRA_DO_NOT_REPLACE_RUNNING_VPN;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
@ -31,20 +33,16 @@ import org.spongycastle.util.io.pem.PemWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.PSSParameterSpec;
import java.util.Collection;
@ -67,6 +65,8 @@ public class VpnProfile implements Serializable, Cloneable {
transient public static final long MAX_EMBED_FILE_SIZE = 2048 * 1024; // 2048kB
// 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 EXTRA_PROFILE_VERSION = "de.blinkt.openvpn.profileVersion";
public static final String INLINE_TAG = "[[INLINE]]";
public static final String DISPLAYNAME_TAG = "[[NAME]]";
public static final int MAXLOGLEVEL = 4;
@ -816,14 +816,14 @@ public class VpnProfile implements Serializable, Cloneable {
cfg.close();
}
public Intent getStartServiceIntent(Context context, String startReason) {
String prefix = context.getPackageName();
public Intent getStartServiceIntent(Context context, String startReason, boolean replace_running_vpn) {
Intent intent = new Intent(context, OpenVPNService.class);
intent.putExtra(prefix + ".profileUUID", mUuid.toString());
intent.putExtra(prefix + ".profileVersion", mVersion);
intent.putExtra(EXTRA_PROFILEUUID, mUuid.toString());
intent.putExtra(EXTRA_PROFILE_VERSION, mVersion);
if (startReason != null)
intent.putExtra(prefix + ".startReason", startReason);
intent.putExtra(OpenVPNService.EXTRA_START_REASON, startReason);
if (!replace_running_vpn)
intent.putExtra(EXTRA_DO_NOT_REPLACE_RUNNING_VPN, true);
return intent;
}

View File

@ -86,7 +86,7 @@ public class DisconnectVPN extends Activity implements DialogInterface.OnClickLi
} else if (which == DialogInterface.BUTTON_NEUTRAL) {
Intent intent = new Intent(this, LaunchVPN.class);
intent.putExtra(LaunchVPN.EXTRA_KEY, VpnStatus.getLastConnectedVPNProfile());
intent.putExtra(LaunchVPN.EXTRA_START_REASON, "Reconnect button pressed.");
intent.putExtra(OpenVPNService.EXTRA_START_REASON, "Reconnect button pressed.");
intent.setAction(Intent.ACTION_MAIN);
startActivity(intent);
}

View File

@ -6,7 +6,6 @@
package de.blinkt.openvpn.api;
import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@ -14,9 +13,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.VpnService;
import android.os.Binder;
import android.os.Build;
@ -146,11 +142,11 @@ public class ExternalOpenVPNService extends Service implements StateListener {
shortVPNIntent.setClass(getBaseContext(), de.blinkt.openvpn.LaunchVPN.class);
shortVPNIntent.putExtra(de.blinkt.openvpn.LaunchVPN.EXTRA_KEY, vp.getUUIDString());
shortVPNIntent.putExtra(de.blinkt.openvpn.LaunchVPN.EXTRA_HIDELOG, true);
shortVPNIntent.putExtra(de.blinkt.openvpn.LaunchVPN.EXTRA_START_REASON, startReason);
shortVPNIntent.putExtra(de.blinkt.openvpn.core.OpenVPNService.EXTRA_START_REASON, startReason);
shortVPNIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(shortVPNIntent);
} else {
VPNLaunchHelper.startOpenVpn(vp, getBaseContext(), startReason);
VPNLaunchHelper.startOpenVpn(vp, getBaseContext(), startReason, true);
}
}

View File

@ -93,7 +93,7 @@ public class RemoteAction extends Activity {
} else {
Intent startVPN = new Intent(this, LaunchVPN.class);
startVPN.putExtra(LaunchVPN.EXTRA_KEY, profile.getUUID().toString());
startVPN.putExtra(LaunchVPN.EXTRA_START_REASON, ".api.ConnectVPN call");
startVPN.putExtra(OpenVPNService.EXTRA_START_REASON, ".api.ConnectVPN call");
startVPN.setAction(Intent.ACTION_MAIN);
startActivity(startVPN);
}

View File

@ -6,6 +6,8 @@
package de.blinkt.openvpn.core;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static de.blinkt.openvpn.VpnProfile.EXTRA_PROFILEUUID;
import static de.blinkt.openvpn.VpnProfile.EXTRA_PROFILE_VERSION;
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;
@ -70,6 +72,11 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
public static final String START_SERVICE = "de.blinkt.openvpn.START_SERVICE";
public static final String START_SERVICE_STICKY = "de.blinkt.openvpn.START_SERVICE_STICKY";
public static final String ALWAYS_SHOW_NOTIFICATION = "de.blinkt.openvpn.NOTIFICATION_ALWAYS_VISIBLE";
public static final String EXTRA_DO_NOT_REPLACE_RUNNING_VPN = "de.blinkt.openvpn.DO_NOT_REPLACE_RUNNING_VPN";
public static final String EXTRA_START_REASON = "de.blinkt.openvpn.startReason";
public static final String DISCONNECT_VPN = "de.blinkt.openvpn.DISCONNECT_VPN";
public static final String NOTIFICATION_CHANNEL_BG_ID = "openvpn_bg";
public static final String NOTIFICATION_CHANNEL_NEWSTATUS_ID = "openvpn_newstat";
@ -86,6 +93,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
private static final int PRIORITY_MAX = 2;
private static boolean mNotificationAlwaysVisible = false;
static class TunConfig {
private final Vector<String> mDnslist = new Vector<>();
private final NetworkSpace mRoutes = new NetworkSpace();
@ -554,45 +562,46 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
private VpnProfile fetchVPNProfile(Intent intent)
{
VpnProfile vpnProfile = null;
String startReason;
if (intent != null && intent.hasExtra(getPackageName() + ".profileUUID")) {
String profileUUID = intent.getStringExtra(getPackageName() + ".profileUUID");
int profileVersion = intent.getIntExtra(getPackageName() + ".profileVersion", 0);
startReason = intent.getStringExtra(getPackageName() + ".startReason");
if (intent != null && intent.hasExtra(EXTRA_PROFILEUUID)) {
String profileUUID = intent.getStringExtra(EXTRA_PROFILEUUID);
int profileVersion = intent.getIntExtra(EXTRA_PROFILE_VERSION, 0);
startReason = intent.getStringExtra(EXTRA_START_REASON);
if (startReason == null)
startReason = "(unknown)";
// Try for 10s to get current version of the profile
mProfile = ProfileManager.get(this, profileUUID, profileVersion, 100);
vpnProfile = ProfileManager.get(this, profileUUID, profileVersion, 100);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
updateShortCutUsage(mProfile);
updateShortCutUsage(vpnProfile);
}
} else {
/* The intent is null when we are set as always-on or the service has been restarted. */
mProfile = ProfileManager.getLastConnectedProfile(this);
vpnProfile = ProfileManager.getLastConnectedProfile(this);
startReason = "Using last connected profile (started with null intent, always-on or restart after crash)";
VpnStatus.logInfo(R.string.service_restarted);
/* Got no profile, just stop */
if (mProfile == null) {
if (vpnProfile == null) {
startReason = "could not get last connected profile, using default (started with null intent, always-on or restart after crash)";
Log.d("OpenVPN", "Got no last connected profile on null intent. Assuming always on.");
mProfile = ProfileManager.getAlwaysOnVPN(this);
vpnProfile = ProfileManager.getAlwaysOnVPN(this);
if (mProfile == null) {
if (vpnProfile == null) {
return null;
}
}
/* Do the asynchronous keychain certificate stuff */
mProfile.checkForRestart(this);
vpnProfile.checkForRestart(this);
}
String name = "(null)";
if (mProfile != null)
name = mProfile.getName();
if (vpnProfile != null)
name = vpnProfile.getName();
VpnStatus.logDebug(String.format("Fetched VPN profile (%s) triggered by %s", name, startReason));
return mProfile;
return vpnProfile;
}
private boolean checkVPNPermission(VpnProfile startprofile) {
@ -608,7 +617,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
Intent launchVPNIntent = new Intent(this, LaunchVPN.class);
launchVPNIntent.putExtra(LaunchVPN.EXTRA_KEY, startprofile.getUUIDString());
launchVPNIntent.putExtra(LaunchVPN.EXTRA_START_REASON, "OpenService lacks permission");
launchVPNIntent.putExtra(EXTRA_START_REASON, "OpenService lacks permission");
launchVPNIntent.putExtra(de.blinkt.openvpn.LaunchVPN.EXTRA_HIDELOG, true);
launchVPNIntent.addFlags(FLAG_ACTIVITY_NEW_TASK);
launchVPNIntent.setAction(Intent.ACTION_MAIN);
@ -633,8 +642,23 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
if (!checkVPNPermission(vp))
return;
ProfileManager.setConnectedVpnProfile(this, mProfile);
VpnStatus.setConnectedVPNProfile(mProfile.getUUIDString());
boolean noReplaceRequested = (intent != null) && intent.getBooleanExtra(EXTRA_DO_NOT_REPLACE_RUNNING_VPN, false);
/* we get an empty start request or explicitly get told to not replace the VPN then ignore
* a start request. This avoids OnBootreciver, Always and user quickly clicking to have
* weird race conditions
*/
if (mProfile != null && mProfile == vp && (intent == null || noReplaceRequested))
{
/* we do not want to replace the running VPN */
VpnStatus.logInfo("VPN already running. Ignoring request to start VPN");
return;
}
mProfile = vp;
ProfileManager.setConnectedVpnProfile(this, vp);
VpnStatus.setConnectedVPNProfile(vp.getUUIDString());
keepVPNAlive.scheduleKeepVPNAliveJobService(this, vp);
String nativeLibraryDirectory = getApplicationInfo().nativeLibraryDir;

View File

@ -100,8 +100,8 @@ public class VPNLaunchHelper {
}
public static void startOpenVpn(VpnProfile startprofile, Context context, String startReason) {
Intent startVPN = startprofile.getStartServiceIntent(context, startReason);
public static void startOpenVpn(VpnProfile startprofile, Context context, String startReason, boolean replace_running_vpn) {
Intent startVPN = startprofile.getStartServiceIntent(context, startReason, replace_running_vpn);
if (startVPN != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
//noinspection NewApi

View File

@ -49,7 +49,7 @@ public class keepVPNAlive extends JobService implements VpnStatus.StateListener
unscheduleKeepVPNAliveJobService(this);
return false;
}
VPNLaunchHelper.startOpenVpn(vp, getApplicationContext(), "VPN keep alive Job");
VPNLaunchHelper.startOpenVpn(vp, getApplicationContext(), "VPN keep alive Job", false);
} else {
VpnStatus.logDebug("Keepalive service called but VPN still connected.");
}

View File

@ -85,7 +85,7 @@ public class OpenVPNTileService extends TileService implements VpnStatus.StateLi
@SuppressLint("Override")
@TargetApi(Build.VERSION_CODES.N)
void launchVPN(VpnProfile profile, Context context) {
VPNLaunchHelper.startOpenVpn(profile, getBaseContext(), "QuickTile");
VPNLaunchHelper.startOpenVpn(profile, getBaseContext(), "QuickTile", true);
}
@TargetApi(Build.VERSION_CODES.N)

View File

@ -5,6 +5,8 @@
package de.blinkt.openvpn.activities;
import static de.blinkt.openvpn.core.OpenVPNService.EXTRA_START_REASON;
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
@ -126,7 +128,7 @@ public class CreateShortcuts extends ListActivity implements OnItemClickListener
Intent shortcutIntent = new Intent(Intent.ACTION_MAIN);
shortcutIntent.setClass(this, LaunchVPN.class);
shortcutIntent.putExtra(LaunchVPN.EXTRA_KEY, profile.getUUID().toString());
shortcutIntent.putExtra(LaunchVPN.EXTRA_START_REASON, "shortcut");
shortcutIntent.putExtra(EXTRA_START_REASON, "shortcut");
// Then, set up the container intent (the response to the caller)

View File

@ -538,7 +538,7 @@ public class LogFragment extends ListFragment implements StateListener, SeekBar.
(dialog1, which) -> {
Intent intent = new Intent(getActivity(), LaunchVPN.class);
intent.putExtra(LaunchVPN.EXTRA_KEY, profile.getUUIDString());
intent.putExtra(LaunchVPN.EXTRA_START_REASON, "restart from logwindow");
intent.putExtra(OpenVPNService.EXTRA_START_REASON, "restart from logwindow");
intent.setAction(Intent.ACTION_MAIN);
startActivity(intent);
});

View File

@ -68,6 +68,7 @@ import de.blinkt.openvpn.core.VpnStatus;
import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT;
import static de.blinkt.openvpn.core.OpenVPNService.DISCONNECT_VPN;
import static de.blinkt.openvpn.core.OpenVPNService.EXTRA_CHALLENGE_TXT;
import static de.blinkt.openvpn.core.OpenVPNService.EXTRA_START_REASON;
public class VPNProfileList extends ListFragment implements OnClickListener, VpnStatus.StateListener {
@ -242,7 +243,7 @@ public class VPNProfileList extends ListFragment implements OnClickListener, Vpn
shortcutIntent.setClass(requireContext(), LaunchVPN.class);
shortcutIntent.putExtra(LaunchVPN.EXTRA_KEY, profile.getUUID().toString());
shortcutIntent.setAction(Intent.ACTION_MAIN);
shortcutIntent.putExtra(LaunchVPN.EXTRA_START_REASON, "shortcut");
shortcutIntent.putExtra(EXTRA_START_REASON, "shortcut");
shortcutIntent.putExtra("EXTRA_HIDELOG", true);
PersistableBundle versionExtras = new PersistableBundle();
@ -563,7 +564,7 @@ public class VPNProfileList extends ListFragment implements OnClickListener, Vpn
Intent intent = new Intent(getActivity(), LaunchVPN.class);
intent.putExtra(LaunchVPN.EXTRA_KEY, profile.getUUID().toString());
intent.putExtra(LaunchVPN.EXTRA_START_REASON, "main profile list");
intent.putExtra(EXTRA_START_REASON, "main profile list");
intent.setAction(Intent.ACTION_MAIN);
startActivity(intent);
}