patches/frameworks/base/0004-Global-VPN-feature-1-2.patch

202 lines
8.6 KiB
Diff

From af0cbe50e889694dc72ab84c4e1af816bdd199b9 Mon Sep 17 00:00:00 2001
From: Oliver Scott <olivercscott@gmail.com>
Date: Thu, 8 Jul 2021 10:41:43 -0400
Subject: [PATCH 4/6] Global VPN feature [1/2]
* Modify existing VPN user range functions to conditionally have traffic
from all users pass through the global VPN.
These functions are called when:
1. Starting a VPN
2. Adding a user
3. Removing a user
* Disallow starting VPNs in secondary users when a global VPN is set
Also includes:
Author: Oliver Scott <olivercscott@gmail.com>
Date: 2021-08-27 16:30:22 -0400
Show Global VPN icon on all users
Change-Id: I496c0abbdf92b8f823bc57b297473aa14bd968c8
Change-Id: I42616cc1f4e39e1dad739d81f6d5c55e218be995
Signed-off-by: Mohammad Hasan Keramat J <ikeramat@protonmail.com>
---
core/java/android/provider/Settings.java | 6 +++
.../policy/SecurityControllerImpl.java | 8 +++-
.../com/android/server/connectivity/Vpn.java | 37 +++++++++++++++++--
3 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 8d8379831e87..bd6cc1d4d7bf 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -16060,6 +16060,12 @@ public final class Settings {
CLOCKWORK_HOME_READY,
};
+ /**
+ * Package designated as global VPN provider.
+ * @hide
+ */
+ public static final String GLOBAL_VPN_APP = "global_vpn_app";
+
/**
* Keys we no longer back up under the current schema, but want to continue to
* process when restoring historical backup datasets.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index ba947149d287..e5eb04c7818d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -39,6 +39,7 @@ import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
import android.security.KeyChain;
import android.util.ArrayMap;
import android.util.Log;
@@ -332,8 +333,13 @@ public class SecurityControllerImpl implements SecurityController {
@Override
public void onUserSwitched(int newUserId) {
mCurrentUserId = newUserId;
+ final String globalVpnApp = Settings.Global.getString(mContext.getContentResolver(),
+ Settings.Global.GLOBAL_VPN_APP);
final UserInfo newUserInfo = mUserManager.getUserInfo(newUserId);
- if (newUserInfo.isRestricted()) {
+ if (mCurrentVpns.get(UserHandle.USER_SYSTEM) != null &&
+ mCurrentVpns.get(UserHandle.USER_SYSTEM).user.equals(globalVpnApp)) {
+ mVpnUserId = UserHandle.USER_SYSTEM;
+ } else if (newUserInfo.isRestricted()) {
// VPN for a restricted profile is routed through its owner user
mVpnUserId = newUserInfo.restrictedProfileParentId;
} else {
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 8510de4ef201..7c02924a711d 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -691,6 +691,15 @@ public class Vpn {
return mAlwaysOn;
}
+ /**
+ * Returns whether currently prepared VPN package is set as the global VPN.
+ */
+ private synchronized boolean isGlobalVpn() {
+ final String globalVpnPkg = Settings.Global.getString(mContext.getContentResolver(),
+ Settings.Global.GLOBAL_VPN_APP);
+ return mUserId == UserHandle.USER_SYSTEM && mPackage.equals(globalVpnPkg);
+ }
+
/**
* Checks if a VPN app supports always-on mode.
*
@@ -1559,6 +1568,7 @@ public class Vpn {
try {
// Restricted users are not allowed to create VPNs, they are tied to Owner
enforceNotRestrictedUser();
+ enforceNotGlobalVpn();
final PackageManager packageManager = mUserIdContext.getPackageManager();
if (packageManager == null) {
@@ -1720,7 +1730,7 @@ public class Vpn {
addUserToRanges(ranges, userId, allowedApplications, disallowedApplications);
// If the user can have restricted profiles, assign all its restricted profiles too
- if (canHaveRestrictedProfile(userId)) {
+ if (canHaveRestrictedProfile(userId) || isGlobalVpn()) {
final long token = Binder.clearCallingIdentity();
List<UserInfo> users;
try {
@@ -1729,7 +1739,8 @@ public class Vpn {
Binder.restoreCallingIdentity(token);
}
for (UserInfo user : users) {
- if (user.isRestricted() && (user.restrictedProfileParentId == userId)) {
+ if ((user.isRestricted() && (user.restrictedProfileParentId == userId))
+ || isGlobalVpn()) {
addUserToRanges(ranges, user.id, allowedApplications, disallowedApplications);
}
}
@@ -1810,7 +1821,8 @@ public class Vpn {
public void onUserAdded(int userId) {
// If the user is restricted tie them to the parent user's VPN
UserInfo user = mUserManager.getUserInfo(userId);
- if (user.isRestricted() && user.restrictedProfileParentId == mUserId) {
+ if ((user.isRestricted() && user.restrictedProfileParentId == mUserId) ||
+ isGlobalVpn()) {
synchronized(Vpn.this) {
final Set<Range<Integer>> existingRanges = mNetworkCapabilities.getUids();
if (existingRanges != null) {
@@ -1839,7 +1851,8 @@ public class Vpn {
public void onUserRemoved(int userId) {
// clean up if restricted
UserInfo user = mUserManager.getUserInfo(userId);
- if (user.isRestricted() && user.restrictedProfileParentId == mUserId) {
+ if ((user.isRestricted() && user.restrictedProfileParentId == mUserId) ||
+ isGlobalVpn()) {
synchronized(Vpn.this) {
final Set<Range<Integer>> existingRanges = mNetworkCapabilities.getUids();
if (existingRanges != null) {
@@ -2278,6 +2291,17 @@ public class Vpn {
}
}
+ private void enforceNotGlobalVpn() {
+ Binder.withCleanCallingIdentity(() -> {
+ if (mUserId != UserHandle.USER_SYSTEM && !TextUtils.isEmpty(
+ Settings.Global.getString(mContext.getContentResolver(),
+ Settings.Global.GLOBAL_VPN_APP))) {
+ throw new SecurityException("Secondary users cannot configure VPNs when" +
+ " global vpn is set");
+ }
+ });
+ }
+
/**
* Start legacy VPN, controlling native daemons as needed. Creates a
* secondary thread to perform connection work, returning quickly.
@@ -2362,6 +2386,7 @@ public class Vpn {
new UserHandle(mUserId))) {
throw new SecurityException("Restricted users cannot establish VPNs");
}
+ enforceNotGlobalVpn();
final RouteInfo ipv4DefaultRoute = findIPv4DefaultRoute(egress);
final String gateway = ipv4DefaultRoute.getGateway().getHostAddress();
@@ -3859,6 +3884,7 @@ public class Vpn {
verifyCallingUidAndPackage(packageName);
enforceNotRestrictedUser();
+ enforceNotGlobalVpn();
validateRequiredFeatures(profile);
if (profile.isRestrictedToTestNetworks) {
@@ -3901,6 +3927,7 @@ public class Vpn {
verifyCallingUidAndPackage(packageName);
enforceNotRestrictedUser();
+ enforceNotGlobalVpn();
final long token = Binder.clearCallingIdentity();
try {
@@ -3964,6 +3991,7 @@ public class Vpn {
requireNonNull(packageName, "No package name provided");
enforceNotRestrictedUser();
+ enforceNotGlobalVpn();
// Prepare VPN for startup
if (!prepare(packageName, null /* newPackage */, VpnManager.TYPE_VPN_PLATFORM)) {
@@ -4085,6 +4113,7 @@ public class Vpn {
requireNonNull(packageName, "No package name provided");
enforceNotRestrictedUser();
+ enforceNotGlobalVpn();
// To stop the VPN profile, the caller must be the current prepared package and must be
// running an Ikev2VpnProfile.
--
2.41.0