Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 10cee472 authored by Elis Elliott's avatar Elis Elliott
Browse files

Add permission checks for auto time APIs

Fixes: 254647038

Test: android.devicepolicy.cts.TimeTest
Change-Id: I584ceae9bece30f75aeed949e499cf427865c293
parent 80c32681
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -7480,9 +7480,9 @@ package android.app.admin {
    method @Nullable public String getAlwaysOnVpnPackage(@NonNull android.content.ComponentName);
    method @NonNull @WorkerThread public android.os.Bundle getApplicationRestrictions(@Nullable android.content.ComponentName, String);
    method @Deprecated @Nullable public String getApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName);
    method public boolean getAutoTimeEnabled(@NonNull android.content.ComponentName);
    method @RequiresPermission(anyOf={android.Manifest.permission.SET_TIME, "android.permission.QUERY_ADMIN_POLICY"}, conditional=true) public boolean getAutoTimeEnabled(@NonNull android.content.ComponentName);
    method @Deprecated public boolean getAutoTimeRequired();
    method public boolean getAutoTimeZoneEnabled(@NonNull android.content.ComponentName);
    method @RequiresPermission(anyOf={android.Manifest.permission.SET_TIME_ZONE, "android.permission.QUERY_ADMIN_POLICY"}, conditional=true) public boolean getAutoTimeZoneEnabled(@NonNull android.content.ComponentName);
    method @NonNull public java.util.List<android.os.UserHandle> getBindDeviceAdminTargetUsers(@NonNull android.content.ComponentName);
    method public boolean getBluetoothContactSharingDisabled(@NonNull android.content.ComponentName);
    method public boolean getCameraDisabled(@Nullable android.content.ComponentName);
@@ -7627,9 +7627,9 @@ package android.app.admin {
    method public boolean setApplicationHidden(@NonNull android.content.ComponentName, String, boolean);
    method @WorkerThread public void setApplicationRestrictions(@Nullable android.content.ComponentName, String, android.os.Bundle);
    method @Deprecated public void setApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName, @Nullable String) throws android.content.pm.PackageManager.NameNotFoundException;
    method public void setAutoTimeEnabled(@NonNull android.content.ComponentName, boolean);
    method @RequiresPermission(value=android.Manifest.permission.SET_TIME, conditional=true) public void setAutoTimeEnabled(@NonNull android.content.ComponentName, boolean);
    method @Deprecated public void setAutoTimeRequired(@NonNull android.content.ComponentName, boolean);
    method public void setAutoTimeZoneEnabled(@NonNull android.content.ComponentName, boolean);
    method @RequiresPermission(value=android.Manifest.permission.SET_TIME_ZONE, conditional=true) public void setAutoTimeZoneEnabled(@NonNull android.content.ComponentName, boolean);
    method public void setBackupServiceEnabled(@NonNull android.content.ComponentName, boolean);
    method public void setBluetoothContactSharingDisabled(@NonNull android.content.ComponentName, boolean);
    method public void setCameraDisabled(@NonNull android.content.ComponentName, boolean);
@@ -7706,8 +7706,8 @@ package android.app.admin {
    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 public boolean setTime(@NonNull android.content.ComponentName, long);
    method public boolean setTimeZone(@NonNull android.content.ComponentName, String);
    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);
