From 2a94b5823dc1fec044882839406631f881671ff4 Mon Sep 17 00:00:00 2001 From: Jonathan Scott Date: Mon, 13 Feb 2023 16:11:45 +0000 Subject: [PATCH 1/3] Add permission access to DPM Apis. Test: btest a.d.c.ScreenCaptureDisabledTest Test: btest a.d.c.SystemUpdateTest Test: btest a.d.c.WifiTest Test: btest a.d.c.SecurityLoggingTest Bug: 234609037 Change-Id: Ic68bfdeb9bde90779696101f58ace67bba543a46 --- core/api/current.txt | 26 +- .../app/admin/DevicePolicyManager.java | 219 ++++++---- .../app/admin/IDevicePolicyManager.aidl | 16 +- .../DevicePolicyManagerService.java | 373 +++++++++++++----- 4 files changed, 420 insertions(+), 214 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index 7fdc7b5072e10..cba32356be340 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -7886,8 +7886,8 @@ package android.app.admin { method @NonNull public java.util.List getUserControlDisabledPackages(@NonNull android.content.ComponentName); method @NonNull public android.os.Bundle getUserRestrictions(@NonNull android.content.ComponentName); method @NonNull public android.os.Bundle getUserRestrictionsGlobally(); - method @Nullable public String getWifiMacAddress(@NonNull android.content.ComponentName); - method @Nullable public android.app.admin.WifiSsidPolicy getWifiSsidPolicy(); + method @Nullable public String getWifiMacAddress(@Nullable android.content.ComponentName); + method @Nullable @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI, conditional=true) public android.app.admin.WifiSsidPolicy getWifiSsidPolicy(); method public boolean grantKeyPairToApp(@Nullable android.content.ComponentName, @NonNull String, @NonNull String); method public boolean grantKeyPairToWifiAuth(@NonNull String); method public boolean hasCaCertInstalled(@Nullable android.content.ComponentName, byte[]); @@ -7899,7 +7899,7 @@ package android.app.admin { method public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate, @NonNull String); method public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate[], @NonNull String, boolean); method public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate[], @NonNull String, int); - method public void installSystemUpdate(@NonNull android.content.ComponentName, @NonNull android.net.Uri, @NonNull java.util.concurrent.Executor, @NonNull android.app.admin.DevicePolicyManager.InstallSystemUpdateCallback); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, conditional=true) public void installSystemUpdate(@Nullable android.content.ComponentName, @NonNull android.net.Uri, @NonNull java.util.concurrent.Executor, @NonNull android.app.admin.DevicePolicyManager.InstallSystemUpdateCallback); method public boolean isActivePasswordSufficient(); method public boolean isActivePasswordSufficientForDeviceRequirement(); method public boolean isAdminActive(@NonNull android.content.ComponentName); @@ -7927,7 +7927,7 @@ package android.app.admin { method public boolean isProvisioningAllowed(@NonNull String); method public boolean isResetPasswordTokenActive(android.content.ComponentName); method public boolean isSafeOperation(int); - method public boolean isSecurityLoggingEnabled(@Nullable android.content.ComponentName); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING, conditional=true) public boolean isSecurityLoggingEnabled(@Nullable android.content.ComponentName); method public boolean isStatusBarDisabled(); method public boolean isUninstallBlocked(@Nullable android.content.ComponentName, String); method public boolean isUniqueDeviceAttestationSupported(); @@ -7947,8 +7947,8 @@ package android.app.admin { method @Deprecated public boolean resetPassword(String, int); method public boolean resetPasswordWithToken(@NonNull android.content.ComponentName, String, byte[], int); method @Nullable public java.util.List retrieveNetworkLogs(@Nullable android.content.ComponentName, long); - method @Nullable public java.util.List retrievePreRebootSecurityLogs(@NonNull android.content.ComponentName); - method @Nullable public java.util.List retrieveSecurityLogs(@NonNull android.content.ComponentName); + method @Nullable @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING, conditional=true) public java.util.List retrievePreRebootSecurityLogs(@Nullable android.content.ComponentName); + method @Nullable @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING, conditional=true) public java.util.List retrieveSecurityLogs(@Nullable android.content.ComponentName); method public boolean revokeKeyPairFromApp(@Nullable android.content.ComponentName, @NonNull String, @NonNull String); method public boolean revokeKeyPairFromWifiAuth(@NonNull String); method public void setAccountManagementDisabled(@NonNull android.content.ComponentName, String, boolean); @@ -7994,10 +7994,10 @@ package android.app.admin { method public void setManagedProfileMaximumTimeOff(@NonNull android.content.ComponentName, long); method public void setManagedSubscriptionsPolicy(@Nullable android.app.admin.ManagedSubscriptionsPolicy); method public void setMasterVolumeMuted(@NonNull android.content.ComponentName, boolean); - method public void setMaximumFailedPasswordsForWipe(@NonNull android.content.ComponentName, int); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_WIPE_DATA, conditional=true) public void setMaximumFailedPasswordsForWipe(@Nullable android.content.ComponentName, int); method public void setMaximumTimeToLock(@NonNull android.content.ComponentName, long); method @NonNull public java.util.List setMeteredDataDisabledPackages(@NonNull android.content.ComponentName, @NonNull java.util.List); - method public void setMinimumRequiredWifiSecurityLevel(int); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI, conditional=true) public void setMinimumRequiredWifiSecurityLevel(int); method public void setMtePolicy(int); method public void setNearbyAppStreamingPolicy(int); method public void setNearbyNotificationStreamingPolicy(int); @@ -8032,23 +8032,23 @@ package android.app.admin { method public void setRequiredStrongAuthTimeout(@NonNull android.content.ComponentName, long); method public boolean setResetPasswordToken(android.content.ComponentName, byte[]); method public void setRestrictionsProvider(@NonNull android.content.ComponentName, @Nullable android.content.ComponentName); - method public void setScreenCaptureDisabled(@NonNull android.content.ComponentName, boolean); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, conditional=true) public void setScreenCaptureDisabled(@Nullable android.content.ComponentName, boolean); method public void setSecureSetting(@NonNull android.content.ComponentName, String, String); - method public void setSecurityLoggingEnabled(@NonNull android.content.ComponentName, boolean); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING, conditional=true) public void setSecurityLoggingEnabled(@Nullable android.content.ComponentName, boolean); method public void setShortSupportMessage(@NonNull android.content.ComponentName, @Nullable CharSequence); method public void setStartUserSessionMessage(@NonNull android.content.ComponentName, @Nullable CharSequence); method public boolean setStatusBarDisabled(@NonNull android.content.ComponentName, boolean); method @Deprecated public int setStorageEncryption(@NonNull android.content.ComponentName, boolean); method public void setSystemSetting(@NonNull android.content.ComponentName, @NonNull String, String); - method public void setSystemUpdatePolicy(@NonNull android.content.ComponentName, android.app.admin.SystemUpdatePolicy); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, conditional=true) public void setSystemUpdatePolicy(@NonNull android.content.ComponentName, android.app.admin.SystemUpdatePolicy); method @RequiresPermission(value=android.Manifest.permission.SET_TIME, conditional=true) public boolean setTime(@NonNull android.content.ComponentName, long); method @RequiresPermission(value=android.Manifest.permission.SET_TIME_ZONE, conditional=true) public boolean setTimeZone(@NonNull android.content.ComponentName, String); method public void setTrustAgentConfiguration(@NonNull android.content.ComponentName, @NonNull android.content.ComponentName, android.os.PersistableBundle); method public void setUninstallBlocked(@Nullable android.content.ComponentName, String, boolean); - method public void setUsbDataSignalingEnabled(boolean); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING, conditional=true) public void setUsbDataSignalingEnabled(boolean); method public void setUserControlDisabledPackages(@NonNull android.content.ComponentName, @NonNull java.util.List); method public void setUserIcon(@NonNull android.content.ComponentName, android.graphics.Bitmap); - method public void setWifiSsidPolicy(@Nullable android.app.admin.WifiSsidPolicy); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI, conditional=true) public void setWifiSsidPolicy(@Nullable android.app.admin.WifiSsidPolicy); method public int startUserInBackground(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle); method public int stopUser(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle); method public boolean switchUser(@NonNull android.content.ComponentName, @Nullable android.os.UserHandle); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index f8941c06185bf..c12e7ca08e9e5 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -19,7 +19,15 @@ package android.app.admin; import static android.Manifest.permission.INTERACT_ACROSS_USERS; import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA; +import static android.Manifest.permission.MANAGE_DEVICE_ADMINS; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SCREEN_CAPTURE; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIPE_DATA; import static android.Manifest.permission.QUERY_ADMIN_POLICY; import static android.Manifest.permission.SET_TIME; import static android.Manifest.permission.SET_TIME_ZONE; @@ -5722,16 +5730,16 @@ public class DevicePolicyManager { } /** - * Setting this to a value greater than zero enables a built-in policy that will perform a + * Setting this to a value greater than zero enables a policy that will perform a * device or profile wipe after too many incorrect device-unlock passwords have been entered. - * This built-in policy combines watching for failed passwords and wiping the device, and - * requires that you request both {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} and + * This policy combines watching for failed passwords and wiping the device, and + * requires that calling Device Admins request both + * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} and * {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA}}. *

- * When this policy is set by a device owner, profile owner of an organization-owned device or - * an admin on the primary user, the device will be factory reset after too many incorrect - * password attempts. When set by a profile owner or an admin on a secondary user or a managed - * profile, only the corresponding user or profile will be wiped. + * When this policy is set on the system or the main user, the device will be factory reset + * after too many incorrect password attempts. When set on any other user, only the + * corresponding user or profile will be wiped. *

* To implement any other policy (e.g. wiping data for a particular application only, erasing or * revoking credentials, or reporting the failure to a server), you should implement @@ -5744,19 +5752,27 @@ public class DevicePolicyManager { * profile. *

On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the * password is always empty and this method has no effect - i.e. the policy is not set. + *

+ * This policy can be set by holders of the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_WIPE_DATA} permission. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the + * caller is not a device admin. * @param num The number of failed password attempts at which point the device or profile will * be wiped. - * @throws SecurityException if {@code admin} is not an active administrator or does not use - * both {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} and - * {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA}. + * @throws SecurityException if {@code admin} is not null, and {@code admin} is not an active + * administrator or does not use both + * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} and + * {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA}, or if {@code admin} is null and the + * caller does not have permission to wipe the device. */ + @RequiresPermission(value = MANAGE_DEVICE_POLICY_WIPE_DATA, conditional = true) @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN) - public void setMaximumFailedPasswordsForWipe(@NonNull ComponentName admin, int num) { + public void setMaximumFailedPasswordsForWipe(@Nullable ComponentName admin, int num) { if (mService != null) { try { - mService.setMaximumFailedPasswordsForWipe(admin, num, mParentInstance); + mService.setMaximumFailedPasswordsForWipe( + admin, mContext.getPackageName(), num, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -8318,9 +8334,11 @@ public class DevicePolicyManager { } /** - * Called by a device/profile owner to set whether the screen capture is disabled. Disabling - * screen capture also prevents the content from being shown on display devices that do not have - * a secure video output. See {@link android.view.Display#FLAG_SECURE} for more details about + * Called by a device owner, profile owner, or holder of the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_SCREEN_CAPTURE} permission to set + * whether the screen capture is disabled. Disabling screen capture also prevents the + * content from being shown on display devices that do not have a secure video output. + * See {@link android.view.Display#FLAG_SECURE} for more details about * secure surfaces and secure displays. *

* This method can be called on the {@link DevicePolicyManager} instance, returned by @@ -8334,16 +8352,17 @@ public class DevicePolicyManager { * From version {@link android.os.Build.VERSION_CODES#M} disabling screen capture also blocks * assist requests for all activities of the relevant user. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the + * caller is not a device admin. * @param disabled Whether screen capture is disabled or not. - * @throws SecurityException if {@code admin} is not a device or profile owner or if - * called on the parent profile and the {@code admin} is not a - * profile owner of an organization-owned managed profile. + * @throws SecurityException if the caller is not permitted to control screen capture policy. */ - public void setScreenCaptureDisabled(@NonNull ComponentName admin, boolean disabled) { + @RequiresPermission(value = MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, conditional = true) + public void setScreenCaptureDisabled(@Nullable ComponentName admin, boolean disabled) { if (mService != null) { try { - mService.setScreenCaptureDisabled(admin, disabled, mParentInstance); + mService.setScreenCaptureDisabled( + admin, mContext.getPackageName(), disabled, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -8781,7 +8800,7 @@ public class DevicePolicyManager { @TestApi @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @RequiresPermission(allOf = { - android.Manifest.permission.MANAGE_DEVICE_ADMINS, + MANAGE_DEVICE_ADMINS, INTERACT_ACROSS_USERS_FULL }) public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing, @@ -9209,7 +9228,7 @@ public class DevicePolicyManager { */ @Deprecated @SystemApi - @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) + @RequiresPermission(MANAGE_DEVICE_ADMINS) public boolean setActiveProfileOwner(@NonNull ComponentName admin, @Deprecated String ownerName) throws IllegalArgumentException { throwIfParentInstance("setActiveProfileOwner"); @@ -12500,9 +12519,10 @@ public class DevicePolicyManager { } /** - * Called by device owners or profile owners of an organization-owned managed profile to to set - * a local system update policy. When a new policy is set, - * {@link #ACTION_SYSTEM_UPDATE_POLICY_CHANGED} is broadcasted. + * Called by a device owner, profile owners of an organization-owned managed profile, or a + * holder of the {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_SYSTEM_UPDATES} + * permission to set a local system update policy. When a new policy is set, + * {@link #ACTION_SYSTEM_UPDATE_POLICY_CHANGED} is broadcast. *

* If the supplied system update policy has freeze periods set but the freeze periods do not * meet 90-day maximum length or 60-day minimum separation requirement set out in @@ -12516,22 +12536,24 @@ public class DevicePolicyManager { * {@code adb shell dpm clear-freeze-period-record} can be used to clear the record. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. All - * components in the device owner package can set system update policies and the most - * recent policy takes effect. + * components in the package can set system update policies and the most + * recent policy takes effect. This should be null if the caller is not a device + * admin. * @param policy the new policy, or {@code null} to clear the current policy. * @throws SecurityException if {@code admin} is not a device owner or a profile owner of an - * organization-owned managed profile. + * organization-owned managed profile, or the caller is not permitted to set this policy * @throws IllegalArgumentException if the policy type or maintenance window is not valid. * @throws SystemUpdatePolicy.ValidationFailedException if the policy's freeze period does not * meet the requirement. * @see SystemUpdatePolicy * @see SystemUpdatePolicy#setFreezePeriods(List) */ + @RequiresPermission(value = MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, conditional = true) public void setSystemUpdatePolicy(@NonNull ComponentName admin, SystemUpdatePolicy policy) { throwIfParentInstance("setSystemUpdatePolicy"); if (mService != null) { try { - mService.setSystemUpdatePolicy(admin, policy); + mService.setSystemUpdatePolicy(admin, mContext.getPackageName(), policy); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -12989,7 +13011,7 @@ public class DevicePolicyManager { } /** - * Called by device owner, or profile owner on organization-owned device, to get the MAC + * Called by a device owner or profile owner on organization-owned device to get the MAC * address of the Wi-Fi device. * * NOTE: The MAC address returned here should only be used for inventory management and is @@ -12998,17 +13020,19 @@ public class DevicePolicyManager { * To get the randomized MAC address used, call * {@link android.net.wifi.WifiConfiguration#getRandomizedMacAddress}. * - * @param admin Which device owner this request is associated with. + * @param admin Which admin this request is associated with. Null if the caller is not a device + * admin * @return the MAC address of the Wi-Fi device, or null when the information is not available. * (For example, Wi-Fi hasn't been enabled, or the device doesn't support Wi-Fi.) *

* The address will be in the {@code XX:XX:XX:XX:XX:XX} format. - * @throws SecurityException if {@code admin} is not a device owner. + * @throws SecurityException if {@code admin} is not permitted to get wifi mac addresses */ - public @Nullable String getWifiMacAddress(@NonNull ComponentName admin) { +// @RequiresPermission(value = MANAGE_DEVICE_POLICY_WIFI, conditional = true) + public @Nullable String getWifiMacAddress(@Nullable ComponentName admin) { throwIfParentInstance("getWifiMacAddress"); try { - return mService.getWifiMacAddress(admin); + return mService.getWifiMacAddress(admin, mContext.getPackageName()); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -13249,31 +13273,34 @@ public class DevicePolicyManager { } /** - * Called by device owner or a profile owner of an organization-owned managed profile to - * control the security logging feature. + * Called by a device owner, profile owner of an organization-owned managed profile, or holder + * of the {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_SECURITY_LOGGING} permission + * to control the security logging feature. * *

Security logs contain various information intended for security auditing purposes. - * When security logging is enabled by a profile owner of - * an organization-owned managed profile, certain security logs are not visible (for example - * personal app launch events) or they will be redacted (for example, details of the physical - * volume mount events). Please see {@link SecurityEvent} for details. + * When security logging is enabled by any app other than the device owner, certain security + * logs are not visible (for example personal app launch events) or they will be redacted + * (for example, details of the physical volume mount events). + * Please see {@link SecurityEvent} for details. * *

Note: The device owner won't be able to retrieve security logs if there * are unaffiliated secondary users or profiles on the device, regardless of whether the * feature is enabled. Logs will be discarded if the internal buffer fills up while waiting for * all users to become affiliated. Therefore it's recommended that affiliation ids are set for - * new users as soon as possible after provisioning via {@link #setAffiliationIds}. Profile - * owner of organization-owned managed profile is not subject to this restriction since all + * new users as soon as possible after provisioning via {@link #setAffiliationIds}. Non device + * owners are not subject to this restriction since all * privacy-sensitive events happening outside the managed profile would have been redacted * already. * - * @param admin Which device admin this request is associated with. + * @param admin Which device admin this request is associated with. Null if the caller is not + * a device admin * @param enabled whether security logging should be enabled or not. - * @throws SecurityException if {@code admin} is not allowed to control security logging. + * @throws SecurityException if the caller is not permitted to control security logging. * @see #setAffiliationIds * @see #retrieveSecurityLogs */ - public void setSecurityLoggingEnabled(@NonNull ComponentName admin, boolean enabled) { + @RequiresPermission(value = MANAGE_DEVICE_POLICY_SECURITY_LOGGING, conditional = true) + public void setSecurityLoggingEnabled(@Nullable ComponentName admin, boolean enabled) { throwIfParentInstance("setSecurityLoggingEnabled"); try { mService.setSecurityLoggingEnabled(admin, mContext.getPackageName(), enabled); @@ -13285,13 +13312,17 @@ public class DevicePolicyManager { /** * Return whether security logging is enabled or not by the admin. * - *

Can only be called by the device owner or a profile owner of an organization-owned - * managed profile, otherwise a {@link SecurityException} will be thrown. + *

Can only be called by a device owner, a profile owner of an organization-owned + * managed profile, or a holder of the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_SECURITY_LOGGING} permission + * otherwise a {@link SecurityException} will be thrown. * - * @param admin Which device admin this request is associated with. - * @return {@code true} if security logging is enabled by device owner, {@code false} otherwise. - * @throws SecurityException if {@code admin} is not allowed to control security logging. + * @param admin Which device admin this request is associated with. Null if the caller is not + * a device admin + * @return {@code true} if security logging is enabled, {@code false} otherwise. + * @throws SecurityException if the caller is not allowed to control security logging. */ + @RequiresPermission(value = MANAGE_DEVICE_POLICY_SECURITY_LOGGING, conditional = true) public boolean isSecurityLoggingEnabled(@Nullable ComponentName admin) { throwIfParentInstance("isSecurityLoggingEnabled"); try { @@ -13302,26 +13333,30 @@ public class DevicePolicyManager { } /** - * Called by device owner or profile owner of an organization-owned managed profile to retrieve - * all new security logging entries since the last call to this API after device boots. + * Called by a device owner, profile owner of an organization-owned managed profile, or holder + * of the {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_SECURITY_LOGGING} permission + * to retrieve all new security logging entries since the last call to this API after device + * boots. * - *

Access to the logs is rate limited and it will only return new logs after the device - * owner has been notified via {@link DeviceAdminReceiver#onSecurityLogsAvailable}. + *

Access to the logs is rate limited and it will only return new logs after the admin has + * been notified via {@link DeviceAdminReceiver#onSecurityLogsAvailable}. * *

When called by a device owner, if there is any other user or profile on the device, * it must be affiliated with the device. Otherwise a {@link SecurityException} will be thrown. * See {@link #isAffiliatedUser}. * - * @param admin Which device admin this request is associated with. + * @param admin Which device admin this request is associated with. Null if the caller is not + * a device admin. * @return the new batch of security logs which is a list of {@link SecurityEvent}, * or {@code null} if rate limitation is exceeded or if logging is currently disabled. - * @throws SecurityException if {@code admin} is not allowed to access security logging, + * @throws SecurityException if the caller is not allowed to access security logging, * or there is at least one profile or secondary user that is not affiliated with the device. * @see #isAffiliatedUser * @see DeviceAdminReceiver#onSecurityLogsAvailable */ @SuppressLint("NullableCollection") - public @Nullable List retrieveSecurityLogs(@NonNull ComponentName admin) { + @RequiresPermission(value = MANAGE_DEVICE_POLICY_SECURITY_LOGGING, conditional = true) + public @Nullable List retrieveSecurityLogs(@Nullable ComponentName admin) { throwIfParentInstance("retrieveSecurityLogs"); try { ParceledListSlice list = mService.retrieveSecurityLogs( @@ -13455,8 +13490,9 @@ public class DevicePolicyManager { } /** - * Called by device owner or profile owner of an organization-owned managed profile to retrieve - * device logs from before the device's last reboot. + * Called by a device owner, profile owner of an organization-owned managed profile, or holder + * of the {@link android.Manfiest.permission#MANAGE_DEVICE_POLICY_SECURITY_LOGGING} permission + * to retrieve device logs from before the device's last reboot. *

* This API is not supported on all devices. Calling this API on unsupported devices * will result in {@code null} being returned. The device logs are retrieved from a RAM region @@ -13467,17 +13503,19 @@ public class DevicePolicyManager { * it must be affiliated with the device. Otherwise a {@link SecurityException} will be thrown. * See {@link #isAffiliatedUser}. * - * @param admin Which device admin this request is associated with. + * @param admin Which device admin this request is associated with. Null if the caller is not + * a device admin. * @return Device logs from before the latest reboot of the system, or {@code null} if this API * is not supported on the device. - * @throws SecurityException if {@code admin} is not allowed to access security logging, or + * @throws SecurityException if the caller is not allowed to access security logging, or * there is at least one profile or secondary user that is not affiliated with the device. * @see #isAffiliatedUser * @see #retrieveSecurityLogs */ @SuppressLint("NullableCollection") + @RequiresPermission(value = MANAGE_DEVICE_POLICY_SECURITY_LOGGING, conditional = true) public @Nullable List retrievePreRebootSecurityLogs( - @NonNull ComponentName admin) { + @Nullable ComponentName admin) { throwIfParentInstance("retrievePreRebootSecurityLogs"); try { ParceledListSlice list = mService.retrievePreRebootSecurityLogs( @@ -14837,8 +14875,9 @@ public class DevicePolicyManager { } /** - * Called by device owner or profile owner of an organization-owned managed profile to install - * a system update from the given file. The device will be + * Called by a device owner, profile owner of an organization-owned managed profile, or a holder + * of the {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_SYSTEM_UPDATES} permission to + * install a system update from the given file. The device will be * rebooted in order to finish installing the update. Note that if the device is rebooted, this * doesn't necessarily mean that the update has been applied successfully. The caller should * additionally check the system version with {@link android.os.Build#FINGERPRINT} or {@link @@ -14847,15 +14886,17 @@ public class DevicePolicyManager { * sufficient battery level, the installation will fail with error {@link * InstallSystemUpdateCallback#UPDATE_ERROR_BATTERY_LOW}. * - * @param admin The {@link DeviceAdminReceiver} that this request is associated with. - * @param updateFilePath An Uri of the file that contains the update. The file should be + * @param admin The {@link DeviceAdminReceiver} that this request is associated with. Null if + * the caller is not a device admin + * @param updateFilePath A Uri of the file that contains the update. The file should be * readable by the calling app. * @param executor The executor through which the callback should be invoked. * @param callback A callback object that will inform the caller when installing an update * fails. */ + @RequiresPermission(value = MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, conditional = true) public void installSystemUpdate( - @NonNull ComponentName admin, @NonNull Uri updateFilePath, + @Nullable ComponentName admin, @NonNull Uri updateFilePath, @NonNull @CallbackExecutor Executor executor, @NonNull InstallSystemUpdateCallback callback) { throwIfParentInstance("installUpdate"); @@ -14865,7 +14906,8 @@ public class DevicePolicyManager { try (ParcelFileDescriptor fileDescriptor = mContext.getContentResolver() .openFileDescriptor(updateFilePath, "r")) { mService.installUpdateFromFile( - admin, fileDescriptor, new StartInstallingUpdateCallback.Stub() { + admin, mContext.getPackageName(), fileDescriptor, + new StartInstallingUpdateCallback.Stub() { @Override public void onStartInstallingUpdateError( int errorCode, String errorMessage) { @@ -15691,7 +15733,7 @@ public class DevicePolicyManager { * @hide */ @TestApi - @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) + @RequiresPermission(MANAGE_DEVICE_ADMINS) public void setNextOperationSafety(@DevicePolicyOperation int operation, @OperationSafetyReason int reason) { if (mService != null) { @@ -16007,20 +16049,21 @@ public class DevicePolicyManager { } /** - * Called by device owner or profile owner of an organization-owned managed profile to - * enable or disable USB data signaling for the device. When disabled, USB data connections - * (except from charging functions) are prohibited. + * Called by a device owner, profile owner of an organization-owned managed profile, or holder + * of the {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING} + * permission to enable or disable USB data signaling for the device. When disabled, USB data + * connections (except from charging functions) are prohibited. * *

This API is not supported on all devices, the caller should call * {@link #canUsbDataSignalingBeDisabled()} to check whether enabling or disabling USB data * signaling is supported on the device. * * @param enabled whether USB data signaling should be enabled or not. - * @throws SecurityException if the caller is not a device owner or a profile owner on - * an organization-owned managed profile. + * @throws SecurityException if the caller is not permitted to set this policy * @throws IllegalStateException if disabling USB data signaling is not supported or * if USB data signaling fails to be enabled/disabled. */ + @RequiresPermission(value = MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING, conditional = true) public void setUsbDataSignalingEnabled(boolean enabled) { throwIfParentInstance("setUsbDataSignalingEnabled"); if (mService != null) { @@ -16114,7 +16157,7 @@ public class DevicePolicyManager { * @hide */ @TestApi - @RequiresPermission(value = android.Manifest.permission.MANAGE_DEVICE_ADMINS) + @RequiresPermission(value = MANAGE_DEVICE_ADMINS) public @NonNull Set getPolicyExemptApps() { if (mService == null) return Collections.emptySet(); @@ -16155,7 +16198,8 @@ public class DevicePolicyManager { } /** - * Called by device owner or profile owner of an organization-owned managed profile to + * Called by a device owner, profile owner of an organization-owned managed profile, or holder + * of the {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_WIFI} permission to * specify the minimum security level required for Wi-Fi networks. * The device may not connect to networks that do not meet the minimum security level. * If the current network does not meet the minimum security level set, it will be disconnected. @@ -16167,14 +16211,14 @@ public class DevicePolicyManager { * {@link #WIFI_SECURITY_ENTERPRISE_192} * * @param level minimum security level - * @throws SecurityException if the caller is not a device owner or a profile owner on - * an organization-owned managed profile. + * @throws SecurityException if the caller is not permitted to set this policy */ + @RequiresPermission(value = MANAGE_DEVICE_POLICY_WIFI, conditional = true) public void setMinimumRequiredWifiSecurityLevel(@WifiSecurity int level) { throwIfParentInstance("setMinimumRequiredWifiSecurityLevel"); if (mService != null) { try { - mService.setMinimumRequiredWifiSecurityLevel(level); + mService.setMinimumRequiredWifiSecurityLevel(mContext.getPackageName(), level); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -16199,23 +16243,24 @@ public class DevicePolicyManager { } /** - * Called by device owner or profile owner of an organization-owned managed profile to + * Called by device owner, profile owner of an organization-owned managed profile, or holder of + * the {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_WIFI} permission to * specify the Wi-Fi SSID policy ({@link WifiSsidPolicy}). * Wi-Fi SSID policy specifies the SSID restriction the network must satisfy * in order to be eligible for a connection. Providing a null policy results in the * deactivation of the SSID restriction * * @param policy Wi-Fi SSID policy - * @throws SecurityException if the caller is not a device owner or a profile owner on - * an organization-owned managed profile. + * @throws SecurityException if the caller is not permitted to manage wifi policy */ + @RequiresPermission(value = MANAGE_DEVICE_POLICY_WIFI, conditional = true) public void setWifiSsidPolicy(@Nullable WifiSsidPolicy policy) { throwIfParentInstance("setWifiSsidPolicy"); if (mService == null) { return; } try { - mService.setWifiSsidPolicy(policy); + mService.setWifiSsidPolicy(mContext.getPackageName(), policy); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -16227,9 +16272,9 @@ public class DevicePolicyManager { * If the policy has not been set, it will return NULL. * * @see #setWifiSsidPolicy(WifiSsidPolicy) - * @throws SecurityException if the caller is not a device owner or a profile owner on - * an organization-owned managed profile. + * @throws SecurityException if the caller is not permitted to manage wifi policy */ + @RequiresPermission(value = MANAGE_DEVICE_POLICY_WIFI, conditional = true) @Nullable public WifiSsidPolicy getWifiSsidPolicy() { throwIfParentInstance("getWifiSsidPolicy"); diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 132d616a94991..435673568c9f2 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -107,7 +107,8 @@ interface IDevicePolicyManager { int getCurrentFailedPasswordAttempts(int userHandle, boolean parent); int getProfileWithMinimumFailedPasswordsForWipe(int userHandle, boolean parent); - void setMaximumFailedPasswordsForWipe(in ComponentName admin, int num, boolean parent); + void setMaximumFailedPasswordsForWipe( + in ComponentName admin, String callerPackageName, int num, boolean parent); int getMaximumFailedPasswordsForWipe(in ComponentName admin, int userHandle, boolean parent); boolean resetPassword(String password, int flags); @@ -144,7 +145,8 @@ interface IDevicePolicyManager { void setCameraDisabled(in ComponentName who, String callerPackageName, boolean disabled, boolean parent); boolean getCameraDisabled(in ComponentName who, int userHandle, boolean parent); - void setScreenCaptureDisabled(in ComponentName who, boolean disabled, boolean parent); + void setScreenCaptureDisabled( + in ComponentName who, String callerPackageName, boolean disabled, boolean parent); boolean getScreenCaptureDisabled(in ComponentName who, int userHandle, boolean parent); void setNearbyNotificationStreamingPolicy(int policy); @@ -376,7 +378,7 @@ interface IDevicePolicyManager { void setUserIcon(in ComponentName admin, in Bitmap icon); - void setSystemUpdatePolicy(in ComponentName who, in SystemUpdatePolicy policy); + void setSystemUpdatePolicy(in ComponentName who, String callerPackageName, in SystemUpdatePolicy policy); SystemUpdatePolicy getSystemUpdatePolicy(); void clearSystemUpdatePolicyFreezePeriodRecord(); @@ -398,7 +400,7 @@ interface IDevicePolicyManager { void setKeepUninstalledPackages(in ComponentName admin, in String callerPackage, in List packageList); List getKeepUninstalledPackages(in ComponentName admin, in String callerPackage); boolean isManagedProfile(in ComponentName admin); - String getWifiMacAddress(in ComponentName admin); + String getWifiMacAddress(in ComponentName admin, String callerPackageName); void reboot(in ComponentName admin); void setShortSupportMessage(in ComponentName admin, in CharSequence message); @@ -502,7 +504,7 @@ interface IDevicePolicyManager { void setProfileOwnerOnOrganizationOwnedDevice(in ComponentName who, int userId, boolean isProfileOwnerOnOrganizationOwnedDevice); - void installUpdateFromFile(in ComponentName admin, in ParcelFileDescriptor updateFileDescriptor, in StartInstallingUpdateCallback listener); + void installUpdateFromFile(in ComponentName admin, String callerPackageName, in ParcelFileDescriptor updateFileDescriptor, in StartInstallingUpdateCallback listener); void setCrossProfileCalendarPackages(in ComponentName admin, in List packageNames); List getCrossProfileCalendarPackages(in ComponentName admin); @@ -565,10 +567,10 @@ interface IDevicePolicyManager { boolean isUsbDataSignalingEnabledForUser(int userId); boolean canUsbDataSignalingBeDisabled(); - void setMinimumRequiredWifiSecurityLevel(int level); + void setMinimumRequiredWifiSecurityLevel(String callerPackageName, int level); int getMinimumRequiredWifiSecurityLevel(); - void setWifiSsidPolicy(in WifiSsidPolicy policy); + void setWifiSsidPolicy(String callerPackageName, in WifiSsidPolicy policy); WifiSsidPolicy getWifiSsidPolicy(); List listForegroundAffiliatedUsers(); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index dd9791b332d24..c976bd2fff167 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -23,6 +23,13 @@ import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SCREEN_CAPTURE; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIPE_DATA; import static android.Manifest.permission.QUERY_ADMIN_POLICY; import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY; import static android.Manifest.permission.SET_TIME; @@ -5157,27 +5164,43 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public void setMaximumFailedPasswordsForWipe(ComponentName who, int num, boolean parent) { + public void setMaximumFailedPasswordsForWipe( + ComponentName who, String callerPackageName, int num, boolean parent) { if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return; } - Objects.requireNonNull(who, "ComponentName is null"); - final int userId = mInjector.userHandleGetCallingUserId(); + + if (!isPermissionCheckFlagEnabled()) { + Objects.requireNonNull(who, "ComponentName is null"); + } + + CallerIdentity caller = getCallerIdentity(who, callerPackageName); + + int userId = mInjector.userHandleGetCallingUserId(); + int affectedUserId = parent ? getProfileParentId(userId) : userId; + synchronized (getLockObject()) { - // This API can only be called by an active device admin, - // so try to retrieve it to check that the caller is one. - getActiveAdminForCallerLocked( - who, DeviceAdminInfo.USES_POLICY_WIPE_DATA, parent); - ActiveAdmin ap = getActiveAdminForCallerLocked( - who, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, parent); + ActiveAdmin ap; + if (isPermissionCheckFlagEnabled()) { + ap = enforcePermissionAndGetEnforcingAdmin( + who, MANAGE_DEVICE_POLICY_WIPE_DATA, + caller.getPackageName(), affectedUserId).getActiveAdmin(); + } else { + // This API can only be called by an active device admin, + // so try to retrieve it to check that the caller is one. + getActiveAdminForCallerLocked( + who, DeviceAdminInfo.USES_POLICY_WIPE_DATA, parent); + ap = getActiveAdminForCallerLocked( + who, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, parent); + } + if (ap.maximumFailedPasswordsForWipe != num) { ap.maximumFailedPasswordsForWipe = num; saveSettingsLocked(userId); } } if (SecurityLog.isLoggingEnabled()) { - final int affectedUserId = parent ? getProfileParentId(userId) : userId; - SecurityLog.writeEvent(SecurityLog.TAG_MAX_PASSWORD_ATTEMPTS_SET, who.getPackageName(), + SecurityLog.writeEvent(SecurityLog.TAG_MAX_PASSWORD_ATTEMPTS_SET, callerPackageName, userId, affectedUserId, num); } } @@ -8042,23 +8065,37 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * Set whether the screen capture is disabled for the user managed by the specified admin. */ @Override - public void setScreenCaptureDisabled(ComponentName who, boolean disabled, boolean parent) { + public void setScreenCaptureDisabled( + ComponentName who, String callerPackage, boolean disabled, boolean parent) { if (!mHasFeature) { return; } - Objects.requireNonNull(who, "ComponentName is null"); - final CallerIdentity caller = getCallerIdentity(who); - if (parent) { - Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller)); - } else { - Preconditions.checkCallAuthorization(isProfileOwner(caller) - || isDeviceOwner(caller)); + CallerIdentity caller = getCallerIdentity(who, callerPackage); + if (!isPermissionCheckFlagEnabled()) { + Objects.requireNonNull(who, "ComponentName is null"); + if (parent) { + Preconditions.checkCallAuthorization( + isProfileOwnerOfOrganizationOwnedDevice(caller)); + } else { + Preconditions.checkCallAuthorization(isProfileOwner(caller) + || isDeviceOwner(caller)); + } } synchronized (getLockObject()) { - ActiveAdmin ap = getParentOfAdminIfRequired( - getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), parent); + ActiveAdmin ap; + if (isPermissionCheckFlagEnabled()) { + int callerUserId = Binder.getCallingUserHandle().getIdentifier(); + int targetUserId = parent ? getProfileParentId(callerUserId) : callerUserId; + ap = enforcePermissionAndGetEnforcingAdmin( + who, MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, caller.getPackageName(), + targetUserId).getActiveAdmin(); + } else { + ap = getParentOfAdminIfRequired( + getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), parent); + } + if (ap.disableScreenCapture != disabled) { ap.disableScreenCapture = disabled; saveSettingsLocked(caller.getUserId()); @@ -8067,7 +8104,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_SCREEN_CAPTURE_DISABLED) - .setAdmin(caller.getComponentName()) + .setAdmin(caller.getPackageName()) .setBoolean(disabled) .write(); } @@ -9915,6 +9952,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return UserHandle.USER_NULL; } + private @UserIdInt int getManagedProfileUserId() { + for (UserInfo ui : mUserManagerInternal.getUserInfos()) { + if (ui.isManagedProfile()) { + return ui.id; + } + } + return UserHandle.USER_NULL; + } + /** * This API is cached: invalidate with invalidateBinderCaches(). */ @@ -14909,7 +14955,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public void setSystemUpdatePolicy(ComponentName who, SystemUpdatePolicy policy) { + public void setSystemUpdatePolicy( + ComponentName who, String callerPackageName, SystemUpdatePolicy policy) { if (policy != null) { // throws exception if policy type is invalid policy.validateType(); @@ -14920,11 +14967,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { policy.validateAgainstPreviousFreezePeriod(record.first, record.second, LocalDate.now()); } - final CallerIdentity caller = getCallerIdentity(who); + final CallerIdentity caller = getCallerIdentity(who, callerPackageName); synchronized (getLockObject()) { - Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller) - || isDefaultDeviceOwner(caller)); + if (isPermissionCheckFlagEnabled()) { + enforcePermission(MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, UserHandle.USER_ALL); + } else { + Preconditions.checkCallAuthorization( + isProfileOwnerOfOrganizationOwnedDevice(caller) + || isDefaultDeviceOwner(caller)); + } + checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_SYSTEM_UPDATE_POLICY); if (policy == null) { @@ -14939,7 +14992,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { new Intent(ACTION_SYSTEM_UPDATE_POLICY_CHANGED), UserHandle.SYSTEM)); DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_SYSTEM_UPDATE_POLICY) - .setAdmin(who) + .setAdmin(caller.getPackageName()) .setInt(policy != null ? policy.getPolicyType() : 0) .write(); } @@ -15618,12 +15671,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public String getWifiMacAddress(ComponentName admin) { - Objects.requireNonNull(admin, "ComponentName is null"); + public String getWifiMacAddress(ComponentName admin, String callerPackageName) { +// if (!isPermissionCheckFlagEnabled()) { + Objects.requireNonNull(admin, "ComponentName is null"); +// } - final CallerIdentity caller = getCallerIdentity(admin); - Preconditions.checkCallAuthorization( - isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller)); + final CallerIdentity caller = getCallerIdentity(admin, callerPackageName); +// if (isPermissionCheckFlagEnabled()) { +// enforcePermission(MANAGE_DEVICE_POLICY_WIFI, UserHandle.USER_ALL); +// } else { + Preconditions.checkCallAuthorization( + isDefaultDeviceOwner(caller) + || isProfileOwnerOfOrganizationOwnedDevice(caller)); +// } return mInjector.binderWithCleanCallingIdentity(() -> { String[] macAddresses = mInjector.getWifiManager().getFactoryMacAddresses(); @@ -15632,7 +15692,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } DevicePolicyEventLogger .createEvent(DevicePolicyEnums.GET_WIFI_MAC_ADDRESS) - .setAdmin(caller.getComponentName()) + .setAdmin(caller.getPackageName()) .write(); return macAddresses.length > 0 ? macAddresses[0] : null; }); @@ -16288,6 +16348,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return UserHandle.USER_ALL; } } + // TODO: Add check for permission-based return getOrganizationOwnedProfileUserId(); } @@ -16300,14 +16361,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { final CallerIdentity caller = getCallerIdentity(admin, packageName); synchronized (getLockObject()) { - if (admin != null) { - Preconditions.checkCallAuthorization( - isProfileOwnerOfOrganizationOwnedDevice(caller) - || isDefaultDeviceOwner(caller)); + if (isPermissionCheckFlagEnabled()) { + // TODO: add support for DELEGATION_SECURITY_LOGGING + enforcePermission(MANAGE_DEVICE_POLICY_SECURITY_LOGGING, UserHandle.USER_ALL); } else { - // A delegate app passes a null admin component, which is expected - Preconditions.checkCallAuthorization( - isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING)); + if (admin != null) { + Preconditions.checkCallAuthorization( + isProfileOwnerOfOrganizationOwnedDevice(caller) + || isDefaultDeviceOwner(caller)); + } else { + // A delegate app passes a null admin component, which is expected + Preconditions.checkCallAuthorization( + isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING)); + } } if (enabled == mInjector.securityLogGetLoggingEnabledProperty()) { @@ -16323,7 +16389,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_SECURITY_LOGGING_ENABLED) - .setAdmin(admin) + .setAdmin(caller.getPackageName()) .setBoolean(enabled) .write(); } @@ -16337,14 +16403,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { synchronized (getLockObject()) { if (!isSystemUid(getCallerIdentity())) { final CallerIdentity caller = getCallerIdentity(admin, packageName); - if (admin != null) { - Preconditions.checkCallAuthorization( - isProfileOwnerOfOrganizationOwnedDevice(caller) - || isDefaultDeviceOwner(caller)); + if (isPermissionCheckFlagEnabled()) { + enforcePermission(MANAGE_DEVICE_POLICY_SECURITY_LOGGING, UserHandle.USER_ALL); } else { - // A delegate app passes a null admin component, which is expected - Preconditions.checkCallAuthorization( - isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING)); + if (admin != null) { + Preconditions.checkCallAuthorization( + isProfileOwnerOfOrganizationOwnedDevice(caller) + || isDefaultDeviceOwner(caller)); + } else { + // A delegate app passes a null admin component, which is expected + Preconditions.checkCallAuthorization( + isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING)); + } } } return mInjector.securityLogGetLoggingEnabledProperty(); @@ -16370,22 +16440,27 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } final CallerIdentity caller = getCallerIdentity(admin, packageName); - if (admin != null) { - Preconditions.checkCallAuthorization( - isProfileOwnerOfOrganizationOwnedDevice(caller) - || isDefaultDeviceOwner(caller)); + if (isPermissionCheckFlagEnabled()) { + // TODO: Restore the "affiliated users" check + enforcePermission(MANAGE_DEVICE_POLICY_SECURITY_LOGGING, UserHandle.USER_ALL); } else { - // A delegate app passes a null admin component, which is expected - Preconditions.checkCallAuthorization( - isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING)); - } + if (admin != null) { + Preconditions.checkCallAuthorization( + isProfileOwnerOfOrganizationOwnedDevice(caller) + || isDefaultDeviceOwner(caller)); + } else { + // A delegate app passes a null admin component, which is expected + Preconditions.checkCallAuthorization( + isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING)); + } - Preconditions.checkCallAuthorization(isOrganizationOwnedDeviceWithManagedProfile() - || areAllUsersAffiliatedWithDeviceLocked()); + Preconditions.checkCallAuthorization(isOrganizationOwnedDeviceWithManagedProfile() + || areAllUsersAffiliatedWithDeviceLocked()); + } DevicePolicyEventLogger .createEvent(DevicePolicyEnums.RETRIEVE_PRE_REBOOT_SECURITY_LOGS) - .setAdmin(caller.getComponentName()) + .setAdmin(caller.getPackageName()) .write(); if (!mContext.getResources().getBoolean(R.bool.config_supportPreRebootSecurityLogs) @@ -16416,17 +16491,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } final CallerIdentity caller = getCallerIdentity(admin, packageName); - if (admin != null) { - Preconditions.checkCallAuthorization( - isProfileOwnerOfOrganizationOwnedDevice(caller) - || isDefaultDeviceOwner(caller)); + if (isPermissionCheckFlagEnabled()) { + // TODO: Restore the "affiliated users" check + enforcePermission(MANAGE_DEVICE_POLICY_SECURITY_LOGGING, UserHandle.USER_ALL); } else { - // A delegate app passes a null admin component, which is expected - Preconditions.checkCallAuthorization( - isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING)); + if (admin != null) { + Preconditions.checkCallAuthorization( + isProfileOwnerOfOrganizationOwnedDevice(caller) + || isDefaultDeviceOwner(caller)); + } else { + // A delegate app passes a null admin component, which is expected + Preconditions.checkCallAuthorization( + isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING)); + } + Preconditions.checkCallAuthorization(isOrganizationOwnedDeviceWithManagedProfile() + || areAllUsersAffiliatedWithDeviceLocked()); } - Preconditions.checkCallAuthorization(isOrganizationOwnedDeviceWithManagedProfile() - || areAllUsersAffiliatedWithDeviceLocked()); if (!mInjector.securityLogGetLoggingEnabledProperty()) { return null; @@ -16437,7 +16517,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { List logs = mSecurityLogMonitor.retrieveLogs(); DevicePolicyEventLogger .createEvent(DevicePolicyEnums.RETRIEVE_SECURITY_LOGS) - .setAdmin(caller.getComponentName()) + .setAdmin(caller.getPackageName()) .write(); return logs != null ? new ParceledListSlice(logs) : null; } @@ -17004,9 +17084,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mNetworkLogger.pause(); } } + // TODO: We need to also enable this when someone is managing using permission if (!isOrganizationOwnedDeviceWithManagedProfile()) { - Slogf.i(LOG_TAG, "Not org-owned managed profile device, security logging will be " - + "paused if enabled."); + Slogf.i(LOG_TAG, + "Not org-owned managed profile device, security logging will be " + + "paused if enabled."); mSecurityLogMonitor.pause(); } } @@ -18104,18 +18186,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public void installUpdateFromFile(ComponentName admin, + public void installUpdateFromFile(ComponentName admin, String callerPackageName, ParcelFileDescriptor updateFileDescriptor, StartInstallingUpdateCallback callback) { - Objects.requireNonNull(admin, "ComponentName is null"); + if (!isPermissionCheckFlagEnabled()) { + Objects.requireNonNull(admin, "ComponentName is null"); + } - final CallerIdentity caller = getCallerIdentity(admin); - Preconditions.checkCallAuthorization( - isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller)); + final CallerIdentity caller = getCallerIdentity(admin, callerPackageName); + if (isPermissionCheckFlagEnabled()) { + enforcePermission(MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, UserHandle.USER_ALL); + } else { + Preconditions.checkCallAuthorization( + isDefaultDeviceOwner(caller) + || isProfileOwnerOfOrganizationOwnedDevice(caller)); + } checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_INSTALL_SYSTEM_UPDATE); DevicePolicyEventLogger .createEvent(DevicePolicyEnums.INSTALL_SYSTEM_UPDATE) - .setAdmin(caller.getComponentName()) + .setAdmin(caller.getPackageName()) .setBoolean(isDeviceAB()) .write(); @@ -20164,15 +20253,27 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { public void setUsbDataSignalingEnabled(String packageName, boolean enabled) { Objects.requireNonNull(packageName, "Admin package name must be provided"); final CallerIdentity caller = getCallerIdentity(packageName); - Preconditions.checkCallAuthorization( - isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller), - "USB data signaling can only be controlled by a device owner or " - + "a profile owner on an organization-owned device."); - Preconditions.checkState(canUsbDataSignalingBeDisabled(), - "USB data signaling cannot be disabled."); + if (!isPermissionCheckFlagEnabled()) { + Preconditions.checkCallAuthorization( + isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller), + "USB data signaling can only be controlled by a device owner or " + + "a profile owner on an organization-owned device."); + Preconditions.checkState(canUsbDataSignalingBeDisabled(), + "USB data signaling cannot be disabled."); + } + synchronized (getLockObject()) { - final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()); + ActiveAdmin admin; + if (isPermissionCheckFlagEnabled()) { + admin = enforcePermissionAndGetEnforcingAdmin( + /* admin= */ null, MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING, + caller.getPackageName(), + caller.getUserId()).getActiveAdmin(); + } else { + admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()); + } + if (admin.mUsbDataSignalingEnabled != enabled) { admin.mUsbDataSignalingEnabled = enabled; saveSettingsLocked(caller.getUserId()); @@ -20261,16 +20362,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public void setMinimumRequiredWifiSecurityLevel(int level) { + public void setMinimumRequiredWifiSecurityLevel(String callerPackageName, int level) { final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization( - isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller), - "Wi-Fi minimum security level can only be controlled by a device owner or " - + "a profile owner on an organization-owned device."); + if (!isPermissionCheckFlagEnabled()) { + Preconditions.checkCallAuthorization( + isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller), + "Wi-Fi minimum security level can only be controlled by a device owner or " + + "a profile owner on an organization-owned device."); + } boolean valueChanged = false; synchronized (getLockObject()) { - final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()); + ActiveAdmin admin; + if (isPermissionCheckFlagEnabled()) { + admin = enforcePermissionAndGetEnforcingAdmin(/* admin= */ null, + MANAGE_DEVICE_POLICY_WIFI, caller.getPackageName(), caller.getUserId()) + .getActiveAdmin(); + } else { + admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()); + } if (admin.mWifiMinimumSecurityLevel != level) { admin.mWifiMinimumSecurityLevel = level; saveSettingsLocked(caller.getUserId()); @@ -20299,12 +20409,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public WifiSsidPolicy getWifiSsidPolicy() { final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization( - isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller) - || canQueryAdminPolicy(caller), - "SSID policy can only be retrieved by a device owner or " - + "a profile owner on an organization-owned device or " - + "an app with the QUERY_ADMIN_POLICY permission."); + if (isPermissionCheckFlagEnabled()) { + enforcePermission(MANAGE_DEVICE_POLICY_WIFI, caller.getUserId()); + } else { + Preconditions.checkCallAuthorization( + isDefaultDeviceOwner(caller) + || isProfileOwnerOfOrganizationOwnedDevice(caller) + || canQueryAdminPolicy(caller), + "SSID policy can only be retrieved by a device owner or " + + "a profile owner on an organization-owned device or " + + "an app with the QUERY_ADMIN_POLICY permission."); + } synchronized (getLockObject()) { ActiveAdmin admin; // TODO(b/261999445): remove @@ -20319,16 +20434,27 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public void setWifiSsidPolicy(WifiSsidPolicy policy) { - final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization( - isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller), - "SSID denylist can only be controlled by a device owner or " - + "a profile owner on an organization-owned device."); + public void setWifiSsidPolicy(String callerPackageName, WifiSsidPolicy policy) { + final CallerIdentity caller = getCallerIdentity(callerPackageName); + + if (!isPermissionCheckFlagEnabled()) { + Preconditions.checkCallAuthorization( + isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller), + "SSID denylist can only be controlled by a device owner or " + + "a profile owner on an organization-owned device."); + } boolean changed = false; synchronized (getLockObject()) { - final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()); + ActiveAdmin admin; + if (isPermissionCheckFlagEnabled()) { + admin = enforcePermissionAndGetEnforcingAdmin( + /* admin= */ null, MANAGE_DEVICE_POLICY_WIFI, + caller.getPackageName(), + caller.getUserId()).getActiveAdmin(); + } else { + admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()); + } if (!Objects.equals(policy, admin.mWifiSsidPolicy)) { admin.mWifiSsidPolicy = policy; changed = true; @@ -20704,7 +20830,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL, SET_TIME, SET_TIME_ZONE, - MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY); + MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY, + MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, + MANAGE_DEVICE_POLICY_WIFI, + MANAGE_DEVICE_POLICY_WIPE_DATA, + MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, + MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, + MANAGE_DEVICE_POLICY_SECURITY_LOGGING, + MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING); private static final List FINANCED_DEVICE_OWNER_PERMISSIONS = List.of( MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL, MANAGE_DEVICE_POLICY_ACROSS_USERS, @@ -20716,13 +20849,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL, SET_TIME, SET_TIME_ZONE, - MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY); + MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY, + MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, + MANAGE_DEVICE_POLICY_WIFI, + MANAGE_DEVICE_POLICY_WIPE_DATA, + MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, + MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, + MANAGE_DEVICE_POLICY_SECURITY_LOGGING, + MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING); private static final List PROFILE_OWNER_ON_USER_0_PERMISSIONS = List.of( SET_TIME, - SET_TIME_ZONE); + SET_TIME_ZONE, + MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, + MANAGE_DEVICE_POLICY_WIPE_DATA, + MANAGE_DEVICE_POLICY_SCREEN_CAPTURE); private static final List PROFILE_OWNER_PERMISSIONS = List.of( MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL, - MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY); + MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY, + MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, + MANAGE_DEVICE_POLICY_WIPE_DATA, + MANAGE_DEVICE_POLICY_SCREEN_CAPTURE); private static final HashMap> DPC_PERMISSIONS = new HashMap<>(); { @@ -20735,6 +20881,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } //TODO(b/254253251) Fill this map in as new permissions are added for policies. + // TODO: Add USES_POLICY_WIPE_DATA -> MANAGE_DEVICE_POLICY_WIPE_DATA private static final HashMap ACTIVE_ADMIN_POLICIES = new HashMap<>(); private static final HashMap CROSS_USER_PERMISSIONS = @@ -20743,10 +20890,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // Time and Timezone is intrinsically global so there is no cross-user permission. CROSS_USER_PERMISSIONS.put(SET_TIME, null); CROSS_USER_PERMISSIONS.put(SET_TIME_ZONE, null); + // system updates are intrinsically global so there is no cross-user permission + CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, null); + // security logs are intrinsically global so there is no cross-user permission + CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_SECURITY_LOGGING, null); + // usb signalling is intrinsically global so there is no cross-user permission + CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING, null); // Organisation identity policy will involve data of other organisations on the device and // therefore the FULL cross-user permission is required. CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY, MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL); + CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_WIFI, + MANAGE_DEVICE_POLICY_ACROSS_USERS); + CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_WIPE_DATA, + MANAGE_DEVICE_POLICY_ACROSS_USERS); + CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, + MANAGE_DEVICE_POLICY_ACROSS_USERS); } /** From 96c43ae80b7f1913fd19da8c636fbc226e7442d2 Mon Sep 17 00:00:00 2001 From: Jonathan Scott Date: Mon, 13 Feb 2023 17:09:28 +0000 Subject: [PATCH 2/3] Add permissions to DPM 2. Test: btest a.d.c.MtePolicyTest Test: btest a.d.c.PasswordTest Test: btest a.d.c.PasswordComplexityTest Test: btest a.d.c.ApplicationHiddenTest Test: btest a.d.c.WifiTest Bug: 234609037 Change-Id: I090ee7eee6e1c7a1e746232a961e37ec55ae942b --- core/api/current.txt | 26 +- .../app/admin/DevicePolicyManager.java | 147 +++++---- .../app/admin/IDevicePolicyManager.aidl | 12 +- .../DevicePolicyManagerService.java | 286 +++++++++++++----- 4 files changed, 320 insertions(+), 151 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index cba32356be340..d7460b326160e 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -7818,7 +7818,7 @@ package android.app.admin { method @Deprecated public boolean getCrossProfileContactsSearchDisabled(@NonNull android.content.ComponentName); method @NonNull public java.util.Set getCrossProfilePackages(@NonNull android.content.ComponentName); method @NonNull public java.util.List getCrossProfileWidgetProviders(@NonNull android.content.ComponentName); - method public int getCurrentFailedPasswordAttempts(); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional=true) public int getCurrentFailedPasswordAttempts(); method @Nullable public java.util.List getDelegatePackages(@NonNull android.content.ComponentName, @NonNull String); method @NonNull public java.util.List getDelegatedScopes(@Nullable android.content.ComponentName, @NonNull String); method public CharSequence getDeviceOwnerLockScreenInfo(); @@ -7843,14 +7843,14 @@ package android.app.admin { method public long getMaximumTimeToLock(@Nullable android.content.ComponentName); method @NonNull public java.util.List getMeteredDataDisabledPackages(@NonNull android.content.ComponentName); method public int getMinimumRequiredWifiSecurityLevel(); - method public int getMtePolicy(); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_MTE, conditional=true) public int getMtePolicy(); method @RequiresPermission(value=android.Manifest.permission.READ_NEARBY_STREAMING_POLICY, conditional=true) public int getNearbyAppStreamingPolicy(); method @RequiresPermission(value=android.Manifest.permission.READ_NEARBY_STREAMING_POLICY, conditional=true) public int getNearbyNotificationStreamingPolicy(); method @Deprecated @ColorInt public int getOrganizationColor(@NonNull android.content.ComponentName); method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY) public CharSequence getOrganizationName(@Nullable android.content.ComponentName); method public java.util.List getOverrideApns(@NonNull android.content.ComponentName); method @NonNull public android.app.admin.DevicePolicyManager getParentProfileInstance(@NonNull android.content.ComponentName); - method @RequiresPermission(android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY) public int getPasswordComplexity(); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY}, conditional=true) public int getPasswordComplexity(); method public long getPasswordExpiration(@Nullable android.content.ComponentName); method public long getPasswordExpirationTimeout(@Nullable android.content.ComponentName); method public int getPasswordHistoryLength(@Nullable android.content.ComponentName); @@ -7871,7 +7871,7 @@ package android.app.admin { method @Nullable public java.util.List getPermittedInputMethods(@NonNull android.content.ComponentName); method public int getPersonalAppsSuspendedReasons(@NonNull android.content.ComponentName); method @NonNull public java.util.List getPreferentialNetworkServiceConfigs(); - method public int getRequiredPasswordComplexity(); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional=true) public int getRequiredPasswordComplexity(); method public long getRequiredStrongAuthTimeout(@Nullable android.content.ComponentName); method @NonNull public android.app.admin.DevicePolicyResourcesManager getResources(); method public boolean getScreenCaptureDisabled(@Nullable android.content.ComponentName); @@ -7893,19 +7893,19 @@ package android.app.admin { method public boolean hasCaCertInstalled(@Nullable android.content.ComponentName, byte[]); method public boolean hasGrantedPolicy(@NonNull android.content.ComponentName, int); method public boolean hasKeyPair(@NonNull String); - method public boolean hasLockdownAdminConfiguredNetworks(@NonNull android.content.ComponentName); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI, conditional=true) public boolean hasLockdownAdminConfiguredNetworks(@Nullable android.content.ComponentName); method public boolean installCaCert(@Nullable android.content.ComponentName, byte[]); method public boolean installExistingPackage(@NonNull android.content.ComponentName, String); method public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate, @NonNull String); method public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate[], @NonNull String, boolean); method public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate[], @NonNull String, int); method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, conditional=true) public void installSystemUpdate(@Nullable android.content.ComponentName, @NonNull android.net.Uri, @NonNull java.util.concurrent.Executor, @NonNull android.app.admin.DevicePolicyManager.InstallSystemUpdateCallback); - method public boolean isActivePasswordSufficient(); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional=true) public boolean isActivePasswordSufficient(); method public boolean isActivePasswordSufficientForDeviceRequirement(); 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 @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_PACKAGE_STATE, conditional=true) public boolean isApplicationHidden(@Nullable android.content.ComponentName, String); method public boolean isBackupServiceEnabled(@NonNull android.content.ComponentName); method @Deprecated public boolean isCallerApplicationRestrictionsManagingPackage(); method public boolean isCommonCriteriaModeEnabled(@Nullable android.content.ComponentName); @@ -7955,7 +7955,7 @@ package android.app.admin { method public void setAffiliationIds(@NonNull android.content.ComponentName, @NonNull java.util.Set); method public void setAlwaysOnVpnPackage(@NonNull android.content.ComponentName, @Nullable String, boolean) throws android.content.pm.PackageManager.NameNotFoundException; method public void setAlwaysOnVpnPackage(@NonNull android.content.ComponentName, @Nullable String, boolean, @Nullable java.util.Set) throws android.content.pm.PackageManager.NameNotFoundException; - method public boolean setApplicationHidden(@NonNull android.content.ComponentName, String, boolean); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_PACKAGE_STATE, conditional=true) public boolean setApplicationHidden(@Nullable 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; method @RequiresPermission(value=android.Manifest.permission.SET_TIME, conditional=true) public void setAutoTimeEnabled(@NonNull android.content.ComponentName, boolean); @@ -7966,7 +7966,7 @@ package android.app.admin { method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA, conditional=true) public void setCameraDisabled(@Nullable android.content.ComponentName, boolean); method @Deprecated public void setCertInstallerPackage(@NonNull android.content.ComponentName, @Nullable String) throws java.lang.SecurityException; method public void setCommonCriteriaModeEnabled(@NonNull android.content.ComponentName, boolean); - method public void setConfiguredNetworksLockdownState(@NonNull android.content.ComponentName, boolean); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI, conditional=true) public void setConfiguredNetworksLockdownState(@Nullable android.content.ComponentName, boolean); method public void setCredentialManagerPolicy(@Nullable android.app.admin.PackagePolicy); method @Deprecated public void setCrossProfileCalendarPackages(@NonNull android.content.ComponentName, @Nullable java.util.Set); method @Deprecated public void setCrossProfileCallerIdDisabled(@NonNull android.content.ComponentName, boolean); @@ -7998,7 +7998,7 @@ package android.app.admin { method public void setMaximumTimeToLock(@NonNull android.content.ComponentName, long); method @NonNull public java.util.List setMeteredDataDisabledPackages(@NonNull android.content.ComponentName, @NonNull java.util.List); method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI, conditional=true) public void setMinimumRequiredWifiSecurityLevel(int); - method public void setMtePolicy(int); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_MTE, conditional=true) public void setMtePolicy(int); method public void setNearbyAppStreamingPolicy(int); method public void setNearbyNotificationStreamingPolicy(int); method public void setNetworkLoggingEnabled(@Nullable android.content.ComponentName, boolean); @@ -8007,7 +8007,7 @@ package android.app.admin { method @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY) public void setOrganizationName(@Nullable android.content.ComponentName, @Nullable CharSequence); method public void setOverrideApnsEnabled(@NonNull android.content.ComponentName, boolean); method @NonNull public String[] setPackagesSuspended(@NonNull android.content.ComponentName, @NonNull String[], boolean); - method public void setPasswordExpirationTimeout(@NonNull android.content.ComponentName, long); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional=true) public void setPasswordExpirationTimeout(@Nullable android.content.ComponentName, long); method public void setPasswordHistoryLength(@NonNull android.content.ComponentName, int); method @Deprecated public void setPasswordMinimumLength(@NonNull android.content.ComponentName, int); method @Deprecated public void setPasswordMinimumLetters(@NonNull android.content.ComponentName, int); @@ -8028,8 +8028,8 @@ package android.app.admin { method public void setProfileEnabled(@NonNull android.content.ComponentName); method public void setProfileName(@NonNull android.content.ComponentName, String); method public void setRecommendedGlobalProxy(@NonNull android.content.ComponentName, @Nullable android.net.ProxyInfo); - method public void setRequiredPasswordComplexity(int); - method public void setRequiredStrongAuthTimeout(@NonNull android.content.ComponentName, long); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional=true) public void setRequiredPasswordComplexity(int); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional=true) public void setRequiredStrongAuthTimeout(@Nullable android.content.ComponentName, long); method public boolean setResetPasswordToken(android.content.ComponentName, byte[]); method public void setRestrictionsProvider(@NonNull android.content.ComponentName, @Nullable android.content.ComponentName); method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, conditional=true) public void setScreenCaptureDisabled(@Nullable android.content.ComponentName, boolean); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index c12e7ca08e9e5..d4d5aac23d7f2 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -20,7 +20,10 @@ import static android.Manifest.permission.INTERACT_ACROSS_USERS; import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA; import static android.Manifest.permission.MANAGE_DEVICE_ADMINS; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MTE; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_PACKAGE_STATE; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SCREEN_CAPTURE; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING; @@ -29,6 +32,7 @@ import static android.Manifest.permission.MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLI import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIPE_DATA; import static android.Manifest.permission.QUERY_ADMIN_POLICY; +import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY; import static android.Manifest.permission.SET_TIME; import static android.Manifest.permission.SET_TIME_ZONE; import static android.content.Intent.LOCAL_FLAG_FROM_SYSTEM; @@ -2226,7 +2230,7 @@ public class DevicePolicyManager { * *

If an invalid value is used, it will be treated as {@link #PASSWORD_COMPLEXITY_NONE}. */ - @RequiresPermission(android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY) + @RequiresPermission(REQUEST_PASSWORD_COMPLEXITY) public static final String EXTRA_PASSWORD_COMPLEXITY = "android.app.extra.PASSWORD_COMPLEXITY"; @@ -4000,7 +4004,8 @@ public class DevicePolicyManager { public static @interface MtePolicy {} /** - * Called by a device owner or profile owner of an organization-owned device to set the Memory + * Called by a device owner, profile owner of an organization-owned device, or holder of the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_MTE} permission to set the Memory * Tagging Extension (MTE) policy. MTE is a CPU extension that allows to protect against certain * classes of security problems at a small runtime performance cost overhead. * @@ -4009,16 +4014,16 @@ public class DevicePolicyManager { * *

The device needs to be rebooted to apply changes to the MTE policy. * - * @throws SecurityException if caller is not device owner or profile owner of org-owned device - * or if called on a parent instance + * @throws SecurityException if caller is not permitted to set Mte policy * @throws UnsupportedOperationException if the device does not support MTE * @param policy the MTE policy to be set */ + @RequiresPermission(value = MANAGE_DEVICE_POLICY_MTE, conditional = true) public void setMtePolicy(@MtePolicy int policy) { throwIfParentInstance("setMtePolicy"); if (mService != null) { try { - mService.setMtePolicy(policy); + mService.setMtePolicy(policy, mContext.getPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4026,21 +4031,22 @@ public class DevicePolicyManager { } /** - * Called by a device owner, a profile owner of an organization-owned device or the system to + * Called by a device owner, profile owner of an organization-owned device, or a holder of the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_MTE} permission to * get the Memory Tagging Extension (MTE) policy * * * Learn more about MTE * - * @throws SecurityException if caller is not device owner or profile owner of org-owned device - * or system uid, or if called on a parent instance + * @throws SecurityException if caller is not permitted to set Mte policy * @return the currently set MTE policy */ + @RequiresPermission(value = MANAGE_DEVICE_POLICY_MTE, conditional = true) public @MtePolicy int getMtePolicy() { throwIfParentInstance("setMtePolicy"); if (mService != null) { try { - return mService.getMtePolicy(); + return mService.getMtePolicy(mContext.getPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -5236,7 +5242,9 @@ public class DevicePolicyManager { } /** - * Called by a device admin to set the password expiration timeout. Calling this method will + * Called by a device admin or holder of the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS} permission to set + * the password expiration timeout. Calling this method will * restart the countdown for password expiration for the given admin, as will changing the * device password (for all admins). *

@@ -5249,7 +5257,7 @@ public class DevicePolicyManager { * On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the * password expiration is always disabled. *

- * The calling device admin must have requested + * A calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to be able to call this method; if it has * not, a security exception will be thrown. *

@@ -5260,17 +5268,23 @@ public class DevicePolicyManager { * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent * profile. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the + * caller is not a device admin * @param timeout The limit (in ms) that a password can remain in effect. A value of 0 means * there is no restriction (unlimited). * @throws SecurityException if {@code admin} is not an active administrator or {@code admin} - * does not use {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} + * does not use {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} and the caller + * does not hold the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS} + * permission */ @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN) - public void setPasswordExpirationTimeout(@NonNull ComponentName admin, long timeout) { + @RequiresPermission(value = MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional = true) + public void setPasswordExpirationTimeout(@Nullable ComponentName admin, long timeout) { if (mService != null) { try { - mService.setPasswordExpirationTimeout(admin, timeout, mParentInstance); + mService.setPasswordExpirationTimeout( + admin, mContext.getPackageName(), timeout, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -5426,9 +5440,11 @@ public class DevicePolicyManager { * * @return {@code true} if the password meets the policy requirements, {@code false} otherwise * @throws SecurityException if the calling application isn't an active admin that uses - * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} + * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} and does not hold the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS} permission * @throws IllegalStateException if the user isn't unlocked */ + @RequiresPermission(value = MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional = true) public boolean isActivePasswordSufficient() { if (mService != null) { try { @@ -5492,7 +5508,8 @@ public class DevicePolicyManager { *

Note that when called from a profile which uses an unified challenge with its parent, the * screen lock complexity of the parent will be returned. * - *

Apps need the {@link permission#REQUEST_PASSWORD_COMPLEXITY} permission to call this + *

Apps need the {@link permission#REQUEST_PASSWORD_COMPLEXITY} or + * {@link permission#MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS} permissions to call this * method. On Android {@link android.os.Build.VERSION_CODES#S} and above, the calling * application does not need this permission if it is a device owner or a profile owner. * @@ -5502,11 +5519,12 @@ public class DevicePolicyManager { * * @throws IllegalStateException if the user is not unlocked. * @throws SecurityException if the calling application does not have the permission - * {@link permission#REQUEST_PASSWORD_COMPLEXITY}, and is not a - * device owner or a profile owner. + * {@link permission#REQUEST_PASSWORD_COMPLEXITY} or + * {@link permission#MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS}, and + * is not a device owner or a profile owner. */ @PasswordComplexity - @RequiresPermission(android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY) + @RequiresPermission(anyOf={MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, REQUEST_PASSWORD_COMPLEXITY}, conditional = true) public int getPasswordComplexity() { if (mService == null) { return PASSWORD_COMPLEXITY_NONE; @@ -5540,20 +5558,23 @@ public class DevicePolicyManager { * with {@link #PASSWORD_QUALITY_UNSPECIFIED} on that instance prior to setting complexity * requirement for the managed profile. * - * @throws SecurityException if the calling application is not a device owner or a profile - * owner. + * @throws SecurityException if the calling application is not a device owner, a profile + * owner, or a holder of the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS} permission. * @throws IllegalArgumentException if the complexity level is not one of the four above. * @throws IllegalStateException if the caller is trying to set password complexity while there * are password requirements specified using {@link #setPasswordQuality(ComponentName, int)} * on the parent {@code DevicePolicyManager} instance. */ + @RequiresPermission(value = MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional = true) public void setRequiredPasswordComplexity(@PasswordComplexity int passwordComplexity) { if (mService == null) { return; } try { - mService.setRequiredPasswordComplexity(passwordComplexity, mParentInstance); + mService.setRequiredPasswordComplexity( + mContext.getPackageName(), passwordComplexity, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -5573,9 +5594,11 @@ public class DevicePolicyManager { * restrictions on the parent profile. * * @throws SecurityException if the calling application is not a device owner or a profile - * owner. + * owner and does not hold the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS} permission. */ @PasswordComplexity + @RequiresPermission(value = MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional = true) public int getRequiredPasswordComplexity() { if (mService == null) { return PASSWORD_COMPLEXITY_NONE; @@ -5683,9 +5706,11 @@ public class DevicePolicyManager { * @return The number of times user has entered an incorrect password since the last correct * password entry. * @throws SecurityException if the calling application does not own an active administrator - * that uses {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} + * that uses {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} and does not hold the + * @link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS} permission. */ @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN) + @RequiresPermission(value = MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional = true) public int getCurrentFailedPasswordAttempts() { return getCurrentFailedPasswordAttempts(myUserId()); } @@ -6125,7 +6150,9 @@ public class DevicePolicyManager { } /** - * Called by a device/profile owner to set the timeout after which unlocking with secondary, non + * Called by a device owner, profile owner, or holder of the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS} permission to set + * the timeout after which unlocking with secondary, non * strong auth (e.g. fingerprint, face, trust agents) times out, i.e. the user has to use a * strong authentication method like password, pin or pattern. * @@ -6136,10 +6163,7 @@ public class DevicePolicyManager { * *

Trust agents can also be disabled altogether using {@link #KEYGUARD_DISABLE_TRUST_AGENTS}. * - *

The calling device admin must be a device or profile owner. If it is not, - * a {@link SecurityException} will be thrown. - * - *

The calling device admin can verify the value it has set by calling + *

A calling device admin can verify the value it has set by calling * {@link #getRequiredStrongAuthTimeout(ComponentName)} and passing in its instance. * *

This method can be called on the {@link DevicePolicyManager} instance returned by @@ -6149,7 +6173,8 @@ public class DevicePolicyManager { *

On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, * calling this methods has no effect - i.e. the timeout is not set. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the + * caller is not a device admin * @param timeoutMs The new timeout in milliseconds, after which the user will have to unlock * with strong authentication method. A value of 0 means the admin is not participating * in controlling the timeout. @@ -6158,14 +6183,17 @@ public class DevicePolicyManager { * auth at all times using {@link #KEYGUARD_DISABLE_FINGERPRINT} and/or * {@link #KEYGUARD_DISABLE_TRUST_AGENTS}. * - * @throws SecurityException if {@code admin} is not a device or profile owner. + * @throws SecurityException if {@code admin} is not permitted to set this policy. + * */ @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN) - public void setRequiredStrongAuthTimeout(@NonNull ComponentName admin, + @RequiresPermission(value = MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional = true) + public void setRequiredStrongAuthTimeout(@Nullable ComponentName admin, long timeoutMs) { if (mService != null) { try { - mService.setRequiredStrongAuthTimeout(admin, timeoutMs, mParentInstance); + mService.setRequiredStrongAuthTimeout( + admin, mContext.getPackageName(), timeoutMs, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -11496,9 +11524,10 @@ public class DevicePolicyManager { /** * Hide or unhide packages. When a package is hidden it is unavailable for use, but the data and - * actual package file remain. This function can be called by a device owner, profile owner, or - * by a delegate given the {@link #DELEGATION_PACKAGE_ACCESS} scope via - * {@link #setDelegatedScopes}. + * actual package file remain. This function can be called by a device owner, profile owner, + * delegate given the {@link #DELEGATION_PACKAGE_ACCESS} scope via + * {@link #setDelegatedScopes}, or a holder of the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_PACKAGE_STATE} permission. *

* This method can be called on the {@link DevicePolicyManager} instance, returned by * {@link #getParentProfileInstance(ComponentName)}, where the caller must be the profile owner @@ -11506,7 +11535,7 @@ public class DevicePolicyManager { * on the parent instance, then the package is hidden or unhidden in the personal profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or - * {@code null} if the caller is a package access delegate. + * {@code null} if the caller is not a device admin. * @param packageName The name of the package to hide or unhide. * @param hidden {@code true} if the package should be hidden, {@code false} if it should be * unhidden. @@ -11519,7 +11548,8 @@ public class DevicePolicyManager { * @see #setDelegatedScopes * @see #DELEGATION_PACKAGE_ACCESS */ - public boolean setApplicationHidden(@NonNull ComponentName admin, String packageName, + @RequiresPermission(value = MANAGE_DEVICE_POLICY_PACKAGE_STATE, conditional = true) + public boolean setApplicationHidden(@Nullable ComponentName admin, String packageName, boolean hidden) { if (mService != null) { try { @@ -11534,8 +11564,9 @@ public class DevicePolicyManager { /** * Determine if a package is hidden. This function can be called by a device owner, profile - * owner, or by a delegate given the {@link #DELEGATION_PACKAGE_ACCESS} scope via - * {@link #setDelegatedScopes}. + * owner, delegate given the {@link #DELEGATION_PACKAGE_ACCESS} scope via + * {@link #setDelegatedScopes}, or a holder of the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_PACKAGE_STATE} permission. *

* This method can be called on the {@link DevicePolicyManager} instance, returned by * {@link #getParentProfileInstance(ComponentName)}, where the caller must be the profile owner @@ -11544,7 +11575,7 @@ public class DevicePolicyManager { * personal profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or - * {@code null} if the caller is a package access delegate. + * {@code null} if the caller is not a device admin. * @param packageName The name of the package to retrieve the hidden status of. * @return boolean {@code true} if the package is hidden, {@code false} otherwise. * @throws SecurityException if {@code admin} is not a device or profile owner or if called on @@ -11555,7 +11586,8 @@ public class DevicePolicyManager { * @see #setDelegatedScopes * @see #DELEGATION_PACKAGE_ACCESS */ - public boolean isApplicationHidden(@NonNull ComponentName admin, String packageName) { + @RequiresPermission(value = MANAGE_DEVICE_POLICY_PACKAGE_STATE, conditional = true) + public boolean isApplicationHidden(@Nullable ComponentName admin, String packageName) { if (mService != null) { try { return mService.isApplicationHidden(admin, mContext.getPackageName(), packageName, @@ -12114,7 +12146,8 @@ public class DevicePolicyManager { } /** - * Called by a device owner or a profile owner of an organization-owned managed profile to + * Called by a device owner, profile owner of an organization-owned managed profile, or holder + * of the {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_WIFI} permission to * control whether the user can change networks configured by the admin. When this lockdown is * enabled, the user can still configure and connect to other Wi-Fi networks, or use other Wi-Fi * capabilities such as tethering. @@ -12126,17 +12159,19 @@ public class DevicePolicyManager { * to this API. * * @param admin admin Which {@link DeviceAdminReceiver} this request is associated - * with. + * with. Null if the caller is not a device admin. * @param lockdown Whether the admin configured networks should be unmodifiable by the * user. - * @throws SecurityException if caller is not a device owner or a profile owner of an - * organization-owned managed profile. + * @throws SecurityException if caller is not permitted to modify this policy */ - public void setConfiguredNetworksLockdownState(@NonNull ComponentName admin, boolean lockdown) { + @RequiresPermission(value = MANAGE_DEVICE_POLICY_WIFI, conditional = true) + public void setConfiguredNetworksLockdownState( + @Nullable ComponentName admin, boolean lockdown) { throwIfParentInstance("setConfiguredNetworksLockdownState"); if (mService != null) { try { - mService.setConfiguredNetworksLockdownState(admin, lockdown); + mService.setConfiguredNetworksLockdownState( + admin, mContext.getPackageName(), lockdown); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -12144,15 +12179,19 @@ public class DevicePolicyManager { } /** - * Called by a device owner or a profile owner of an organization-owned managed profile to + * Called by a device owner, profile owner of an organization-owned managed profile, or holder + * of the {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_WIFI} permission to * determine whether the user is prevented from modifying networks configured by the admin. * * @param admin admin Which {@link DeviceAdminReceiver} this request is associated - * with. - * @throws SecurityException if caller is not a device owner or a profile owner of an - * organization-owned managed profile. + * with. Null if the caller is not a device admin. + * @throws SecurityException if caller is not a device owner, a profile owner of an + * organization-owned managed profile, or holder of the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_WIFI} + * permission. */ - public boolean hasLockdownAdminConfiguredNetworks(@NonNull ComponentName admin) { + @RequiresPermission(value = MANAGE_DEVICE_POLICY_WIFI, conditional = true) + public boolean hasLockdownAdminConfiguredNetworks(@Nullable ComponentName admin) { throwIfParentInstance("hasLockdownAdminConfiguredNetworks"); if (mService != null) { try { diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 435673568c9f2..23871c313db7d 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -91,7 +91,7 @@ interface IDevicePolicyManager { void setPasswordHistoryLength(in ComponentName who, int length, boolean parent); int getPasswordHistoryLength(in ComponentName who, int userHandle, boolean parent); - void setPasswordExpirationTimeout(in ComponentName who, long expiration, boolean parent); + void setPasswordExpirationTimeout(in ComponentName who, String callerPackageName, long expiration, boolean parent); long getPasswordExpirationTimeout(in ComponentName who, int userHandle, boolean parent); long getPasswordExpiration(in ComponentName who, int userHandle, boolean parent); @@ -100,7 +100,7 @@ interface IDevicePolicyManager { boolean isActivePasswordSufficientForDeviceRequirement(); boolean isPasswordSufficientAfterProfileUnification(int userHandle, int profileUser); int getPasswordComplexity(boolean parent); - void setRequiredPasswordComplexity(int passwordComplexity, boolean parent); + void setRequiredPasswordComplexity(String callerPackageName, int passwordComplexity, boolean parent); int getRequiredPasswordComplexity(boolean parent); int getAggregatedPasswordComplexityForUser(int userId, boolean deviceWideOnly); boolean isUsingUnifiedPassword(in ComponentName admin); @@ -116,7 +116,7 @@ interface IDevicePolicyManager { void setMaximumTimeToLock(in ComponentName who, long timeMs, boolean parent); long getMaximumTimeToLock(in ComponentName who, int userHandle, boolean parent); - void setRequiredStrongAuthTimeout(in ComponentName who, long timeMs, boolean parent); + void setRequiredStrongAuthTimeout(in ComponentName who, String callerPackageName, long timeMs, boolean parent); long getRequiredStrongAuthTimeout(in ComponentName who, int userId, boolean parent); void lockNow(int flags, boolean parent); @@ -314,7 +314,7 @@ interface IDevicePolicyManager { void setSystemSetting(in ComponentName who, in String setting, in String value); void setSecureSetting(in ComponentName who, in String setting, in String value); - void setConfiguredNetworksLockdownState(in ComponentName who, boolean lockdown); + void setConfiguredNetworksLockdownState(in ComponentName who, String callerPackageName, boolean lockdown); boolean hasLockdownAdminConfiguredNetworks(in ComponentName who); void setLocationEnabled(in ComponentName who, boolean locationEnabled); @@ -593,8 +593,8 @@ interface IDevicePolicyManager { void setApplicationExemptions(String packageName, in int[]exemptions); int[] getApplicationExemptions(String packageName); - void setMtePolicy(int flag); - int getMtePolicy(); + void setMtePolicy(int flag, String callerPackageName); + int getMtePolicy(String callerPackageName); void setManagedSubscriptionsPolicy(in ManagedSubscriptionsPolicy policy); ManagedSubscriptionsPolicy getManagedSubscriptionsPolicy(); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index c976bd2fff167..d5612ada6a441 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -22,7 +22,10 @@ import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MTE; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_PACKAGE_STATE; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SCREEN_CAPTURE; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING; @@ -4371,16 +4374,31 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public void setPasswordExpirationTimeout(ComponentName who, long timeout, boolean parent) { + public void setPasswordExpirationTimeout(ComponentName who, String callerPackageName, + long timeout, boolean parent) { if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return; } - Objects.requireNonNull(who, "ComponentName is null"); + if (!isPermissionCheckFlagEnabled()) { + Objects.requireNonNull(who, "ComponentName is null"); + } + + CallerIdentity caller = getCallerIdentity(who, callerPackageName); + Preconditions.checkArgumentNonnegative(timeout, "Timeout must be >= 0 ms"); - final int userHandle = mInjector.userHandleGetCallingUserId(); + int userHandle = mInjector.userHandleGetCallingUserId(); + int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle; synchronized (getLockObject()) { - ActiveAdmin ap = getActiveAdminForCallerLocked( - who, DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD, parent); + ActiveAdmin ap; + if (isPermissionCheckFlagEnabled()) { + ap = enforcePermissionAndGetEnforcingAdmin( + who, MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, + caller.getPackageName(), affectedUserId) + .getActiveAdmin(); + } else { + ap = getActiveAdminForCallerLocked( + who, DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD, parent); + } // Calling this API automatically bumps the expiration date final long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L; ap.passwordExpirationDate = expiration; @@ -4396,8 +4414,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { setExpirationAlarmCheckLocked(mContext, userHandle, parent); } if (SecurityLog.isLoggingEnabled()) { - final int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle; - SecurityLog.writeEvent(SecurityLog.TAG_PASSWORD_EXPIRATION_SET, who.getPackageName(), + SecurityLog.writeEvent(SecurityLog.TAG_PASSWORD_EXPIRATION_SET, caller.getPackageName(), userHandle, affectedUserId, timeout); } } @@ -4858,9 +4875,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { enforceUserUnlocked(userHandle, parent); synchronized (getLockObject()) { - // This API can only be called by an active device admin, - // so try to retrieve it to check that the caller is one. - getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent); + if (isPermissionCheckFlagEnabled()) { + int affectedUser = parent ? getProfileParentId(userHandle) : userHandle; + enforcePermission(MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, affectedUser); + } else { + // This API can only be called by an active device admin, + // so try to retrieve it to check that the caller is one. + getActiveAdminForCallerLocked( + null, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent); + } + int credentialOwner = getCredentialOwner(userHandle, parent); DevicePolicyData policy = getUserDataUnchecked(credentialOwner); PasswordMetrics metrics = mLockSettingsInternal.getUserPasswordMetrics(credentialOwner); @@ -5006,11 +5030,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { isDefaultDeviceOwner(caller) || isProfileOwner(caller) || isSystemUid(caller), "Only profile owner, device owner and system may call this method on parent."); } else { - Preconditions.checkCallAuthorization( - hasCallingOrSelfPermission(REQUEST_PASSWORD_COMPLEXITY) - || isDefaultDeviceOwner(caller) || isProfileOwner(caller), - "Must have " + REQUEST_PASSWORD_COMPLEXITY - + " permission, or be a profile owner or device owner."); + if (isPermissionCheckFlagEnabled()) { + Preconditions.checkCallAuthorization( + hasCallingOrSelfPermission(REQUEST_PASSWORD_COMPLEXITY) + || hasCallingOrSelfPermission(MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS) + || isDefaultDeviceOwner(caller) || isProfileOwner(caller), + "Must have " + REQUEST_PASSWORD_COMPLEXITY + " or " + + MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS + + " permissions, or be a profile owner or device owner."); + } else { + Preconditions.checkCallAuthorization( + hasCallingOrSelfPermission(REQUEST_PASSWORD_COMPLEXITY) + || isDefaultDeviceOwner(caller) || isProfileOwner(caller), + "Must have " + REQUEST_PASSWORD_COMPLEXITY + + " permission, or be a profile owner or device owner."); + } } synchronized (getLockObject()) { @@ -5021,7 +5055,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public void setRequiredPasswordComplexity(int passwordComplexity, boolean calledOnParent) { + public void setRequiredPasswordComplexity( + String callerPackageName, int passwordComplexity, boolean calledOnParent) { if (!mHasFeature) { return; } @@ -5030,14 +5065,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Preconditions.checkArgument(allowedModes.contains(passwordComplexity), "Provided complexity is not one of the allowed values."); - final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization( - isDefaultDeviceOwner(caller) || isProfileOwner(caller)); - Preconditions.checkArgument(!calledOnParent || isProfileOwner(caller)); + final CallerIdentity caller = getCallerIdentity(callerPackageName); + if (!isPermissionCheckFlagEnabled()) { + Preconditions.checkCallAuthorization( + isDefaultDeviceOwner(caller) || isProfileOwner(caller)); + Preconditions.checkArgument(!calledOnParent || isProfileOwner(caller)); + } synchronized (getLockObject()) { - final ActiveAdmin admin = getParentOfAdminIfRequired( - getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), calledOnParent); + ActiveAdmin admin; + if (isPermissionCheckFlagEnabled()) { + // TODO: Make sure this returns the parent of the fake admin + // TODO: Deal with null componentname + int affectedUser = calledOnParent + ? getProfileParentId(caller.getUserId()) : caller.getUserId(); + admin = enforcePermissionAndGetEnforcingAdmin( + null, MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, + caller.getPackageName(), affectedUser).getActiveAdmin(); + } else { + admin = getParentOfAdminIfRequired( + getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), calledOnParent); + } + if (admin.mPasswordComplexity != passwordComplexity) { // We require the caller to explicitly clear any password quality requirements set // on the parent DPM instance, to avoid the case where password requirements are @@ -5064,22 +5113,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_PASSWORD_COMPLEXITY) - .setAdmin(admin.info.getPackageName()) + .setAdmin(caller.getPackageName()) .setInt(passwordComplexity) .setBoolean(calledOnParent) .write(); } - logPasswordComplexityRequiredIfSecurityLogEnabled(admin.info.getComponent(), + logPasswordComplexityRequiredIfSecurityLogEnabled(caller.getPackageName(), caller.getUserId(), calledOnParent, passwordComplexity); } } - private void logPasswordComplexityRequiredIfSecurityLogEnabled(ComponentName who, int userId, + private void logPasswordComplexityRequiredIfSecurityLogEnabled(String adminPackageName, + int userId, boolean parent, int complexity) { if (SecurityLog.isLoggingEnabled()) { final int affectedUserId = parent ? getProfileParentId(userId) : userId; SecurityLog.writeEvent(SecurityLog.TAG_PASSWORD_COMPLEXITY_REQUIRED, - who.getPackageName(), userId, affectedUserId, complexity); + adminPackageName, userId, affectedUserId, complexity); } } @@ -5111,10 +5161,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization( - isDefaultDeviceOwner(caller) || isProfileOwner(caller)); - Preconditions.checkArgument(!calledOnParent || isProfileOwner(caller)); + if (isPermissionCheckFlagEnabled()) { + int affectedUser = calledOnParent ? getProfileParentId(caller.getUserId()) + : caller.getUserId(); + enforcePermission(MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, affectedUser); + } else { + Preconditions.checkCallAuthorization( + isDefaultDeviceOwner(caller) || isProfileOwner(caller)); + + Preconditions.checkArgument(!calledOnParent || isProfileOwner(caller)); + } synchronized (getLockObject()) { final ActiveAdmin requiredAdmin = getParentOfAdminIfRequired( @@ -5152,8 +5209,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!isSystemUid(caller)) { // This API can be called by an active device admin or by keyguard code. if (!hasCallingPermission(permission.ACCESS_KEYGUARD_SECURE_STORAGE)) { - getActiveAdminForCallerLocked( - null, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, parent); + if (isPermissionCheckFlagEnabled()) { + int affectedUser = parent ? getProfileParentId(userHandle) : userHandle; + enforcePermission(MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, affectedUser); + } else { + getActiveAdminForCallerLocked( + null, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, parent); + } } } @@ -5558,16 +5620,20 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public void setRequiredStrongAuthTimeout(ComponentName who, long timeoutMs, + public void setRequiredStrongAuthTimeout(ComponentName who, String callerPackageName, long timeoutMs, boolean parent) { if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return; } - Objects.requireNonNull(who, "ComponentName is null"); + if (!isPermissionCheckFlagEnabled()) { + Objects.requireNonNull(who, "ComponentName is null"); + } Preconditions.checkArgument(timeoutMs >= 0, "Timeout must not be a negative number."); - final CallerIdentity caller = getCallerIdentity(who); - Preconditions.checkCallAuthorization( - isDefaultDeviceOwner(caller) || isProfileOwner(caller)); + final CallerIdentity caller = getCallerIdentity(who, callerPackageName); + if (!isPermissionCheckFlagEnabled()) { + Preconditions.checkCallAuthorization( + isDefaultDeviceOwner(caller) || isProfileOwner(caller)); + } // timeoutMs with value 0 means that the admin doesn't participate // timeoutMs is clamped to the interval in case the internal constants change in the future final long minimumStrongAuthTimeout = getMinimumStrongAuthTimeoutMs(); @@ -5581,8 +5647,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { final int userHandle = caller.getUserId(); boolean changed = false; synchronized (getLockObject()) { - ActiveAdmin ap = getParentOfAdminIfRequired( - getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), parent); + ActiveAdmin ap; + if (isPermissionCheckFlagEnabled()) { + int affectedUser = parent + ? getProfileParentId(caller.getUserId()) : caller.getUserId(); + ap = enforcePermissionAndGetEnforcingAdmin( + who, MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, + caller.getPackageName(), affectedUser).getActiveAdmin(); + } else { + ap = getParentOfAdminIfRequired( + getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), parent); + } if (ap.strongAuthUnlockTimeout != timeoutMs) { ap.strongAuthUnlockTimeout = timeoutMs; saveSettingsLocked(userHandle); @@ -8603,7 +8678,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin( who, MANAGE_DEVICE_POLICY_CAMERA, - callerPackageName, + caller.getPackageName(), getProfileParentUserIfRequested(userHandle, parent)); admin = enforcingAdmin.getActiveAdmin(); } else { @@ -12451,10 +12526,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public boolean setApplicationHidden(ComponentName who, String callerPackage, String packageName, boolean hidden, boolean parent) { - final CallerIdentity caller = getCallerIdentity(who, callerPackage); - Preconditions.checkCallAuthorization((caller.hasAdminComponent() - && (isProfileOwner(caller) || isDefaultDeviceOwner(caller))) - || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PACKAGE_ACCESS))); + CallerIdentity caller = getCallerIdentity(who, callerPackage); + int userId = parent ? getProfileParentId(caller.getUserId()) : caller.getUserId(); + if (isPermissionCheckFlagEnabled()) { + // TODO: We need to ensure the delegate with DELEGATION_PACKAGE_ACCESS can do this + enforcePermission(MANAGE_DEVICE_POLICY_PACKAGE_STATE, userId); + } else { + Preconditions.checkCallAuthorization((caller.hasAdminComponent() + && (isProfileOwner(caller) || isDefaultDeviceOwner(caller))) + || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PACKAGE_ACCESS))); + } List exemptApps = listPolicyExemptAppsUnchecked(mContext); if (exemptApps.contains(packageName)) { @@ -12463,12 +12544,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return false; } - final int userId = parent ? getProfileParentId(caller.getUserId()) : caller.getUserId(); boolean result; synchronized (getLockObject()) { if (parent) { - Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice( - caller.getUserId()) && isManagedProfile(caller.getUserId())); + if (!isPermissionCheckFlagEnabled()) { + Preconditions.checkCallAuthorization( + isProfileOwnerOfOrganizationOwnedDevice( + caller.getUserId()) && isManagedProfile(caller.getUserId())); + } // Ensure the package provided is a system package, this is to ensure that this // API cannot be used to leak if certain non-system package exists in the person // profile. @@ -12497,17 +12580,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public boolean isApplicationHidden(ComponentName who, String callerPackage, String packageName, boolean parent) { - final CallerIdentity caller = getCallerIdentity(who, callerPackage); - Preconditions.checkCallAuthorization((caller.hasAdminComponent() - && (isProfileOwner(caller) || isDefaultDeviceOwner(caller))) - || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PACKAGE_ACCESS))); + CallerIdentity caller = getCallerIdentity(who, callerPackage); + int userId = parent ? getProfileParentId(caller.getUserId()) : caller.getUserId(); + if (isPermissionCheckFlagEnabled()) { + // TODO: Also support DELEGATION_PACKAGE_ACCESS + enforcePermission(MANAGE_DEVICE_POLICY_PACKAGE_STATE, userId); + } else { + Preconditions.checkCallAuthorization((caller.hasAdminComponent() + && (isProfileOwner(caller) || isDefaultDeviceOwner(caller))) + || (caller.hasPackage() && isCallerDelegate( + caller, DELEGATION_PACKAGE_ACCESS))); + } - final int userId = parent ? getProfileParentId(caller.getUserId()) : caller.getUserId(); synchronized (getLockObject()) { if (parent) { - Preconditions.checkCallAuthorization( - isProfileOwnerOfOrganizationOwnedDevice(caller.getUserId()) - && isManagedProfile(caller.getUserId())); + if (!isPermissionCheckFlagEnabled()) { + Preconditions.checkCallAuthorization( + isProfileOwnerOfOrganizationOwnedDevice(caller.getUserId()) + && isManagedProfile(caller.getUserId())); + } // Ensure the package provided is a system package. mInjector.binderWithCleanCallingIdentity(() -> enforcePackageIsSystemPackage(packageName, userId)); @@ -13646,15 +13737,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public void setConfiguredNetworksLockdownState(ComponentName who, boolean lockdown) { + public void setConfiguredNetworksLockdownState( + ComponentName who, String callerPackageName, boolean lockdown) { if (!mHasFeature) { return; } - Preconditions.checkNotNull(who, "ComponentName is null"); + CallerIdentity caller = getCallerIdentity(who, callerPackageName); - final CallerIdentity caller = getCallerIdentity(who); - Preconditions.checkCallAuthorization( - isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller)); + if (isPermissionCheckFlagEnabled()) { + enforcePermission(MANAGE_DEVICE_POLICY_WIFI, UserHandle.USER_ALL); + } else { + Preconditions.checkNotNull(who, "ComponentName is null"); + Preconditions.checkCallAuthorization( + isDefaultDeviceOwner(caller) + || isProfileOwnerOfOrganizationOwnedDevice(caller)); + } mInjector.binderWithCleanCallingIdentity(() -> mInjector.settingsGlobalPutInt(Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, @@ -13662,7 +13759,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DevicePolicyEventLogger .createEvent(DevicePolicyEnums.ALLOW_MODIFICATION_OF_ADMIN_CONFIGURED_NETWORKS) - .setAdmin(caller.getComponentName()) + .setAdmin(caller.getPackageName()) .setBoolean(lockdown) .write(); } @@ -13672,11 +13769,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return false; } - Preconditions.checkNotNull(who, "ComponentName is null"); + CallerIdentity caller = getCallerIdentity(who); + if (isPermissionCheckFlagEnabled()) { + enforcePermission(MANAGE_DEVICE_POLICY_WIFI, UserHandle.USER_ALL); + } else { + Preconditions.checkNotNull(who, "ComponentName is null"); - final CallerIdentity caller = getCallerIdentity(who); - Preconditions.checkCallAuthorization( - isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller)); + Preconditions.checkCallAuthorization( + isDefaultDeviceOwner(caller) + || isProfileOwnerOfOrganizationOwnedDevice(caller)); + } return mInjector.binderWithCleanCallingIdentity(() -> mInjector.settingsGlobalGetInt(Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0) > 0); @@ -20837,7 +20939,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, MANAGE_DEVICE_POLICY_SECURITY_LOGGING, - MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING); + MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING, + MANAGE_DEVICE_POLICY_MTE, + MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, + MANAGE_DEVICE_POLICY_PACKAGE_STATE); private static final List FINANCED_DEVICE_OWNER_PERMISSIONS = List.of( MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL, MANAGE_DEVICE_POLICY_ACROSS_USERS, @@ -20856,19 +20961,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, MANAGE_DEVICE_POLICY_SECURITY_LOGGING, - MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING); + MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING, + MANAGE_DEVICE_POLICY_MTE, + MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, + MANAGE_DEVICE_POLICY_PACKAGE_STATE); private static final List PROFILE_OWNER_ON_USER_0_PERMISSIONS = List.of( SET_TIME, SET_TIME_ZONE, MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, MANAGE_DEVICE_POLICY_WIPE_DATA, - MANAGE_DEVICE_POLICY_SCREEN_CAPTURE); + MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, + MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, + MANAGE_DEVICE_POLICY_PACKAGE_STATE); private static final List PROFILE_OWNER_PERMISSIONS = List.of( MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL, MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY, MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, MANAGE_DEVICE_POLICY_WIPE_DATA, - MANAGE_DEVICE_POLICY_SCREEN_CAPTURE); + MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, + MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, + MANAGE_DEVICE_POLICY_PACKAGE_STATE); private static final HashMap> DPC_PERMISSIONS = new HashMap<>(); { @@ -20882,6 +20994,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { //TODO(b/254253251) Fill this map in as new permissions are added for policies. // TODO: Add USES_POLICY_WIPE_DATA -> MANAGE_DEVICE_POLICY_WIPE_DATA + // TODO: Add USES_POLICY_EXPIRE_PASSWORD -> MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS + // TODO: Consider USES_POLICY_WATCH_LOGIN -> MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS - + // is this opening up too much? maybe we need to special case device admin in the checker private static final HashMap ACTIVE_ADMIN_POLICIES = new HashMap<>(); private static final HashMap CROSS_USER_PERMISSIONS = @@ -20896,6 +21011,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_SECURITY_LOGGING, null); // usb signalling is intrinsically global so there is no cross-user permission CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING, null); + // mte is intrinsically global so there is no cross-user permission + CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_MTE, null); // Organisation identity policy will involve data of other organisations on the device and // therefore the FULL cross-user permission is required. CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY, @@ -20906,6 +21023,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { MANAGE_DEVICE_POLICY_ACROSS_USERS); CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, MANAGE_DEVICE_POLICY_ACROSS_USERS); + CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, + MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL); + CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_PACKAGE_STATE, + MANAGE_DEVICE_POLICY_ACROSS_USERS); } /** @@ -21132,8 +21253,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Slog.i(LOG_TAG, "Keep profiles running overridden to: " + enabled); } - @Override - public void setMtePolicy(int flags) { + public void setMtePolicy(int flags, String callerPackageName) { final Set allowedModes = Set.of( DevicePolicyManager.MTE_NOT_CONTROLLED_BY_POLICY, @@ -21152,9 +21272,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { "ro.arm64.memtag.bootctl_settings_toggle", false))) { throw new UnsupportedOperationException("device does not support MTE"); } - final CallerIdentity caller = getCallerIdentity(); + final CallerIdentity caller = getCallerIdentity(callerPackageName); + // For now we continue to restrict the DISABLED setting to device owner - we might need + // another permission for this in future. if (flags == DevicePolicyManager.MTE_DISABLED) { Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)); + } + + if (isPermissionCheckFlagEnabled()) { + enforcePermission(MANAGE_DEVICE_POLICY_MTE, UserHandle.USER_ALL); } else { Preconditions.checkCallAuthorization( isDefaultDeviceOwner(caller) @@ -21184,19 +21310,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DevicePolicyEventLogger.createEvent(DevicePolicyEnums.SET_MTE_POLICY) .setInt(flags) - .setAdmin(admin.info.getPackageName()) + .setAdmin(caller.getPackageName()) .write(); } } } @Override - public int getMtePolicy() { - final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization( - isDefaultDeviceOwner(caller) - || isProfileOwnerOfOrganizationOwnedDevice(caller) - || isSystemUid(caller)); + public int getMtePolicy(String callerPackageName) { + final CallerIdentity caller = getCallerIdentity(callerPackageName); + if (isPermissionCheckFlagEnabled()) { + enforcePermission(MANAGE_DEVICE_POLICY_MTE, UserHandle.USER_ALL); + } else { + Preconditions.checkCallAuthorization( + isDefaultDeviceOwner(caller) + || isProfileOwnerOfOrganizationOwnedDevice(caller) + || isSystemUid(caller)); + } synchronized (getLockObject()) { // TODO(b/261999445): Remove ActiveAdmin admin; From dd1a75b57dc2423203a67976dfdc7ff2a71aca82 Mon Sep 17 00:00:00 2001 From: Jonathan Scott Date: Mon, 13 Feb 2023 15:50:29 +0000 Subject: [PATCH 3/3] Add DPM Permissions 3. Test: btest a.d.c.PermitInputMethodsTest Test: btest a.d.c.KeyguardTest Test: btest a.d.c.LockTest Test: btest a.d.c.FactoryResetTest Bug: 234609037 Change-Id: Id6a35acb9e88fcff44772011e41d63baa8ec8e31 --- core/api/current.txt | 18 +- .../app/admin/DevicePolicyManager.java | 137 ++++++--- .../app/admin/IDevicePolicyManager.aidl | 14 +- .../DevicePolicyManagerService.java | 290 +++++++++++++----- 4 files changed, 320 insertions(+), 139 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index d7460b326160e..e350f565d8112 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -7825,7 +7825,7 @@ package android.app.admin { method @Nullable public String getDevicePolicyManagementRoleHolderPackage(); method public CharSequence getEndUserSessionMessage(@NonNull android.content.ComponentName); method @NonNull public String getEnrollmentSpecificId(); - method @Nullable public android.app.admin.FactoryResetProtectionPolicy getFactoryResetProtectionPolicy(@Nullable android.content.ComponentName); + method @Nullable @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_FACTORY_RESET, conditional=true) public android.app.admin.FactoryResetProtectionPolicy getFactoryResetProtectionPolicy(@Nullable android.content.ComponentName); method @Nullable public String getGlobalPrivateDnsHost(@NonNull android.content.ComponentName); method public int getGlobalPrivateDnsMode(@NonNull android.content.ComponentName); method @NonNull public java.util.List getInstalledCaCerts(@Nullable android.content.ComponentName); @@ -7868,7 +7868,7 @@ package android.app.admin { method public int getPermissionPolicy(android.content.ComponentName); method @Nullable public java.util.List getPermittedAccessibilityServices(@NonNull android.content.ComponentName); method @Nullable public java.util.List getPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName); - method @Nullable public java.util.List getPermittedInputMethods(@NonNull android.content.ComponentName); + method @Nullable @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_INPUT_METHODS, conditional=true) public java.util.List getPermittedInputMethods(@Nullable android.content.ComponentName); method public int getPersonalAppsSuspendedReasons(@NonNull android.content.ComponentName); method @NonNull public java.util.List getPreferentialNetworkServiceConfigs(); method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional=true) public int getRequiredPasswordComplexity(); @@ -7934,8 +7934,8 @@ package android.app.admin { method public boolean isUsbDataSignalingEnabled(); method public boolean isUsingUnifiedPassword(@NonNull android.content.ComponentName); method @NonNull public java.util.List listForegroundAffiliatedUsers(); - method public void lockNow(); - method public void lockNow(int); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK, conditional=true) public void lockNow(); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK, conditional=true) public void lockNow(int); method public int logoutUser(@NonNull android.content.ComponentName); method public void reboot(@NonNull android.content.ComponentName); method public void removeActiveAdmin(@NonNull android.content.ComponentName); @@ -7976,14 +7976,14 @@ package android.app.admin { method public void setDelegatedScopes(@NonNull android.content.ComponentName, @NonNull String, @NonNull java.util.List); method public void setDeviceOwnerLockScreenInfo(@NonNull android.content.ComponentName, CharSequence); method public void setEndUserSessionMessage(@NonNull android.content.ComponentName, @Nullable CharSequence); - method public void setFactoryResetProtectionPolicy(@NonNull android.content.ComponentName, @Nullable android.app.admin.FactoryResetProtectionPolicy); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_FACTORY_RESET, conditional=true) public void setFactoryResetProtectionPolicy(@Nullable android.content.ComponentName, @Nullable android.app.admin.FactoryResetProtectionPolicy); method public int setGlobalPrivateDnsModeOpportunistic(@NonNull android.content.ComponentName); method @WorkerThread public int setGlobalPrivateDnsModeSpecifiedHost(@NonNull android.content.ComponentName, @NonNull String); method public void setGlobalSetting(@NonNull android.content.ComponentName, String, String); method public void setKeepUninstalledPackages(@Nullable android.content.ComponentName, @NonNull java.util.List); method public boolean setKeyPairCertificate(@Nullable android.content.ComponentName, @NonNull String, @NonNull java.util.List, boolean); method public boolean setKeyguardDisabled(@NonNull android.content.ComponentName, boolean); - method public void setKeyguardDisabledFeatures(@NonNull android.content.ComponentName, int); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_KEYGUARD, conditional=true) public void setKeyguardDisabledFeatures(@Nullable android.content.ComponentName, int); method public void setLocationEnabled(@NonNull android.content.ComponentName, boolean); method public void setLockTaskFeatures(@NonNull android.content.ComponentName, int); method public void setLockTaskPackages(@NonNull android.content.ComponentName, @NonNull String[]) throws java.lang.SecurityException; @@ -7995,7 +7995,7 @@ package android.app.admin { method public void setManagedSubscriptionsPolicy(@Nullable android.app.admin.ManagedSubscriptionsPolicy); method public void setMasterVolumeMuted(@NonNull android.content.ComponentName, boolean); method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_WIPE_DATA, conditional=true) public void setMaximumFailedPasswordsForWipe(@Nullable android.content.ComponentName, int); - method public void setMaximumTimeToLock(@NonNull android.content.ComponentName, long); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK, conditional=true) public void setMaximumTimeToLock(@Nullable android.content.ComponentName, long); method @NonNull public java.util.List setMeteredDataDisabledPackages(@NonNull android.content.ComponentName, @NonNull java.util.List); method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI, conditional=true) public void setMinimumRequiredWifiSecurityLevel(int); method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_MTE, conditional=true) public void setMtePolicy(int); @@ -8021,7 +8021,7 @@ package android.app.admin { method public void setPermissionPolicy(@NonNull android.content.ComponentName, int); method public boolean setPermittedAccessibilityServices(@NonNull android.content.ComponentName, java.util.List); method public boolean setPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName, @Nullable java.util.List); - method public boolean setPermittedInputMethods(@NonNull android.content.ComponentName, java.util.List); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_INPUT_METHODS, conditional=true) public boolean setPermittedInputMethods(@Nullable android.content.ComponentName, java.util.List); method public void setPersonalAppsSuspended(@NonNull android.content.ComponentName, boolean); method public void setPreferentialNetworkServiceConfigs(@NonNull java.util.List); method public void setPreferentialNetworkServiceEnabled(boolean); @@ -8043,7 +8043,7 @@ package android.app.admin { method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, conditional=true) public void setSystemUpdatePolicy(@NonNull android.content.ComponentName, android.app.admin.SystemUpdatePolicy); method @RequiresPermission(value=android.Manifest.permission.SET_TIME, conditional=true) public boolean setTime(@NonNull android.content.ComponentName, long); method @RequiresPermission(value=android.Manifest.permission.SET_TIME_ZONE, conditional=true) public boolean setTimeZone(@NonNull android.content.ComponentName, String); - method public void setTrustAgentConfiguration(@NonNull android.content.ComponentName, @NonNull android.content.ComponentName, android.os.PersistableBundle); + method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_KEYGUARD, conditional=true) public void setTrustAgentConfiguration(@Nullable android.content.ComponentName, @NonNull android.content.ComponentName, android.os.PersistableBundle); method public void setUninstallBlocked(@Nullable android.content.ComponentName, String, boolean); method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING, conditional=true) public void setUsbDataSignalingEnabled(boolean); method public void setUserControlDisabledPackages(@NonNull android.content.ComponentName, @NonNull java.util.List); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index d4d5aac23d7f2..f3717d3ed3e37 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -20,6 +20,10 @@ import static android.Manifest.permission.INTERACT_ACROSS_USERS; import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA; import static android.Manifest.permission.MANAGE_DEVICE_ADMINS; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_FACTORY_RESET; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_INPUT_METHODS; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_KEYGUARD; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MTE; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY; @@ -6095,23 +6099,26 @@ public class DevicePolicyManager { * activity until the device will lock. This limits the length that the user can set. It takes * effect immediately. *

- * The calling device admin must have requested {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} + * A calling device admin must have requested {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} * to be able to call this method; if it has not, a security exception will be thrown. *

* This method can be called on the {@link DevicePolicyManager} instance returned by * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent * profile. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the + * caller is not a device admin * @param timeMs The new desired maximum time to lock in milliseconds. A value of 0 means there * is no restriction. * @throws SecurityException if {@code admin} is not an active administrator or it does not use - * {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} + * {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} and the caller does not hold the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK} permission */ - public void setMaximumTimeToLock(@NonNull ComponentName admin, long timeMs) { + @RequiresPermission(value = MANAGE_DEVICE_POLICY_LOCK, conditional = true) + public void setMaximumTimeToLock(@Nullable ComponentName admin, long timeMs) { if (mService != null) { try { - mService.setMaximumTimeToLock(admin, timeMs, mParentInstance); + mService.setMaximumTimeToLock(admin, mContext.getPackageName(), timeMs, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -6261,7 +6268,8 @@ public class DevicePolicyManager { *

* This method secures the device in response to an urgent situation, such as a lost or stolen * device. After this method is called, the device must be unlocked using strong authentication - * (PIN, pattern, or password). This API is intended for use only by device admins. + * (PIN, pattern, or password). This API is for use only by device admins and holders of the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK} permission. *

* From version {@link android.os.Build.VERSION_CODES#R} onwards, the caller must either have * the LOCK_DEVICE permission or the device must have the device admin feature; if neither is @@ -6285,8 +6293,10 @@ public class DevicePolicyManager { * Equivalent to calling {@link #lockNow(int)} with no flags. * * @throws SecurityException if the calling application does not own an active administrator - * that uses {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} + * that uses {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} and does not hold the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK} permission */ + @RequiresPermission(value = MANAGE_DEVICE_POLICY_LOCK, conditional = true) public void lockNow() { lockNow(0); } @@ -6297,7 +6307,8 @@ public class DevicePolicyManager { *

* This method secures the device in response to an urgent situation, such as a lost or stolen * device. After this method is called, the device must be unlocked using strong authentication - * (PIN, pattern, or password). This API is intended for use only by device admins. + * (PIN, pattern, or password). This API is for use only by device admins and holders of the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK} permission. *

* From version {@link android.os.Build.VERSION_CODES#R} onwards, the caller must either have * the LOCK_DEVICE permission or the device must have the device admin feature; if neither is @@ -6305,7 +6316,7 @@ public class DevicePolicyManager { * {@link android.os.Build.VERSION_CODES#R}, the device needed the device admin feature, * regardless of the caller's permissions. *

- * The calling device admin must have requested {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} + * A calling device admin must have requested {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} * to be able to call this method; if it has not, a security exception will be thrown. *

* If there's no lock type set, this method forces the device to go to sleep but doesn't lock @@ -6331,16 +6342,17 @@ public class DevicePolicyManager { * * @param flags May be 0 or {@link #FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY}. * @throws SecurityException if the calling application does not own an active administrator - * that uses {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} or the - * {@link #FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY} flag is passed by an application - * that is not a profile - * owner of a managed profile. + * that uses {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} and the does not hold + * the {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK} permission, or + * the {@link #FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY} flag is passed by an + * application that is not a profile owner of a managed profile. * @throws IllegalArgumentException if the {@link #FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY} flag is * passed when locking the parent profile. * @throws UnsupportedOperationException if the {@link #FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY} * flag is passed when {@link #getStorageEncryptionStatus} does not return * {@link #ENCRYPTION_STATUS_ACTIVE_PER_USER}. */ + @RequiresPermission(value = MANAGE_DEVICE_POLICY_LOCK, conditional = true) public void lockNow(@LockNowFlag int flags) { if (mService != null) { try { @@ -6485,24 +6497,28 @@ public class DevicePolicyManager { } /** - * Callable by device owner or profile owner of an organization-owned device, to set a + * Callable by device owner, profile owner of an organization-owned device, or a holder of the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_FACTORY_RESET} permission to set a * factory reset protection (FRP) policy. When a new policy is set, the system * notifies the FRP management agent of a policy change by broadcasting * {@code ACTION_RESET_PROTECTION_POLICY_CHANGED}. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the + * caller is not a device admin * @param policy the new FRP policy, or {@code null} to clear the current policy. - * @throws SecurityException if {@code admin} is not a device owner or a profile owner of - * an organization-owned device. + * @throws SecurityException if {@code admin} is not a device owner, profile owner of + * an organization-owned device, or holder of the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_FACTORY_RESET} permission * @throws UnsupportedOperationException if factory reset protection is not * supported on the device. */ - public void setFactoryResetProtectionPolicy(@NonNull ComponentName admin, + @RequiresPermission(value = MANAGE_DEVICE_POLICY_FACTORY_RESET, conditional = true) + public void setFactoryResetProtectionPolicy(@Nullable ComponentName admin, @Nullable FactoryResetProtectionPolicy policy) { throwIfParentInstance("setFactoryResetProtectionPolicy"); if (mService != null) { try { - mService.setFactoryResetProtectionPolicy(admin, policy); + mService.setFactoryResetProtectionPolicy(admin, mContext.getPackageName(), policy); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -6510,23 +6526,26 @@ public class DevicePolicyManager { } /** - * Callable by device owner or profile owner of an organization-owned device, to retrieve - * the current factory reset protection (FRP) policy set previously by - * {@link #setFactoryResetProtectionPolicy}. + * Callable by device owner, profile owner of an organization-owned device, or + * holder of the {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_FACTORY_RESET} + * permission to retrieve the current factory reset protection (FRP) + * policy set previously by {@link #setFactoryResetProtectionPolicy}. *

* This method can also be called by the FRP management agent on device or with the permission * {@link android.Manifest.permission#MASTER_CLEAR}, in which case, it can pass {@code null} * as the ComponentName. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with or - * {@code null} if called by the FRP management agent on device or with the - * permission {@link android.Manifest.permission#MASTER_CLEAR}. + * {@code null} if the caller is not a device admin * @return The current FRP policy object or {@code null} if no policy is set. * @throws SecurityException if {@code admin} is not a device owner, a profile owner of - * an organization-owned device or the FRP management agent. + * an organization-owned device, a holder of the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_FACTORY_RESET} + * permission, or the FRP management agent. * @throws UnsupportedOperationException if factory reset protection is not * supported on the device. */ + @RequiresPermission(value = MANAGE_DEVICE_POLICY_FACTORY_RESET, conditional = true) public @Nullable FactoryResetProtectionPolicy getFactoryResetProtectionPolicy( @Nullable ComponentName admin) { throwIfParentInstance("getFactoryResetProtectionPolicy"); @@ -8725,7 +8744,7 @@ public class DevicePolicyManager { * such as widgets. After setting this, keyguard features will be disabled according to the * provided feature list. *

- * The calling device admin must have requested + * A calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call this method; * if it has not, a security exception will be thrown. *

@@ -8764,7 +8783,8 @@ public class DevicePolicyManager { * The admin can check which features have been disabled by calling * {@link #getKeyguardDisabledFeatures(ComponentName)} * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the + * caller is not a device admin * @param which The disabled features flag which can be either * {@link #KEYGUARD_DISABLE_FEATURES_NONE} (default), * {@link #KEYGUARD_DISABLE_FEATURES_ALL}, or a combination of @@ -8776,13 +8796,16 @@ public class DevicePolicyManager { * {@link #KEYGUARD_DISABLE_FACE}, * {@link #KEYGUARD_DISABLE_IRIS}, * {@link #KEYGUARD_DISABLE_SHORTCUTS_ALL}. - * @throws SecurityException if {@code admin} is not an active administrator or does not user - * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} + * @throws SecurityException if {@code admin} is not an active administrator or does not use + * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} and does not hold + * the {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_KEYGUARD} permission */ - public void setKeyguardDisabledFeatures(@NonNull ComponentName admin, int which) { + @RequiresPermission(value = MANAGE_DEVICE_POLICY_KEYGUARD, conditional = true) + public void setKeyguardDisabledFeatures(@Nullable ComponentName admin, int which) { if (mService != null) { try { - mService.setKeyguardDisabledFeatures(admin, which, mParentInstance); + mService.setKeyguardDisabledFeatures( + admin, mContext.getPackageName(), which, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -9934,7 +9957,7 @@ public class DevicePolicyManager { * {@link #KEYGUARD_DISABLE_TRUST_AGENTS} and aggregate the configurations to determine its * behavior. The exact meaning of aggregation is trust-agent-specific. *

- * The calling device admin must have requested + * A calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call this method; * if not, a security exception will be thrown. *

@@ -9945,20 +9968,24 @@ public class DevicePolicyManager { * On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, calling * this method has no effect - no trust agent configuration will be set. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the + * caller is not a device admin * @param target Component name of the agent to be configured. * @param configuration Trust-agent-specific feature configuration bundle. Please consult * documentation of the specific trust agent to determine the interpretation of this * bundle. * @throws SecurityException if {@code admin} is not an active administrator or does not use - * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} + * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} and does not have + * the {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_KEYGUARD} permission */ @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN) - public void setTrustAgentConfiguration(@NonNull ComponentName admin, + @RequiresPermission(value = MANAGE_DEVICE_POLICY_KEYGUARD, conditional = true) + public void setTrustAgentConfiguration(@Nullable ComponentName admin, @NonNull ComponentName target, PersistableBundle configuration) { if (mService != null) { try { - mService.setTrustAgentConfiguration(admin, target, configuration, mParentInstance); + mService.setTrustAgentConfiguration( + admin, mContext.getPackageName(), target, configuration, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -10639,8 +10666,10 @@ public class DevicePolicyManager { } /** - * Called by a profile or device owner to set the permitted input methods services for this - * user. By default, the user can use any input method. + * Called by a profile or device owner or holder of the + * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_INPUT_METHODS} permission to set + * the permitted input methods services for this user. By default, the user can use any input + * method. *

* This method can be called on the {@link DevicePolicyManager} instance, * returned by {@link #getParentProfileInstance(ComponentName)}, where the caller must be @@ -10665,23 +10694,28 @@ public class DevicePolicyManager { *

* System input methods are always available to the user - this method can't modify this. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the + * caller is not a device admin * @param packageNames List of input method package names. * @return {@code true} if the operation succeeded, or {@code false} if the list didn't * contain every enabled non-system input method service. - * @throws SecurityException if {@code admin} is not a device, profile owner or if called on - * the parent profile and the {@code admin} is not a profile owner - * of an organization-owned managed profile. + * @throws SecurityException if {@code admin} is not a device or profile owner and does not + * hold the {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_INPUT_METHODS} + * permission, or if called on the parent profile and the + * {@code admin} is not a profile owner of an organization-owned + * managed profile. * @throws IllegalArgumentException if called on the parent profile, the {@code admin} is a * profile owner of an organization-owned managed profile and the * list of permitted input method package names is not null or empty. */ @SupportsCoexistence + @RequiresPermission(value = MANAGE_DEVICE_POLICY_INPUT_METHODS, conditional = true) public boolean setPermittedInputMethods( - @NonNull ComponentName admin, List packageNames) { + @Nullable ComponentName admin, List packageNames) { if (mService != null) { try { - return mService.setPermittedInputMethods(admin, packageNames, mParentInstance); + return mService.setPermittedInputMethods( + admin, mContext.getPackageName(), packageNames, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -10702,16 +10736,19 @@ public class DevicePolicyManager { * An empty list means no input methods except system input methods are allowed. Null means all * input methods are allowed. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the + * caller is not a device admin * @return List of input method package names. - * @throws SecurityException if {@code admin} is not a device, profile owner or if called on - * the parent profile and the {@code admin} is not a profile owner - * of an organization-owned managed profile. + * @throws SecurityException if {@code admin} is not a device or profile owner and does not + * hold the {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_INPUT_METHODS} + * permission or if called on the parent profile and the {@code admin} + * is not a profile owner of an organization-owned managed profile. */ - public @Nullable List getPermittedInputMethods(@NonNull ComponentName admin) { + @RequiresPermission(value = MANAGE_DEVICE_POLICY_INPUT_METHODS, conditional = true) + public @Nullable List getPermittedInputMethods(@Nullable ComponentName admin) { if (mService != null) { try { - return mService.getPermittedInputMethods(admin, mParentInstance); + return mService.getPermittedInputMethods(admin, mContext.getPackageName(), mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 23871c313db7d..14c6ecd414337 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -113,7 +113,7 @@ interface IDevicePolicyManager { boolean resetPassword(String password, int flags); - void setMaximumTimeToLock(in ComponentName who, long timeMs, boolean parent); + void setMaximumTimeToLock(in ComponentName who, String callerPackageName, long timeMs, boolean parent); long getMaximumTimeToLock(in ComponentName who, int userHandle, boolean parent); void setRequiredStrongAuthTimeout(in ComponentName who, String callerPackageName, long timeMs, boolean parent); @@ -126,7 +126,7 @@ interface IDevicePolicyManager { **/ void wipeDataWithReason(int flags, String wipeReasonForUser, boolean parent, boolean factoryReset); - void setFactoryResetProtectionPolicy(in ComponentName who, in FactoryResetProtectionPolicy policy); + void setFactoryResetProtectionPolicy(in ComponentName who, String callerPackageName, in FactoryResetProtectionPolicy policy); FactoryResetProtectionPolicy getFactoryResetProtectionPolicy(in ComponentName who); boolean isFactoryResetProtectionPolicySupported(); @@ -155,7 +155,7 @@ interface IDevicePolicyManager { void setNearbyAppStreamingPolicy(int policy); int getNearbyAppStreamingPolicy(int userId); - void setKeyguardDisabledFeatures(in ComponentName who, int which, boolean parent); + void setKeyguardDisabledFeatures(in ComponentName who, String callerPackageName, int which, boolean parent); int getKeyguardDisabledFeatures(in ComponentName who, int userHandle, boolean parent); void setActiveAdmin(in ComponentName policyReceiver, boolean refreshing, int userHandle); @@ -262,8 +262,8 @@ interface IDevicePolicyManager { List getPermittedAccessibilityServicesForUser(int userId); boolean isAccessibilityServicePermittedByAdmin(in ComponentName admin, String packageName, int userId); - boolean setPermittedInputMethods(in ComponentName admin,in List packageList, boolean parent); - List getPermittedInputMethods(in ComponentName admin, boolean parent); + boolean setPermittedInputMethods(in ComponentName admin, String callerPackageName, in List packageList, boolean parent); + List getPermittedInputMethods(in ComponentName admin, String callerPackageName, boolean parent); List getPermittedInputMethodsAsUser(int userId); boolean isInputMethodPermittedByAdmin(in ComponentName admin, String packageName, int userId, boolean parent); @@ -353,8 +353,8 @@ interface IDevicePolicyManager { boolean getBluetoothContactSharingDisabled(in ComponentName who); boolean getBluetoothContactSharingDisabledForUser(int userId); - void setTrustAgentConfiguration(in ComponentName admin, in ComponentName agent, - in PersistableBundle args, boolean parent); + void setTrustAgentConfiguration(in ComponentName admin, String callerPackageName, + in ComponentName agent, in PersistableBundle args, boolean parent); List getTrustAgentConfiguration(in ComponentName admin, in ComponentName agent, int userId, boolean parent); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index d5612ada6a441..e9860f6f0b7e2 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -17,11 +17,16 @@ package com.android.server.devicepolicy; import static android.Manifest.permission.BIND_DEVICE_ADMIN; +import static android.Manifest.permission.LOCK_DEVICE; import static android.Manifest.permission.MANAGE_CA_CERTIFICATES; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_FACTORY_RESET; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_INPUT_METHODS; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_KEYGUARD; +import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MTE; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY; @@ -2800,14 +2805,34 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { ComponentName who, int reqPolicy, @Nullable String permission) throws SecurityException { + return getActiveAdminOrCheckPermissionsForCallerLocked( + who, reqPolicy, permission == null ? Set.of() : Set.of(permission)); + } + + /** + * Finds an active admin for the caller then checks {@code permissions} if admin check failed. + * + * @return an active admin or {@code null} if there is no active admin but + * one of {@code permissions} is granted + * @throws SecurityException if caller neither has an active admin nor {@code permission} + */ + @Nullable + ActiveAdmin getActiveAdminOrCheckPermissionsForCallerLocked( + ComponentName who, + int reqPolicy, + Set permissions) throws SecurityException { ensureLocked(); final CallerIdentity caller = getCallerIdentity(); ActiveAdmin result = getActiveAdminWithPolicyForUidLocked(who, reqPolicy, caller.getUid()); if (result != null) { return result; - } else if (permission != null && hasCallingPermission(permission)) { - return null; + } else { + for (String permission : permissions) { + if (hasCallingPermission(permission)) { + return null; + } + } } // Code for handling failure from getActiveAdminWithPolicyForUidLocked to find an admin @@ -2831,8 +2856,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + admin.info.getTagForPolicy(reqPolicy)); } else { throw new SecurityException("No active admin owned by uid " - + caller.getUid() + " for policy #" + reqPolicy + (permission == null ? "" - : ", which doesn't have " + permission)); + + caller.getUid() + " for policy #" + reqPolicy + (permissions.isEmpty() ? "" + : ", which doesn't have " + permissions)); } } @@ -2855,12 +2880,29 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int reqPolicy, boolean parent, @Nullable String permission) throws SecurityException { + return getActiveAdminOrCheckPermissionsForCallerLocked( + who, reqPolicy, parent, permission == null ? Set.of() : Set.of(permission)); + } + + /** + * Finds an active admin for the caller then checks {@code permission} if admin check failed. + * + * @return an active admin or {@code null} if there is no active admin but + * {@code permission} is granted + * @throws SecurityException if caller neither has an active admin nor {@code permission} + */ + @Nullable + ActiveAdmin getActiveAdminOrCheckPermissionsForCallerLocked( + @Nullable ComponentName who, + int reqPolicy, + boolean parent, + Set permissions) throws SecurityException { ensureLocked(); if (parent) { Preconditions.checkCallingUser(isManagedProfile(getCallerIdentity().getUserId())); } - ActiveAdmin admin = getActiveAdminOrCheckPermissionForCallerLocked( - who, reqPolicy, permission); + ActiveAdmin admin = getActiveAdminOrCheckPermissionsForCallerLocked( + who, reqPolicy, permissions); return parent ? admin.getParentActiveAdmin() : admin; } @@ -5512,15 +5554,29 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public void setMaximumTimeToLock(ComponentName who, long timeMs, boolean parent) { + public void setMaximumTimeToLock(ComponentName who, String callerPackageName, + long timeMs, boolean parent) { + CallerIdentity caller = getCallerIdentity(who, callerPackageName); if (!mHasFeature) { return; } - Objects.requireNonNull(who, "ComponentName is null"); - final int userHandle = mInjector.userHandleGetCallingUserId(); + if (!isPermissionCheckFlagEnabled()) { + Objects.requireNonNull(who, "ComponentName is null"); + } + int userHandle = mInjector.userHandleGetCallingUserId(); + int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle; synchronized (getLockObject()) { - final ActiveAdmin ap = getActiveAdminForCallerLocked( - who, DeviceAdminInfo.USES_POLICY_FORCE_LOCK, parent); + ActiveAdmin ap; + if (isPermissionCheckFlagEnabled()) { + // TODO: Allow use of USES_POLICY_FORCE_LOCK + ap = enforcePermissionAndGetEnforcingAdmin( + who, MANAGE_DEVICE_POLICY_LOCK, caller.getPackageName(), + affectedUserId).getActiveAdmin(); + } else { + ap = getActiveAdminForCallerLocked( + who, DeviceAdminInfo.USES_POLICY_FORCE_LOCK, parent); + } + if (ap.maximumTimeToUnlock != timeMs) { ap.maximumTimeToUnlock = timeMs; saveSettingsLocked(userHandle); @@ -5528,9 +5584,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } if (SecurityLog.isLoggingEnabled()) { - final int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle; SecurityLog.writeEvent(SecurityLog.TAG_MAX_SCREEN_LOCK_TIMEOUT_SET, - who.getPackageName(), userHandle, affectedUserId, timeMs); + caller.getPackageName(), userHandle, affectedUserId, timeMs); } } @@ -5733,13 +5788,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { final int callingUserId = caller.getUserId(); ComponentName adminComponent = null; synchronized (getLockObject()) { + ActiveAdmin admin; // Make sure the caller has any active admin with the right policy or // the required permission. - final ActiveAdmin admin = getActiveAdminOrCheckPermissionForCallerLocked( - null, - DeviceAdminInfo.USES_POLICY_FORCE_LOCK, - parent, - android.Manifest.permission.LOCK_DEVICE); + if (isPermissionCheckFlagEnabled()) { + admin = getActiveAdminOrCheckPermissionsForCallerLocked( + null, + DeviceAdminInfo.USES_POLICY_FORCE_LOCK, + parent, + Set.of(MANAGE_DEVICE_POLICY_LOCK, LOCK_DEVICE)); + } else { + admin = getActiveAdminOrCheckPermissionForCallerLocked( + null, + DeviceAdminInfo.USES_POLICY_FORCE_LOCK, + parent, + LOCK_DEVICE); + } checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_LOCK_NOW); final long ident = mInjector.binderClearCallingIdentity(); try { @@ -7433,21 +7497,34 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public void setFactoryResetProtectionPolicy(ComponentName who, + public void setFactoryResetProtectionPolicy(ComponentName who, String callerPackageName, @Nullable FactoryResetProtectionPolicy policy) { if (!mHasFeature) { return; } - Preconditions.checkNotNull(who, "ComponentName is null"); - CallerIdentity caller = getCallerIdentity(who); - Preconditions.checkCallAuthorization( - isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller)); + if (!isPermissionCheckFlagEnabled()) { + Preconditions.checkNotNull(who, "ComponentName is null"); + } + CallerIdentity caller = getCallerIdentity(who, callerPackageName); + if (!isPermissionCheckFlagEnabled()) { + Preconditions.checkCallAuthorization( + isDefaultDeviceOwner(caller) + || isProfileOwnerOfOrganizationOwnedDevice(caller)); + } checkCanExecuteOrThrowUnsafe(DevicePolicyManager .OPERATION_SET_FACTORY_RESET_PROTECTION_POLICY); final int frpManagementAgentUid = getFrpManagementAgentUidOrThrow(); synchronized (getLockObject()) { - ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()); + ActiveAdmin admin; + if (isPermissionCheckFlagEnabled()) { + admin = enforcePermissionAndGetEnforcingAdmin( + who, MANAGE_DEVICE_POLICY_FACTORY_RESET, caller.getPackageName(), + UserHandle.USER_ALL) + .getActiveAdmin(); + } else { + admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()); + } admin.mFactoryResetProtectionPolicy = policy; saveSettingsLocked(caller.getUserId()); } @@ -7457,7 +7534,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_FACTORY_RESET_PROTECTION) - .setAdmin(who) + .setAdmin(caller.getPackageName()) .write(); } @@ -7484,7 +7561,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { synchronized (getLockObject()) { if (who == null) { Preconditions.checkCallAuthorization(frpManagementAgentUid == caller.getUid() - || hasCallingPermission(permission.MASTER_CLEAR), + || hasCallingPermission(permission.MASTER_CLEAR) + || hasCallingPermission(MANAGE_DEVICE_POLICY_FACTORY_RESET), "Must be called by the FRP management agent on device"); // TODO(b/261999445): Remove if (isHeadlessFlagEnabled()) { @@ -8770,18 +8848,30 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public void setKeyguardDisabledFeatures(ComponentName who, int which, boolean parent) { + public void setKeyguardDisabledFeatures( + ComponentName who, String callerPackageName, int which, boolean parent) { if (!mHasFeature) { return; } - Objects.requireNonNull(who, "ComponentName is null"); + if (!isPermissionCheckFlagEnabled()) { + Objects.requireNonNull(who, "ComponentName is null"); + } - final CallerIdentity caller = getCallerIdentity(who); + final CallerIdentity caller = getCallerIdentity(who, callerPackageName); final int userHandle = caller.getUserId(); + int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle; synchronized (getLockObject()) { - ActiveAdmin ap = getActiveAdminForCallerLocked( - who, DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES, parent); + ActiveAdmin ap; + if (isPermissionCheckFlagEnabled()) { + // SUPPORT USES_POLICY_DISABLE_KEYGUARD_FEATURES + ap = enforcePermissionAndGetEnforcingAdmin( + who, MANAGE_DEVICE_POLICY_KEYGUARD, caller.getPackageName(), + affectedUserId).getActiveAdmin(); + } else { + ap = getActiveAdminForCallerLocked( + who, DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES, parent); + } if (isManagedProfile(userHandle)) { if (parent) { if (isProfileOwnerOfOrganizationOwnedDevice(caller)) { @@ -8799,13 +8889,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } if (SecurityLog.isLoggingEnabled()) { - final int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle; SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_DISABLED_FEATURES_SET, - who.getPackageName(), userHandle, affectedUserId, which); + caller.getPackageName(), userHandle, affectedUserId, which); } DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_KEYGUARD_DISABLED_FEATURES) - .setAdmin(caller.getComponentName()) + .setAdmin(caller.getPackageName()) .setInt(which) .setStrings(parent ? CALLED_FROM_PARENT : NOT_CALLED_FROM_PARENT) .write(); @@ -10829,17 +10918,31 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public void setTrustAgentConfiguration(ComponentName admin, ComponentName agent, + public void setTrustAgentConfiguration( + ComponentName admin, String callerPackageName, ComponentName agent, PersistableBundle args, boolean parent) { if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return; } - Objects.requireNonNull(admin, "admin is null"); + if (!isPermissionCheckFlagEnabled()) { + Objects.requireNonNull(admin, "admin is null"); + } + CallerIdentity caller = getCallerIdentity(admin, callerPackageName); + Objects.requireNonNull(agent, "agent is null"); - final int userHandle = UserHandle.getCallingUserId(); + int userHandle = UserHandle.getCallingUserId(); synchronized (getLockObject()) { - ActiveAdmin ap = getActiveAdminForCallerLocked(admin, - DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES, parent); + ActiveAdmin ap; + if (isPermissionCheckFlagEnabled()) { + int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle; + // TODO: Support USES_POLICY_DISABLE_KEYGUARD_FEATURES + ap = enforcePermissionAndGetEnforcingAdmin( + admin, MANAGE_DEVICE_POLICY_KEYGUARD, + caller.getPackageName(), affectedUserId).getActiveAdmin(); + } else { + ap = getActiveAdminForCallerLocked(admin, + DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES, parent); + } checkCanExecuteOrThrowUnsafe( DevicePolicyManager.OPERATION_SET_TRUST_AGENT_CONFIGURATION); @@ -11233,23 +11336,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public boolean setPermittedInputMethods(ComponentName who, List packageList, - boolean calledOnParentInstance) { + public boolean setPermittedInputMethods(ComponentName who, String callerPackageName, + List packageList, boolean calledOnParentInstance) { if (!mHasFeature) { return false; } - Objects.requireNonNull(who, "ComponentName is null"); + if (!isPermissionCheckFlagEnabled()) { + Objects.requireNonNull(who, "ComponentName is null"); + } - final CallerIdentity caller = getCallerIdentity(who); - final int userId = getProfileParentUserIfRequested( + CallerIdentity caller = getCallerIdentity(who, callerPackageName); + int userId = getProfileParentUserIfRequested( caller.getUserId(), calledOnParentInstance); if (calledOnParentInstance) { - Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller)); + if (!isPermissionCheckFlagEnabled()) { + Preconditions.checkCallAuthorization( + isProfileOwnerOfOrganizationOwnedDevice(caller)); + } Preconditions.checkArgument(packageList == null || packageList.isEmpty(), "Permitted input methods must allow all input methods or only " + "system input methods when called on the parent instance of an " + "organization-owned device"); - } else { + } else if (!isPermissionCheckFlagEnabled()) { Preconditions.checkCallAuthorization( isDefaultDeviceOwner(caller) || isProfileOwner(caller)); } @@ -11272,15 +11380,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } synchronized (getLockObject()) { - final ActiveAdmin admin = getParentOfAdminIfRequired( - getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), calledOnParentInstance); + ActiveAdmin admin; + if (isPermissionCheckFlagEnabled()) { + admin = enforcePermissionAndGetEnforcingAdmin( + who, MANAGE_DEVICE_POLICY_INPUT_METHODS, + caller.getPackageName(), userId).getActiveAdmin(); + } else { + admin = getParentOfAdminIfRequired( + getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), calledOnParentInstance); + } admin.permittedInputMethods = packageList; saveSettingsLocked(caller.getUserId()); } DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_PERMITTED_INPUT_METHODS) - .setAdmin(who) + .setAdmin(caller.getPackageName()) .setStrings(getStringArrayForLogging(packageList, calledOnParentInstance)) .write(); return true; @@ -11298,24 +11413,39 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public List getPermittedInputMethods(ComponentName who, + public List getPermittedInputMethods(ComponentName who, String callerPackageName, boolean calledOnParentInstance) { if (!mHasFeature) { return null; } - Objects.requireNonNull(who, "ComponentName is null"); + if (!isPermissionCheckFlagEnabled()) { + Objects.requireNonNull(who, "ComponentName is null"); + } - final CallerIdentity caller = getCallerIdentity(who); - if (calledOnParentInstance) { - Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller)); - } else { - Preconditions.checkCallAuthorization( - isDefaultDeviceOwner(caller) || isProfileOwner(caller)); + final CallerIdentity caller = getCallerIdentity(who, callerPackageName); + if (!isPermissionCheckFlagEnabled()) { + if (calledOnParentInstance) { + Preconditions.checkCallAuthorization( + isProfileOwnerOfOrganizationOwnedDevice(caller)); + } else { + Preconditions.checkCallAuthorization( + isDefaultDeviceOwner(caller) || isProfileOwner(caller)); + } } synchronized (getLockObject()) { - final ActiveAdmin admin = getParentOfAdminIfRequired( - getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), calledOnParentInstance); + ActiveAdmin admin; + if (isPermissionCheckFlagEnabled()) { + int affectedUser = calledOnParentInstance ? getProfileParentId( + caller.getUserId()) : caller.getUserId(); + admin = enforcePermissionAndGetEnforcingAdmin( + who, MANAGE_DEVICE_POLICY_INPUT_METHODS, caller.getPackageName(), + affectedUser).getActiveAdmin(); + } else { + admin = getParentOfAdminIfRequired( + getProfileOwnerOrDeviceOwnerLocked( + caller.getUserId()), calledOnParentInstance); + } return admin.permittedInputMethods; } } @@ -18693,11 +18823,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { for (int i = 0; i < exemptions.length; i++) { appOpExemptions[i] = APPLICATION_EXEMPTION_CONSTANTS_TO_APP_OPS.get(exemptions[i]); } - DevicePolicyEventLogger - .createEvent(DevicePolicyEnums.SET_APPLICATION_EXEMPTIONS) - .setAdmin(caller.getPackageName()) - .setStrings(packageName, appOpExemptions) - .write(); +// DevicePolicyEventLogger +// .createEvent(DevicePolicyEnums.SET_APPLICATION_EXEMPTIONS) +// .setAdmin(caller.getPackageName()) +// .setStrings(packageName, appOpExemptions) +// .write(); } @Override @@ -20942,12 +21072,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING, MANAGE_DEVICE_POLICY_MTE, MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, - MANAGE_DEVICE_POLICY_PACKAGE_STATE); + MANAGE_DEVICE_POLICY_PACKAGE_STATE, + MANAGE_DEVICE_POLICY_LOCK, + MANAGE_DEVICE_POLICY_FACTORY_RESET, + MANAGE_DEVICE_POLICY_KEYGUARD); private static final List FINANCED_DEVICE_OWNER_PERMISSIONS = List.of( MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL, MANAGE_DEVICE_POLICY_ACROSS_USERS, MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL, - MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY); + MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY, + MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, + MANAGE_DEVICE_POLICY_FACTORY_RESET, + MANAGE_DEVICE_POLICY_KEYGUARD); private static final List PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE_PERMISSIONS = List.of( MANAGE_DEVICE_POLICY_ACROSS_USERS, @@ -20964,7 +21100,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING, MANAGE_DEVICE_POLICY_MTE, MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, - MANAGE_DEVICE_POLICY_PACKAGE_STATE); + MANAGE_DEVICE_POLICY_PACKAGE_STATE, + MANAGE_DEVICE_POLICY_LOCK, + MANAGE_DEVICE_POLICY_FACTORY_RESET, + MANAGE_DEVICE_POLICY_KEYGUARD); private static final List PROFILE_OWNER_ON_USER_0_PERMISSIONS = List.of( SET_TIME, SET_TIME_ZONE, @@ -20972,7 +21111,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { MANAGE_DEVICE_POLICY_WIPE_DATA, MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, - MANAGE_DEVICE_POLICY_PACKAGE_STATE); + MANAGE_DEVICE_POLICY_PACKAGE_STATE, + MANAGE_DEVICE_POLICY_LOCK, + MANAGE_DEVICE_POLICY_KEYGUARD); private static final List PROFILE_OWNER_PERMISSIONS = List.of( MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL, MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY, @@ -20980,7 +21121,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { MANAGE_DEVICE_POLICY_WIPE_DATA, MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, - MANAGE_DEVICE_POLICY_PACKAGE_STATE); + MANAGE_DEVICE_POLICY_PACKAGE_STATE, + MANAGE_DEVICE_POLICY_LOCK, + MANAGE_DEVICE_POLICY_KEYGUARD); private static final HashMap> DPC_PERMISSIONS = new HashMap<>(); { @@ -20993,10 +21136,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } //TODO(b/254253251) Fill this map in as new permissions are added for policies. - // TODO: Add USES_POLICY_WIPE_DATA -> MANAGE_DEVICE_POLICY_WIPE_DATA - // TODO: Add USES_POLICY_EXPIRE_PASSWORD -> MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS - // TODO: Consider USES_POLICY_WATCH_LOGIN -> MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS - - // is this opening up too much? maybe we need to special case device admin in the checker private static final HashMap ACTIVE_ADMIN_POLICIES = new HashMap<>(); private static final HashMap CROSS_USER_PERMISSIONS = @@ -21013,6 +21152,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING, null); // mte is intrinsically global so there is no cross-user permission CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_MTE, null); + CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_FACTORY_RESET, null); // Organisation identity policy will involve data of other organisations on the device and // therefore the FULL cross-user permission is required. CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY, @@ -21027,6 +21167,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL); CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_PACKAGE_STATE, MANAGE_DEVICE_POLICY_ACROSS_USERS); + CROSS_USER_PERMISSIONS.put( + MANAGE_DEVICE_POLICY_LOCK, MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL); + CROSS_USER_PERMISSIONS.put( + MANAGE_DEVICE_POLICY_KEYGUARD, MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL); } /**