diff options
13 files changed, 70 insertions, 422 deletions
diff --git a/api/current.txt b/api/current.txt index 6f05a6933a1b..014ba9d3d7a8 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6600,7 +6600,6 @@ package android.app.admin { method @Nullable public String[] getAccountTypesWithManagementDisabled(); method @Nullable public java.util.List<android.content.ComponentName> getActiveAdmins(); method @NonNull public java.util.Set<java.lang.String> getAffiliationIds(@NonNull android.content.ComponentName); - method public java.util.List<java.lang.String> getAlwaysOnVpnLockdownWhitelist(@NonNull android.content.ComponentName); method @Nullable public String getAlwaysOnVpnPackage(@NonNull android.content.ComponentName); method @WorkerThread @NonNull public android.os.Bundle getApplicationRestrictions(@Nullable android.content.ComponentName, String); method @Deprecated @Nullable public String getApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName); @@ -6675,7 +6674,6 @@ package android.app.admin { method public boolean isActivePasswordSufficient(); method public boolean isAdminActive(@NonNull android.content.ComponentName); method public boolean isAffiliatedUser(); - method public boolean isAlwaysOnVpnLockdownEnabled(@NonNull android.content.ComponentName); method public boolean isApplicationHidden(@NonNull android.content.ComponentName, String); method public boolean isBackupServiceEnabled(@NonNull android.content.ComponentName); method @Deprecated public boolean isCallerApplicationRestrictionsManagingPackage(); @@ -6713,7 +6711,6 @@ package android.app.admin { method public void setAccountManagementDisabled(@NonNull android.content.ComponentName, String, boolean); method public void setAffiliationIds(@NonNull android.content.ComponentName, @NonNull java.util.Set<java.lang.String>); method public void setAlwaysOnVpnPackage(@NonNull android.content.ComponentName, @Nullable String, boolean) throws android.content.pm.PackageManager.NameNotFoundException, java.lang.UnsupportedOperationException; - method public void setAlwaysOnVpnPackage(@NonNull android.content.ComponentName, @Nullable String, boolean, @Nullable java.util.List<java.lang.String>) throws android.content.pm.PackageManager.NameNotFoundException, java.lang.UnsupportedOperationException; method public boolean setApplicationHidden(@NonNull android.content.ComponentName, String, boolean); method @WorkerThread public void setApplicationRestrictions(@Nullable android.content.ComponentName, String, android.os.Bundle); method @Deprecated public void setApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName, @Nullable String) throws android.content.pm.PackageManager.NameNotFoundException; diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 8ca3544b8d67..2514eee09da0 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -5059,16 +5059,11 @@ public class DevicePolicyManager { } /** - * Service-specific error code used in implementation of {@code setAlwaysOnVpnPackage} methods. - * @hide - */ - public static final int ERROR_VPN_PACKAGE_NOT_FOUND = 1; - - /** * Called by a device or profile owner to configure an always-on VPN connection through a * specific application for the current user. This connection is automatically granted and * persisted after a reboot. - * <p> To support the always-on feature, an app must + * <p> + * To support the always-on feature, an app must * <ul> * <li>declare a {@link android.net.VpnService} in its manifest, guarded by * {@link android.Manifest.permission#BIND_VPN_SERVICE};</li> @@ -5077,13 +5072,12 @@ public class DevicePolicyManager { * {@link android.net.VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON}.</li> * </ul> * The call will fail if called with the package name of an unsupported VPN app. - * <p> Enabling lockdown via {@code lockdownEnabled} argument carries the risk that any failure - * of the VPN provider could break networking for all apps. * * @param vpnPackage The package name for an installed VPN app on the device, or {@code null} to * remove an existing always-on VPN configuration. * @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or - * {@code false} otherwise. This has no effect when clearing. + * {@code false} otherwise. This carries the risk that any failure of the VPN provider + * could break networking for all apps. This has no effect when clearing. * @throws SecurityException if {@code admin} is not a device or a profile owner. * @throws NameNotFoundException if {@code vpnPackage} is not installed. * @throws UnsupportedOperationException if {@code vpnPackage} exists but does not support being @@ -5092,46 +5086,11 @@ public class DevicePolicyManager { public void setAlwaysOnVpnPackage(@NonNull ComponentName admin, @Nullable String vpnPackage, boolean lockdownEnabled) throws NameNotFoundException, UnsupportedOperationException { - setAlwaysOnVpnPackage(admin, vpnPackage, lockdownEnabled, Collections.emptyList()); - } - - /** - * A version of {@link #setAlwaysOnVpnPackage(ComponentName, String, boolean)} that allows the - * admin to specify a set of apps that should be able to access the network directly when VPN - * is not connected. When VPN connects these apps switch over to VPN if allowed to use that VPN. - * System apps can always bypass VPN. - * <p> Note that the system doesn't update the whitelist when packages are installed or - * uninstalled, the admin app must call this method to keep the list up to date. - * - * @param vpnPackage package name for an installed VPN app on the device, or {@code null} - * to remove an existing always-on VPN configuration - * @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or - * {@code false} otherwise. This has no effect when clearing. - * @param lockdownWhitelist Packages that will be able to access the network directly when VPN - * is in lockdown mode but not connected. Has no effect when clearing. - * @throws SecurityException if {@code admin} is not a device or a profile - * owner. - * @throws NameNotFoundException if {@code vpnPackage} or one of - * {@code lockdownWhitelist} is not installed. - * @throws UnsupportedOperationException if {@code vpnPackage} exists but does - * not support being set as always-on, or if always-on VPN is not - * available. - */ - public void setAlwaysOnVpnPackage(@NonNull ComponentName admin, @Nullable String vpnPackage, - boolean lockdownEnabled, @Nullable List<String> lockdownWhitelist) - throws NameNotFoundException, UnsupportedOperationException { throwIfParentInstance("setAlwaysOnVpnPackage"); if (mService != null) { try { - mService.setAlwaysOnVpnPackage( - admin, vpnPackage, lockdownEnabled, lockdownWhitelist); - } catch (ServiceSpecificException e) { - switch (e.errorCode) { - case ERROR_VPN_PACKAGE_NOT_FOUND: - throw new NameNotFoundException(e.getMessage()); - default: - throw new RuntimeException( - "Unknown error setting always-on VPN: " + e.errorCode); + if (!mService.setAlwaysOnVpnPackage(admin, vpnPackage, lockdownEnabled)) { + throw new NameNotFoundException(vpnPackage); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -5140,51 +5099,6 @@ public class DevicePolicyManager { } /** - * Called by device or profile owner to query whether current always-on VPN is configured in - * lockdown mode. Returns {@code false} when no always-on configuration is set. - * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * - * @throws SecurityException if {@code admin} is not a device or a profile owner. - * - * @see #setAlwaysOnVpnPackage(ComponentName, String, boolean) - */ - public boolean isAlwaysOnVpnLockdownEnabled(@NonNull ComponentName admin) { - throwIfParentInstance("isAlwaysOnVpnLockdownEnabled"); - if (mService != null) { - try { - return mService.isAlwaysOnVpnLockdownEnabled(admin); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - return false; - } - - /** - * Called by device or profile owner to query the list of packages that are allowed to access - * the network directly when always-on VPN is in lockdown mode but not connected. Returns - * {@code null} when always-on VPN is not active or not in lockdown mode. - * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * - * @throws SecurityException if {@code admin} is not a device or a profile owner. - * - * @see #setAlwaysOnVpnPackage(ComponentName, String, boolean, List) - */ - public List<String> getAlwaysOnVpnLockdownWhitelist(@NonNull ComponentName admin) { - throwIfParentInstance("getAlwaysOnVpnLockdownWhitelist"); - if (mService != null) { - try { - return mService.getAlwaysOnVpnLockdownWhitelist(admin); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - return null; - } - - /** * Called by a device or profile owner to read the name of the package administering an * always-on VPN connection for the current user. If there is no such package, or the always-on * VPN is provided by the system instead of by an application, {@code null} will be returned. diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 5790fda718a7..1751a91caf1a 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -187,10 +187,8 @@ interface IDevicePolicyManager { void setCertInstallerPackage(in ComponentName who, String installerPackage); String getCertInstallerPackage(in ComponentName who); - boolean setAlwaysOnVpnPackage(in ComponentName who, String vpnPackage, boolean lockdown, in List<String> lockdownWhitelist); + boolean setAlwaysOnVpnPackage(in ComponentName who, String vpnPackage, boolean lockdown); String getAlwaysOnVpnPackage(in ComponentName who); - boolean isAlwaysOnVpnLockdownEnabled(in ComponentName who); - List<String> getAlwaysOnVpnLockdownWhitelist(in ComponentName who); void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity); void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName); diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 243b0ebab8f9..5bb24bab6e48 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -1014,20 +1014,14 @@ public class ConnectivityManager { * to remove an existing always-on VPN configuration. * @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or * {@code false} otherwise. - * @param lockdownWhitelist The list of packages that are allowed to access network directly - * when VPN is in lockdown mode but is not running. Non-existent packages are ignored so - * this method must be called when a package that should be whitelisted is installed or - * uninstalled. * @return {@code true} if the package is set as always-on VPN controller; * {@code false} otherwise. * @hide */ - @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage, - boolean lockdownEnabled, @Nullable List<String> lockdownWhitelist) { + boolean lockdownEnabled) { try { - return mService.setAlwaysOnVpnPackage( - userId, vpnPackage, lockdownEnabled, lockdownWhitelist); + return mService.setAlwaysOnVpnPackage(userId, vpnPackage, lockdownEnabled); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1042,7 +1036,6 @@ public class ConnectivityManager { * or {@code null} if none is set. * @hide */ - @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) public String getAlwaysOnVpnPackageForUser(int userId) { try { return mService.getAlwaysOnVpnPackage(userId); @@ -1052,36 +1045,6 @@ public class ConnectivityManager { } /** - * @return whether always-on VPN is in lockdown mode. - * - * @hide - **/ - @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) - public boolean isVpnLockdownEnabled(int userId) { - try { - return mService.isVpnLockdownEnabled(userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - - } - - /** - * @return the list of packages that are allowed to access network when always-on VPN is in - * lockdown mode but not connected. Returns {@code null} when VPN lockdown is not active. - * - * @hide - **/ - @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) - public List<String> getVpnLockdownWhitelist(int userId) { - try { - return mService.getVpnLockdownWhitelist(userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** * Returns details about the currently active default data network * for a given uid. This is for internal use only to avoid spying * other apps. diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index fd7360fd4c17..e97060a0a599 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -125,11 +125,8 @@ interface IConnectivityManager boolean updateLockdownVpn(); boolean isAlwaysOnVpnPackageSupported(int userId, String packageName); - boolean setAlwaysOnVpnPackage(int userId, String packageName, boolean lockdown, - in List<String> lockdownWhitelist); + boolean setAlwaysOnVpnPackage(int userId, String packageName, boolean lockdown); String getAlwaysOnVpnPackage(int userId); - boolean isVpnLockdownEnabled(int userId); - List<String> getVpnLockdownWhitelist(int userId); int checkMobileProvisioning(int suggestedTimeOutMs); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index aab2ead4f9ed..d840e3c720cc 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5800,16 +5800,6 @@ public final class Settings { public static final String ALWAYS_ON_VPN_LOCKDOWN = "always_on_vpn_lockdown"; /** - * Comma separated list of packages that are allowed to access the network when VPN is in - * lockdown mode but not running. - * @see #ALWAYS_ON_VPN_LOCKDOWN - * - * @hide - */ - public static final String ALWAYS_ON_VPN_LOCKDOWN_WHITELIST = - "always_on_vpn_lockdown_whitelist"; - - /** * Whether applications can be installed for this user via the system's * {@link Intent#ACTION_INSTALL_PACKAGE} mechanism. * diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 6f7312f79720..f92df6a070c6 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3528,12 +3528,6 @@ android:protectionLevel="signature|privileged" /> <uses-permission android:name="android.permission.CONTROL_VPN" /> - <!-- Allows an application to access and modify always-on VPN configuration. - <p>Not for use by third-party or privileged applications. - @hide --> - <permission android:name="android.permission.CONTROL_ALWAYS_ON_VPN" - android:protectionLevel="signature" /> - <!-- Allows an application to capture audio output. <p>Not for use by third-party applications.</p> --> <permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 9b79e85ae531..a15dbc80d7db 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -574,7 +574,6 @@ public class SettingsBackupTest { Settings.Secure.ALLOWED_GEOLOCATION_ORIGINS, Settings.Secure.ALWAYS_ON_VPN_APP, Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, - Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST, Settings.Secure.ANDROID_ID, Settings.Secure.ANR_SHOW_BACKGROUND, Settings.Secure.ASSISTANT, diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 1519c1785070..14e235489b97 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1884,12 +1884,6 @@ public class ConnectivityService extends IConnectivityManager.Stub "ConnectivityService"); } - private void enforceControlAlwaysOnVpnPermission() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.CONTROL_ALWAYS_ON_VPN, - "ConnectivityService"); - } - private void enforceNetworkStackSettingsOrSetup() { enforceAnyPermissionOf( android.Manifest.permission.NETWORK_SETTINGS, @@ -1897,12 +1891,6 @@ public class ConnectivityService extends IConnectivityManager.Stub android.Manifest.permission.NETWORK_STACK); } - private void enforceNetworkStackPermission() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.NETWORK_STACK, - "ConnectivityService"); - } - private boolean checkNetworkStackPermission() { return PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission( android.Manifest.permission.NETWORK_STACK); @@ -4159,9 +4147,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } @Override - public boolean setAlwaysOnVpnPackage( - int userId, String packageName, boolean lockdown, List<String> lockdownWhitelist) { - enforceControlAlwaysOnVpnPermission(); + public boolean setAlwaysOnVpnPackage(int userId, String packageName, boolean lockdown) { + enforceConnectivityInternalPermission(); enforceCrossUserPermission(userId); synchronized (mVpns) { @@ -4175,11 +4162,11 @@ public class ConnectivityService extends IConnectivityManager.Stub Slog.w(TAG, "User " + userId + " has no Vpn configuration"); return false; } - if (!vpn.setAlwaysOnPackage(packageName, lockdown, lockdownWhitelist)) { + if (!vpn.setAlwaysOnPackage(packageName, lockdown)) { return false; } if (!startAlwaysOnVpn(userId)) { - vpn.setAlwaysOnPackage(null, false, null); + vpn.setAlwaysOnPackage(null, false); return false; } } @@ -4188,7 +4175,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public String getAlwaysOnVpnPackage(int userId) { - enforceControlAlwaysOnVpnPermission(); + enforceConnectivityInternalPermission(); enforceCrossUserPermission(userId); synchronized (mVpns) { @@ -4202,36 +4189,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } @Override - public boolean isVpnLockdownEnabled(int userId) { - enforceControlAlwaysOnVpnPermission(); - enforceCrossUserPermission(userId); - - synchronized (mVpns) { - Vpn vpn = mVpns.get(userId); - if (vpn == null) { - Slog.w(TAG, "User " + userId + " has no Vpn configuration"); - return false; - } - return vpn.getLockdown(); - } - } - - @Override - public List<String> getVpnLockdownWhitelist(int userId) { - enforceControlAlwaysOnVpnPermission(); - enforceCrossUserPermission(userId); - - synchronized (mVpns) { - Vpn vpn = mVpns.get(userId); - if (vpn == null) { - Slog.w(TAG, "User " + userId + " has no Vpn configuration"); - return null; - } - return vpn.getLockdownWhitelist(); - } - } - - @Override public int checkMobileProvisioning(int suggestedTimeOutMs) { // TODO: Remove? Any reason to trigger a provisioning check? return -1; @@ -4460,7 +4417,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName) && !isReplacing) { Slog.d(TAG, "Removing always-on VPN package " + packageName + " for user " + userId); - vpn.setAlwaysOnPackage(null, false, null); + vpn.setAlwaysOnPackage(null, false); } } } @@ -6340,7 +6297,7 @@ public class ConnectivityService extends IConnectivityManager.Stub synchronized (mVpns) { final String alwaysOnPackage = getAlwaysOnVpnPackage(userId); if (alwaysOnPackage != null) { - setAlwaysOnVpnPackage(userId, null, false, null); + setAlwaysOnVpnPackage(userId, null, false); setVpnPackageAuthorization(alwaysOnPackage, userId, false); } diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 250884431440..62a1b036daa0 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -151,7 +151,7 @@ public class Vpn { .divide(BigInteger.valueOf(100)); } // How many routes to evaluate before bailing and declaring this Vpn should provide - // the INTERNET capability. This is necessary because computing the address space is + // the INTERNET capability. This is necessary because computing the adress space is // O(n²) and this is running in the system service, so a limit is needed to alleviate // the risk of attack. // This is taken as a total of IPv4 + IPV6 routes for simplicity, but the algorithm @@ -194,12 +194,6 @@ public class Vpn { private boolean mLockdown = false; /** - * Set of packages in addition to the VPN app itself that can access the network directly when - * VPN is not connected even if {@code mLockdown} is set. - */ - private @NonNull List<String> mLockdownWhitelist = Collections.emptyList(); - - /** * List of UIDs for which networking should be blocked until VPN is ready, during brief periods * when VPN is not running. For example, during system startup or after a crash. * @see mLockdown @@ -326,9 +320,9 @@ public class Vpn { * * Used to enable/disable legacy VPN lockdown. * - * This uses the same ip rule mechanism as - * {@link #setAlwaysOnPackage(String, boolean, List<String>)}; previous settings from calling - * that function will be replaced and saved with the always-on state. + * This uses the same ip rule mechanism as {@link #setAlwaysOnPackage(String, boolean)}; + * previous settings from calling that function will be replaced and saved with the + * always-on state. * * @param lockdown whether to prevent all traffic outside of a VPN. */ @@ -425,14 +419,12 @@ public class Vpn { * * @param packageName the package to designate as always-on VPN supplier. * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting. - * @param lockdownWhitelist packages to be whitelisted from lockdown. * @return {@code true} if the package has been set as always-on, {@code false} otherwise. */ - public synchronized boolean setAlwaysOnPackage( - String packageName, boolean lockdown, List<String> lockdownWhitelist) { + public synchronized boolean setAlwaysOnPackage(String packageName, boolean lockdown) { enforceControlPermissionOrInternalCaller(); - if (setAlwaysOnPackageInternal(packageName, lockdown, lockdownWhitelist)) { + if (setAlwaysOnPackageInternal(packageName, lockdown)) { saveAlwaysOnPackage(); return true; } @@ -447,27 +439,15 @@ public class Vpn { * * @param packageName the package to designate as always-on VPN supplier. * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting. - * @param lockdownWhitelist packages to be whitelisted from lockdown. This is only used if - * {@code lockdown} is {@code true}. Packages must not contain commas. * @return {@code true} if the package has been set as always-on, {@code false} otherwise. */ @GuardedBy("this") - private boolean setAlwaysOnPackageInternal( - String packageName, boolean lockdown, List<String> lockdownWhitelist) { + private boolean setAlwaysOnPackageInternal(String packageName, boolean lockdown) { if (VpnConfig.LEGACY_VPN.equals(packageName)) { Log.w(TAG, "Not setting legacy VPN \"" + packageName + "\" as always-on."); return false; } - if (lockdownWhitelist != null) { - for (String pkg : lockdownWhitelist) { - if (pkg.contains(",")) { - Log.w(TAG, "Not setting always-on vpn, invalid whitelisted package: " + pkg); - return false; - } - } - } - if (packageName != null) { // Pre-authorize new always-on VPN package. if (!setPackageAuthorization(packageName, true)) { @@ -480,18 +460,13 @@ public class Vpn { } mLockdown = (mAlwaysOn && lockdown); - mLockdownWhitelist = (mLockdown && lockdownWhitelist != null) - ? Collections.unmodifiableList(new ArrayList<>(lockdownWhitelist)) - : Collections.emptyList(); - if (isCurrentPreparedPackage(packageName)) { updateAlwaysOnNotification(mNetworkInfo.getDetailedState()); - setVpnForcedLocked(mLockdown); } else { // Prepare this app. The notification will update as a side-effect of updateState(). - // It also calls setVpnForcedLocked(). prepareInternal(packageName); } + setVpnForcedLocked(mLockdown); return true; } @@ -503,6 +478,7 @@ public class Vpn { * @return the package name of the VPN controller responsible for always-on VPN, * or {@code null} if none is set or always-on VPN is controlled through * lockdown instead. + * @hide */ public synchronized String getAlwaysOnPackage() { enforceControlPermissionOrInternalCaller(); @@ -510,13 +486,6 @@ public class Vpn { } /** - * @return an immutable list of packages whitelisted from always-on VPN lockdown. - */ - public synchronized List<String> getLockdownWhitelist() { - return mLockdown ? mLockdownWhitelist : null; - } - - /** * Save the always-on package and lockdown config into Settings.Secure */ @GuardedBy("this") @@ -527,9 +496,6 @@ public class Vpn { getAlwaysOnPackage(), mUserHandle); mSystemServices.settingsSecurePutIntForUser(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, (mAlwaysOn && mLockdown ? 1 : 0), mUserHandle); - mSystemServices.settingsSecurePutStringForUser( - Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST, - String.join(",", mLockdownWhitelist), mUserHandle); } finally { Binder.restoreCallingIdentity(token); } @@ -546,11 +512,7 @@ public class Vpn { Settings.Secure.ALWAYS_ON_VPN_APP, mUserHandle); final boolean alwaysOnLockdown = mSystemServices.settingsSecureGetIntForUser( Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, 0 /*default*/, mUserHandle) != 0; - final String whitelistString = mSystemServices.settingsSecureGetStringForUser( - Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST, mUserHandle); - final List<String> whitelistedPackages = TextUtils.isEmpty(whitelistString) - ? Collections.emptyList() : Arrays.asList(whitelistString.split(",")); - setAlwaysOnPackageInternal(alwaysOnPackage, alwaysOnLockdown, whitelistedPackages); + setAlwaysOnPackageInternal(alwaysOnPackage, alwaysOnLockdown); } finally { Binder.restoreCallingIdentity(token); } @@ -570,7 +532,7 @@ public class Vpn { } // Remove always-on VPN if it's not supported. if (!isAlwaysOnPackageSupported(alwaysOnPackage)) { - setAlwaysOnPackage(null, false, null); + setAlwaysOnPackage(null, false); return false; } // Skip if the service is already established. This isn't bulletproof: it's not bound @@ -1287,10 +1249,9 @@ public class Vpn { } /** - * Restricts network access from all UIDs affected by this {@link Vpn}, apart from the VPN - * service app itself and whitelisted packages, to only sockets that have had {@code protect()} - * called on them. All non-VPN traffic is blocked via a {@code PROHIBIT} response from the - * kernel. + * Restrict network access from all UIDs affected by this {@link Vpn}, apart from the VPN + * service app itself, to only sockets that have had {@code protect()} called on them. All + * non-VPN traffic is blocked via a {@code PROHIBIT} response from the kernel. * * The exception for the VPN UID isn't technically necessary -- setup should use protected * sockets -- but in practice it saves apps that don't protect their sockets from breaking. @@ -1306,13 +1267,8 @@ public class Vpn { */ @GuardedBy("this") private void setVpnForcedLocked(boolean enforce) { - final List<String> exemptedPackages; - if (isNullOrLegacyVpn(mPackage)) { - exemptedPackages = null; - } else { - exemptedPackages = new ArrayList<>(mLockdownWhitelist); - exemptedPackages.add(mPackage); - } + final List<String> exemptedPackages = + isNullOrLegacyVpn(mPackage) ? null : Collections.singletonList(mPackage); final Set<UidRange> removedRanges = new ArraySet<>(mBlockedUsers); Set<UidRange> addedRanges = Collections.emptySet(); diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java index 8d64b810b407..2455113d8874 100644 --- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java +++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java @@ -16,6 +16,10 @@ package com.android.server.pm; +import com.google.android.collect.Sets; + +import com.android.internal.util.Preconditions; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; @@ -38,10 +42,6 @@ import android.util.Log; import android.util.Slog; import android.util.SparseArray; -import com.android.internal.util.Preconditions; - -import com.google.android.collect.Sets; - import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlSerializer; @@ -666,7 +666,6 @@ public class UserRestrictionsUtils { case android.provider.Settings.Secure.ALWAYS_ON_VPN_APP: case android.provider.Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN: - case android.provider.Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST: // Whitelist system uid (ConnectivityService) and root uid to change always-on vpn final int appId = UserHandle.getAppId(callingUid); if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 90888201b89a..f79f9bc4ef86 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -74,14 +74,20 @@ import static android.app.admin.DevicePolicyManager.WIPE_SILENTLY; import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; import static android.provider.Settings.Global.PRIVATE_DNS_MODE; import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER; + import static android.provider.Telephony.Carriers.DPC_URI; import static android.provider.Telephony.Carriers.ENFORCE_KEY; import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI; -import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_ADB; -import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent + .PROVISIONING_ENTRY_POINT_ADB; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker + .STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; + import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_DEVICE_OWNER; import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_PROFILE_OWNER; + + import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; @@ -234,11 +240,11 @@ import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.FunctionalUtils.ThrowingRunnable; import com.android.internal.util.JournaledFile; import com.android.internal.util.Preconditions; -import com.android.internal.util.StatLogger; import com.android.internal.util.XmlUtils; import com.android.internal.widget.LockPatternUtils; import com.android.server.LocalServices; import com.android.server.LockGuard; +import com.android.internal.util.StatLogger; import com.android.server.SystemServerInitThreadPool; import com.android.server.SystemService; import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo; @@ -1919,11 +1925,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } AlarmManager getAlarmManager() { - return mContext.getSystemService(AlarmManager.class); - } - - ConnectivityManager getConnectivityManager() { - return mContext.getSystemService(ConnectivityManager.class); + return (AlarmManager) mContext.getSystemService(AlarmManager.class); } IWindowManager getIWindowManager() { @@ -6306,8 +6308,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { * @throws UnsupportedOperationException if the package does not support being set as always-on. */ @Override - public boolean setAlwaysOnVpnPackage(ComponentName admin, String vpnPackage, boolean lockdown, - List<String> lockdownWhitelist) + public boolean setAlwaysOnVpnPackage(ComponentName admin, String vpnPackage, boolean lockdown) throws SecurityException { enforceProfileOrDeviceOwner(admin); @@ -6315,23 +6316,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final long token = mInjector.binderClearCallingIdentity(); try { if (vpnPackage != null && !isPackageInstalledForUser(vpnPackage, userId)) { - Slog.w(LOG_TAG, "Non-existent VPN package specified: " + vpnPackage); - throw new ServiceSpecificException( - DevicePolicyManager.ERROR_VPN_PACKAGE_NOT_FOUND, vpnPackage); - } - - if (vpnPackage != null && lockdown && lockdownWhitelist != null) { - for (String packageName : lockdownWhitelist) { - if (!isPackageInstalledForUser(packageName, userId)) { - Slog.w(LOG_TAG, "Non-existent package in VPN whitelist: " + packageName); - throw new ServiceSpecificException( - DevicePolicyManager.ERROR_VPN_PACKAGE_NOT_FOUND, packageName); - } - } + return false; } - // If some package is uninstalled after the check above, it will be ignored by CM. - if (!mInjector.getConnectivityManager().setAlwaysOnVpnPackageForUser( - userId, vpnPackage, lockdown, lockdownWhitelist)) { + ConnectivityManager connectivityManager = (ConnectivityManager) + mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + if (!connectivityManager.setAlwaysOnVpnPackageForUser(userId, vpnPackage, lockdown)) { throw new UnsupportedOperationException(); } DevicePolicyEventLogger @@ -6348,40 +6337,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override - public String getAlwaysOnVpnPackage(ComponentName admin) throws SecurityException { - enforceProfileOrDeviceOwner(admin); - - final int userId = mInjector.userHandleGetCallingUserId(); - final long token = mInjector.binderClearCallingIdentity(); - try { - return mInjector.getConnectivityManager().getAlwaysOnVpnPackageForUser(userId); - } finally { - mInjector.binderRestoreCallingIdentity(token); - } - } - - @Override - public boolean isAlwaysOnVpnLockdownEnabled(ComponentName admin) throws SecurityException { - enforceProfileOrDeviceOwner(admin); - - final int userId = mInjector.userHandleGetCallingUserId(); - final long token = mInjector.binderClearCallingIdentity(); - try { - return mInjector.getConnectivityManager().isVpnLockdownEnabled(userId); - } finally { - mInjector.binderRestoreCallingIdentity(token); - } - } - - @Override - public List<String> getAlwaysOnVpnLockdownWhitelist(ComponentName admin) + public String getAlwaysOnVpnPackage(ComponentName admin) throws SecurityException { enforceProfileOrDeviceOwner(admin); final int userId = mInjector.userHandleGetCallingUserId(); final long token = mInjector.binderClearCallingIdentity(); - try { - return mInjector.getConnectivityManager().getVpnLockdownWhitelist(userId); + try{ + ConnectivityManager connectivityManager = (ConnectivityManager) + mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + return connectivityManager.getAlwaysOnVpnPackageForUser(userId); } finally { mInjector.binderRestoreCallingIdentity(token); } @@ -6854,7 +6819,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { enforceDeviceOwner(who); long token = mInjector.binderClearCallingIdentity(); try { - mInjector.getConnectivityManager().setGlobalProxy(proxyInfo); + ConnectivityManager connectivityManager = (ConnectivityManager) + mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + connectivityManager.setGlobalProxy(proxyInfo); } finally { mInjector.binderRestoreCallingIdentity(token); } diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index 5b17224e41e5..0b74d878f069 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -246,17 +246,17 @@ public class VpnTest { assertFalse(vpn.getLockdown()); // Set always-on without lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, Collections.emptyList())); + assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false)); assertTrue(vpn.getAlwaysOn()); assertFalse(vpn.getLockdown()); // Set always-on with lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.emptyList())); + assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true)); assertTrue(vpn.getAlwaysOn()); assertTrue(vpn.getLockdown()); // Remove always-on configuration. - assertTrue(vpn.setAlwaysOnPackage(null, false, Collections.emptyList())); + assertTrue(vpn.setAlwaysOnPackage(null, false)); assertFalse(vpn.getAlwaysOn()); assertFalse(vpn.getLockdown()); } @@ -270,11 +270,11 @@ public class VpnTest { assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); // Set always-on without lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null)); + assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false)); assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); // Set always-on with lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null)); + assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true)); verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { new UidRange(user.start, user.start + PKG_UIDS[1] - 1), new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) @@ -283,7 +283,7 @@ public class VpnTest { assertUnblocked(vpn, user.start + PKG_UIDS[1]); // Switch to another app. - assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null)); + assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true)); verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { new UidRange(user.start, user.start + PKG_UIDS[1] - 1), new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) @@ -297,87 +297,6 @@ public class VpnTest { } @Test - public void testLockdownWhitelist() throws Exception { - final Vpn vpn = createVpn(primaryUser.id); - final UidRange user = UidRange.createForUser(primaryUser.id); - - // Set always-on with lockdown and whitelist app PKGS[2] from lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.singletonList(PKGS[2]))); - verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { - new UidRange(user.start, user.start + PKG_UIDS[1] - 1), - new UidRange(user.start + PKG_UIDS[2] + 1, user.stop) - })); - assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]); - assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); - - // Change whitelisted app to PKGS[3]. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.singletonList(PKGS[3]))); - verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { - new UidRange(user.start + PKG_UIDS[2] + 1, user.stop) - })); - verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { - new UidRange(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1), - new UidRange(user.start + PKG_UIDS[3] + 1, user.stop) - })); - assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2]); - assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[3]); - - // Change the VPN app. - assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, Collections.singletonList(PKGS[3]))); - verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { - new UidRange(user.start, user.start + PKG_UIDS[1] - 1), - new UidRange(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1) - })); - verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { - new UidRange(user.start, user.start + PKG_UIDS[0] - 1), - new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1) - })); - assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); - assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]); - - // Remove the whitelist. - assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null)); - verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { - new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1), - new UidRange(user.start + PKG_UIDS[3] + 1, user.stop) - })); - verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { - new UidRange(user.start + PKG_UIDS[0] + 1, user.stop), - })); - assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], - user.start + PKG_UIDS[3]); - assertUnblocked(vpn, user.start + PKG_UIDS[0]); - - // Add the whitelist. - assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, Collections.singletonList(PKGS[1]))); - verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { - new UidRange(user.start + PKG_UIDS[0] + 1, user.stop) - })); - verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { - new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), - new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) - })); - assertBlocked(vpn, user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); - assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1]); - - // Try whitelisting a package with a comma, should be rejected. - assertFalse(vpn.setAlwaysOnPackage(PKGS[0], true, Collections.singletonList("a.b,c.d"))); - - // Pass a non-existent packages in the whitelist, they (and only they) should be ignored. - // Whitelisted package should change from PGKS[1] to PKGS[2]. - assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, - Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"))); - verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[]{ - new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), - new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) - })); - verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[]{ - new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[2] - 1), - new UidRange(user.start + PKG_UIDS[2] + 1, user.stop) - })); - } - - @Test public void testLockdownAddingAProfile() throws Exception { final Vpn vpn = createVpn(primaryUser.id); setMockedUsers(primaryUser); @@ -391,7 +310,7 @@ public class VpnTest { final UidRange profile = UidRange.createForUser(tempProfile.id); // Set lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null)); + assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true)); verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { new UidRange(user.start, user.start + PKG_UIDS[3] - 1), new UidRange(user.start + PKG_UIDS[3] + 1, user.stop) @@ -517,7 +436,7 @@ public class VpnTest { .cancelAsUser(anyString(), anyInt(), eq(userHandle)); // Start showing a notification for disconnected once always-on. - vpn.setAlwaysOnPackage(PKGS[0], false, null); + vpn.setAlwaysOnPackage(PKGS[0], false); order.verify(mNotificationManager) .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle)); @@ -531,7 +450,7 @@ public class VpnTest { .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle)); // Notification should be cleared after unsetting always-on package. - vpn.setAlwaysOnPackage(null, false, null); + vpn.setAlwaysOnPackage(null, false); order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle)); } @@ -664,9 +583,7 @@ public class VpnTest { doAnswer(invocation -> { final String appName = (String) invocation.getArguments()[0]; final int userId = (int) invocation.getArguments()[1]; - Integer appId = packages.get(appName); - if (appId == null) throw new PackageManager.NameNotFoundException(appName); - return UserHandle.getUid(userId, appId); + return UserHandle.getUid(userId, packages.get(appName)); }).when(mPackageManager).getPackageUidAsUser(anyString(), anyInt()); } catch (Exception e) { } |