+55 −20
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@
package android.app.admin;
import static android.Manifest.permission.QUERY_ADMIN_POLICY;
import static android.Manifest.permission.SET_TIME;
import static android.Manifest.permission.SET_TIME_ZONE;
import static android.content.Intent.LOCAL_FLAG_FROM_SYSTEM;
import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
@@ -8461,8 +8464,10 @@ public class DevicePolicyManager {
    }
    /**
     * Called by a device owner, a profile owner for the primary user or a profile
     * owner of an organization-owned managed profile to turn auto time on and off.
     * Called by a device owner, a profile owner for the primary user, a profile
     * owner of an organization-owned managed profile or, starting from Android
     * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, holders of the permission
     * {@link android.Manifest.permission#SET_TIME} to turn auto time on and off.
     * Callers are recommended to use {@link UserManager#DISALLOW_CONFIG_DATE_TIME}
     * to prevent the user from changing this setting.
     * <p>
@@ -8473,8 +8478,10 @@ public class DevicePolicyManager {
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param enabled Whether time should be obtained automatically from the network or not.
     * @throws SecurityException if caller is not a device owner, a profile owner for the
     * primary user, or a profile owner of an organization-owned managed profile.
     * primary user, or a profile owner of an organization-owned managed profile or a holder of the
     * permission {@link android.Manifest.permission#SET_TIME}.
     */
    @RequiresPermission(value = SET_TIME, conditional = true)
    public void setAutoTimeEnabled(@NonNull ComponentName admin, boolean enabled) {
        if (mService != null) {
            try {
@@ -8486,10 +8493,18 @@ public class DevicePolicyManager {
    }
    /**
     * Returns true if auto time is enabled on the device.
     *
     * <p> Starting from Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, callers
     * are also able to call this method if they hold the permission
     *{@link android.Manifest.permission#SET_TIME}.
     *
     * @return true if auto time is enabled on the device.
     * @throws SecurityException if caller is not a device owner, a profile owner for the
     * primary user, or a profile owner of an organization-owned managed profile.
     * @throws SecurityException if the caller is not a device owner, a profile
     * owner for the primary user, or a profile owner of an organization-owned managed profile or a
     * holder of the permission {@link android.Manifest.permission#SET_TIME}.
     */
    @RequiresPermission(anyOf = {SET_TIME, QUERY_ADMIN_POLICY}, conditional = true)
    public boolean getAutoTimeEnabled(@NonNull ComponentName admin) {
        if (mService != null) {
            try {
@@ -8502,8 +8517,10 @@ public class DevicePolicyManager {
    }
    /**
     * Called by a device owner, a profile owner for the primary user or a profile
     * owner of an organization-owned managed profile to turn auto time zone on and off.
     * Called by a device owner, a profile owner for the primary user, a profile
     * owner of an organization-owned managed profile or, starting from Android
     * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, holders of the permission
     * {@link android.Manifest.permission#SET_TIME} to turn auto time zone on and off.
     * Callers are recommended to use {@link UserManager#DISALLOW_CONFIG_DATE_TIME}
     * to prevent the user from changing this setting.
     * <p>
@@ -8514,8 +8531,10 @@ public class DevicePolicyManager {
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param enabled Whether time zone should be obtained automatically from the network or not.
     * @throws SecurityException if caller is not a device owner, a profile owner for the
     * primary user, or a profile owner of an organization-owned managed profile.
     * primary user, or a profile owner of an organization-owned managed profile or a holder of the
     * permission {@link android.Manifest.permission#SET_TIME_ZONE}.
     */
    @RequiresPermission(value = SET_TIME_ZONE, conditional = true)
    public void setAutoTimeZoneEnabled(@NonNull ComponentName admin, boolean enabled) {
        throwIfParentInstance("setAutoTimeZone");
        if (mService != null) {
@@ -8528,10 +8547,18 @@ public class DevicePolicyManager {
    }
    /**
     * Returns true if auto time zone is enabled on the device.
     *
     * <p> Starting from Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, callers
     * are also able to call this method if they hold the permission
     *{@link android.Manifest.permission#SET_TIME}.
     *
     * @return true if auto time zone is enabled on the device.
     * @throws SecurityException if caller is not a device owner, a profile owner for the
     * primary user, or a profile owner of an organization-owned managed profile.
     * @throws SecurityException if the caller is not a device owner, a profile
     * owner for the primary user, or a profile owner of an organization-owned managed profile or a
     * holder of the permission {@link android.Manifest.permission#SET_TIME_ZONE}.
     */
    @RequiresPermission(anyOf = {SET_TIME_ZONE, QUERY_ADMIN_POLICY}, conditional = true)
    public boolean getAutoTimeZoneEnabled(@NonNull ComponentName admin) {
        throwIfParentInstance("getAutoTimeZone");
        if (mService != null) {
@@ -11669,17 +11696,21 @@ public class DevicePolicyManager {
    }
    /**
     * Called by a device owner or a profile owner of an organization-owned managed
     * profile to set the system wall clock time. This only takes effect if called when
     * {@link android.provider.Settings.Global#AUTO_TIME} is 0, otherwise {@code false}
     * will be returned.
     * Called by a device owner, a profile owner of an organization-owned managed
     * profile or, starting from Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
     * holders of the permission {@link android.Manifest.permission#SET_TIME} to set the system wall
     * clock time. This only takes effect if called when
     * {@link android.provider.Settings.Global#AUTO_TIME} is 0, otherwise {@code false} will be
     * returned.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with
     * @param millis time in milliseconds since the Epoch
     * @return {@code true} if set time succeeded, {@code false} otherwise.
     * @throws SecurityException if {@code admin} is not a device owner or a profile owner
     * of an organization-owned managed profile.
     * of an organization-owned managed profile or a holder of the permission
     * {@link android.Manifest.permission#SET_TIME}.
     */
    @RequiresPermission(value = SET_TIME, conditional = true)
    public boolean setTime(@NonNull ComponentName admin, long millis) {
        throwIfParentInstance("setTime");
        if (mService != null) {
@@ -11693,10 +11724,12 @@ public class DevicePolicyManager {
    }
    /**
     * Called by a device owner or a profile owner of an organization-owned managed
     * profile to set the system's persistent default time zone. This only takes
     * effect if called when {@link android.provider.Settings.Global#AUTO_TIME_ZONE}
     * is 0, otherwise {@code false} will be returned.
     * Called by a device owner, a profile owner of an organization-owned managed
     * profile or, starting from Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
     * holders of the permission {@link android.Manifest.permission#SET_TIME_ZONE} to set the
     * system's persistent default time zone. This only take effect if called when
     * {@link android.provider.Settings.Global#AUTO_TIME_ZONE} is 0, otherwise {@code false} will be
     * returned.
     *
     * @see android.app.AlarmManager#setTimeZone(String)
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with
@@ -11704,8 +11737,10 @@ public class DevicePolicyManager {
     *     {@link java.util.TimeZone#getAvailableIDs}
     * @return {@code true} if set timezone succeeded, {@code false} otherwise.
     * @throws SecurityException if {@code admin} is not a device owner or a profile owner
     * of an organization-owned managed profile.
     * of an organization-owned managed profile or a holder of the permissions
     * {@link android.Manifest.permission#SET_TIME_ZONE}.
     */
    @RequiresPermission(value = SET_TIME_ZONE, conditional = true)
    public boolean setTimeZone(@NonNull ComponentName admin, String timeZone) {
        throwIfParentInstance("setTimeZone");
        if (mService != null) {
+83 −22
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ 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.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.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.AppOpsManager.MODE_ALLOWED;
@@ -719,7 +721,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                    + "management app's authentication policy";
    private static final String NOT_SYSTEM_CALLER_MSG = "Only the system can %s";
    private static final String PERMISSION_BASED_ACCESS_EXPERIMENT_FLAG =
            "enable_permission_based_access";
    private static final String ENABLE_COEXISTENCE_FLAG = "enable_coexistence";
    private static final boolean DEFAULT_VALUE_PERMISSION_BASED_ACCESS_FLAG = false;
    private static final boolean DEFAULT_ENABLE_COEXISTENCE_FLAG = false;
    // TODO(b/258425381) remove the flag after rollout.
@@ -7964,9 +7969,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        Objects.requireNonNull(who, "ComponentName is null");
        final CallerIdentity caller = getCallerIdentity(who);
        Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
                || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(caller));
        if (isPermissionCheckFlagEnabled()) {
            // The effect of this policy is device-wide.
            enforcePermission(SET_TIME, UserHandle.USER_ALL);
        } else {
            Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
                    || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(
                    caller));
        }
        mInjector.binderWithCleanCallingIdentity(() ->
                mInjector.settingsGlobalPutInt(Settings.Global.AUTO_TIME, enabled ? 1 : 0));
@@ -7988,8 +7999,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        Objects.requireNonNull(who, "ComponentName is null");
        final CallerIdentity caller = getCallerIdentity(who);
        if (isPermissionCheckFlagEnabled()) {
            enforceCanQuery(SET_TIME, UserHandle.USER_ALL);
        } else {
            Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
                || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(caller));
                    || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(
                    caller));
        }
        return mInjector.settingsGlobalGetInt(Global.AUTO_TIME, 0) > 0;
    }
@@ -8005,8 +8022,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        Objects.requireNonNull(who, "ComponentName is null");
        final CallerIdentity caller = getCallerIdentity(who);
        if (isPermissionCheckFlagEnabled()) {
            // The effect of this policy is device-wide.
            enforcePermission(SET_TIME_ZONE, UserHandle.USER_ALL);
        } else {
            Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
                || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(caller));
                    || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(
                    caller));
        }
        if (isCoexistenceEnabled(caller)) {
            mDevicePolicyEngine.setGlobalPolicy(
@@ -8038,8 +8062,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        Objects.requireNonNull(who, "ComponentName is null");
        final CallerIdentity caller = getCallerIdentity(who);
        if (isPermissionCheckFlagEnabled()) {
            // The effect of this policy is device-wide.
            enforceCanQuery(SET_TIME_ZONE, UserHandle.USER_ALL);
        } else {
            Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
                || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(caller));
                    || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(
                    caller));
        }
        return mInjector.settingsGlobalGetInt(Global.AUTO_TIME_ZONE, 0) > 0;
    }
@@ -12772,8 +12803,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        Objects.requireNonNull(who, "ComponentName is null");
        final CallerIdentity caller = getCallerIdentity(who);
        if (isPermissionCheckFlagEnabled()) {
            // This is a global action.
            enforcePermission(SET_TIME, UserHandle.USER_ALL);
        } else {
            Preconditions.checkCallAuthorization(
                isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller));
                    isDefaultDeviceOwner(caller)
                            || isProfileOwnerOfOrganizationOwnedDevice(caller));
        }
        // Don't allow set time when auto time is on.
        if (mInjector.settingsGlobalGetInt(Global.AUTO_TIME, 0) == 1) {
@@ -12792,8 +12829,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        Objects.requireNonNull(who, "ComponentName is null");
        final CallerIdentity caller = getCallerIdentity(who);
        if (isPermissionCheckFlagEnabled()) {
            // This is a global action.
            enforcePermission(SET_TIME_ZONE, UserHandle.USER_ALL);
        } else {
            Preconditions.checkCallAuthorization(
                isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller));
                    isDefaultDeviceOwner(caller)
                            || isProfileOwnerOfOrganizationOwnedDevice(caller));
        }
        // Don't allow set timezone when auto timezone is on.
        if (mInjector.settingsGlobalGetInt(Global.AUTO_TIME_ZONE, 0) == 1) {
@@ -19258,7 +19301,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    private static final List<String> DEFAULT_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_ACROSS_USERS_SECURITY_CRITICAL,
            SET_TIME,
            SET_TIME_ZONE);
    private static final List<String> FINANCED_DEVICE_OWNER_PERMISSIONS = List.of(
            MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL,
            MANAGE_DEVICE_POLICY_ACROSS_USERS,
@@ -19266,12 +19311,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    private static final List<String> PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE_PERMISSIONS =
            List.of(
                MANAGE_DEVICE_POLICY_ACROSS_USERS,
                MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL);
    private static final List<String> PROFILE_OWNER_ON_USER_0_PERMISSIONS  = List.of();
                MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL,
                SET_TIME,
                SET_TIME_ZONE);
    private static final List<String> PROFILE_OWNER_ON_USER_0_PERMISSIONS  = List.of(
            SET_TIME,
            SET_TIME_ZONE);
    private static final List<String> PROFILE_OWNER_PERMISSIONS  = List.of(
            MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL);
    private static final HashMap<Integer, List<String>> DPC_PERMISSIONS = new HashMap<>();
    {
        DPC_PERMISSIONS.put(DEFAULT_DEVICE_OWNER, DEFAULT_DEVICE_OWNER_PERMISSIONS);
@@ -19285,7 +19333,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    //TODO(b/254253251) Fill this map in as new permissions are added for policies.
    private static final HashMap<String, Integer> ACTIVE_ADMIN_POLICIES = new HashMap<>();
    private static final HashMap<String, String> CROSS_USER_PERMISSIONS = new HashMap<>();
    private static final HashMap<String, String> CROSS_USER_PERMISSIONS =
            new HashMap<>();
    {
        // Auto time 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);
    }
    /**
     * Checks if the calling process has been granted permission to apply a device policy on a
@@ -19335,12 +19389,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
     * @param targetUserId The userId of the user which the caller needs permission to act on.
     */
    private boolean hasPermission(String permission, int targetUserId) {
        boolean hasPermission = hasPermission(permission);
        if (getCallerIdentity().getUserId() != targetUserId) {
            hasPermission = hasPermission
                    && hasPermission(CROSS_USER_PERMISSIONS.get(permission));
        boolean hasPermissionOnOwnUser = hasPermission(permission);
        boolean hasPermissionOnTargetUser = true;
        if (hasPermissionOnOwnUser & getCallerIdentity().getUserId() != targetUserId) {
            hasPermissionOnTargetUser = hasPermission(CROSS_USER_PERMISSIONS.get(permission));
        }
        return hasPermission;
        return hasPermissionOnOwnUser && hasPermissionOnTargetUser;
    }
    /**
@@ -19415,6 +19469,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        return false;
    }
    private boolean isPermissionCheckFlagEnabled() {
        return DeviceConfig.getBoolean(
                NAMESPACE_DEVICE_POLICY_MANAGER,
                PERMISSION_BASED_ACCESS_EXPERIMENT_FLAG,
                DEFAULT_VALUE_PERMISSION_BASED_ACCESS_FLAG);
    }
    // TODO(b/260560985): properly gate coexistence changes
    private boolean isCoexistenceEnabled(CallerIdentity caller) {
        return isCoexistenceFlagEnabled()