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

199 lines
8.4 KiB
Diff

From 9924588f49088c1b4eeba9a113c19de2874ec832 Mon Sep 17 00:00:00 2001
From: Oliver Scott <olivercscott@gmail.com>
Date: Thu, 8 Jul 2021 10:41:43 -0400
Subject: [PATCH 03/11] 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 | 35 ++++++++++++++++---
3 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e7bca1419418..2d05e3e3e17f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -18572,6 +18572,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 ab5b3499d9c2..38eff0039fb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -45,6 +45,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;
@@ -393,8 +394,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 aa985907071f..9207bfea3b01 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -778,6 +778,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.
*
@@ -1724,6 +1733,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) {
@@ -1874,7 +1884,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 {
@@ -1883,7 +1893,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);
}
}
@@ -1968,7 +1979,7 @@ public class Vpn {
Log.e(TAG, "Can not retrieve UserInfo for userId=" + userId);
return;
}
- 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) {
@@ -2005,7 +2016,7 @@ public class Vpn {
Log.e(TAG, "Can not retrieve UserInfo for userId=" + userId);
return;
}
- 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) {
@@ -2430,6 +2441,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.
@@ -2513,6 +2535,7 @@ public class Vpn {
new UserHandle(mUserId))) {
throw new SecurityException("Restricted users cannot establish VPNs");
}
+ enforceNotGlobalVpn();
// Load certificates.
String privateKey = "";
@@ -4055,6 +4078,7 @@ public class Vpn {
verifyCallingUidAndPackage(packageName);
enforceNotRestrictedUser();
+ enforceNotGlobalVpn();
validateRequiredFeatures(profile);
if (profile.isRestrictedToTestNetworks) {
@@ -4097,6 +4121,7 @@ public class Vpn {
verifyCallingUidAndPackage(packageName);
enforceNotRestrictedUser();
+ enforceNotGlobalVpn();
final long token = Binder.clearCallingIdentity();
try {
@@ -4166,6 +4191,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)) {
@@ -4288,6 +4314,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.48.1