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

Commit 7b649b92 authored by Elis Elliott's avatar Elis Elliott
Browse files

Add method to return an EnforcingAdmin after checking the caller's

permissions.

Fixes: 254652444

Test: atest com.android.server.devicepolicy.DevicePolicyManagerTest#testSetOrganizationName_financeDo_success
Change-Id: Ibc72fb41dae5361ae5801ccc718c2d6d5c0517f7
parent 9f8f4db9
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -7570,7 +7570,7 @@ package android.app.admin {
    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 public CharSequence getOrganizationName(@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<android.telephony.data.ApnSetting> 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();
@@ -7724,7 +7724,7 @@ package android.app.admin {
    method public void setNetworkLoggingEnabled(@Nullable android.content.ComponentName, boolean);
    method @Deprecated public void setOrganizationColor(@NonNull android.content.ComponentName, int);
    method public void setOrganizationId(@NonNull String);
    method public void setOrganizationName(@NonNull android.content.ComponentName, @Nullable CharSequence);
    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);
+27 −13
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.app.admin;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY;
import static android.Manifest.permission.QUERY_ADMIN_POLICY;
import static android.Manifest.permission.SET_TIME;
import static android.Manifest.permission.SET_TIME_ZONE;
@@ -13410,18 +13411,24 @@ public class DevicePolicyManager {
    }
    /**
     * Called by the device owner (since API 26) or profile owner (since API 24) to set the name of
     * the organization under management.
     * Called by the device owner (since API 26) or profile owner (since API 24) or, starting from
     * Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
     * holders of the permission
     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY} to set the
     * name of the organization under management.
     *
     * <p>If the organization name needs to be localized, it is the responsibility of the {@link
     * DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast and set
     * a new version of this string accordingly.
     * <p>If the organization name needs to be localized, it is the responsibility of the caller
     * to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast and set a new version of this
     * string accordingly.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with or can be
     * {@code null} if accessing with a permission without association with a DeviceAdminReceiver.
     * @param title The organization name or {@code null} to clear a previously set name.
     * @throws SecurityException if {@code admin} is not a device or profile owner.
     * @throws SecurityException if {@code admin} is not a device or profile owner or holder of the
     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY}.
     */
    public void setOrganizationName(@NonNull ComponentName admin, @Nullable CharSequence title) {
    @RequiresPermission(MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY)
    public void setOrganizationName(@Nullable ComponentName admin, @Nullable CharSequence title) {
        throwIfParentInstance("setOrganizationName");
        try {
            mService.setOrganizationName(admin, title);
@@ -13431,14 +13438,21 @@ public class DevicePolicyManager {
    }
    /**
     * Called by a profile owner of a managed profile to retrieve the name of the organization under
     * management.
     * Called by the device owner (since API 26) or profile owner (since API 24) or, starting from
     * Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
     * holders of the permission
     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY
     * to retrieve the name of the organization under management.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with or can be
     * {@code null} if accessing with a permission without association with a DeviceAdminReceiver.
     * @return The organization name or {@code null} if none is set.
     * @throws SecurityException if {@code admin} is not a profile owner.
     * @throws SecurityException if {@code admin} if {@code admin} is not a device or profile
     * owner or holder of the
     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY}.
     */
    public @Nullable CharSequence getOrganizationName(@NonNull ComponentName admin) {
    @RequiresPermission(MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY)
    public @Nullable CharSequence getOrganizationName(@Nullable ComponentName admin) {
        throwIfParentInstance("getOrganizationName");
        try {
            return mService.getOrganizationName(admin);
+111 −24
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ 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_ORGANIZATION_IDENTITY;
import static android.Manifest.permission.QUERY_ADMIN_POLICY;
import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
import static android.Manifest.permission.SET_TIME;
@@ -15257,16 +15258,27 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    }
    @Override
    public void setOrganizationName(@NonNull ComponentName who, CharSequence text) {
    public void setOrganizationName(@Nullable ComponentName who, CharSequence text) {
        if (!mHasFeature) {
            return;
        }
        Objects.requireNonNull(who, "ComponentName is null");
        final CallerIdentity caller = getCallerIdentity(who);
        CallerIdentity caller = getCallerIdentity(who);
        ActiveAdmin admin = null;
        if (isPermissionCheckFlagEnabled()) {
            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
                    who,
                    MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY,
                    caller.getUserId());
            admin = enforcingAdmin.getActiveAdmin();
        } else {
            Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
        }
        synchronized (getLockObject()) {
            ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId());
            if (!isPermissionCheckFlagEnabled()) {
                admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId());
            }
            if (!TextUtils.equals(admin.organizationName, text)) {
                admin.organizationName = (text == null || text.length() == 0)
                        ? null : text.toString();
@@ -15276,20 +15288,29 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    }
    @Override
    public CharSequence getOrganizationName(@NonNull ComponentName who) {
    public CharSequence getOrganizationName(@Nullable ComponentName who) {
        if (!mHasFeature) {
            return null;
        }
        Objects.requireNonNull(who, "ComponentName is null");
        CallerIdentity caller = getCallerIdentity(who);
        ActiveAdmin admin = null;
        final CallerIdentity caller = getCallerIdentity(who);
        if (isPermissionCheckFlagEnabled()) {
            EnforcingAdmin enforcingAdmin = enforceCanQueryAndGetEnforcingAdmin(
                    who,
                    MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY,
                    caller.getUserId());
            admin = enforcingAdmin.getActiveAdmin();
        } else {
            Preconditions.checkCallingUser(isManagedProfile(caller.getUserId()));
            Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
            synchronized (getLockObject()) {
            ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId());
            return admin.organizationName;
                admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId());
            }
        }
        return admin.organizationName;
    }
    /**
@@ -19910,22 +19931,26 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            MANAGE_DEVICE_POLICY_ACROSS_USERS,
            MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL,
            SET_TIME,
            SET_TIME_ZONE);
            SET_TIME_ZONE,
            MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY);
    private static final List<String> 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_ACROSS_USERS_SECURITY_CRITICAL,
            MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY);
    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,
                SET_TIME,
                SET_TIME_ZONE);
                SET_TIME_ZONE,
                MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY);
    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);
            MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL,
            MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY);
    private static final HashMap<Integer, List<String>> DPC_PERMISSIONS = new HashMap<>();
    {
@@ -19943,9 +19968,48 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    private static final HashMap<String, String> CROSS_USER_PERMISSIONS =
            new HashMap<>();
    {
        // Auto time is intrinsically global so there is no cross-user permission.
        // 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);
        // 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);
    }
    /**
     * Checks if the calling process has been granted permission to apply a device policy on a
     * specific user.
     * The given permission will be checked along with its associated cross-user permission if it
     * exists and the target user is different to the calling user.
     * Returns the {@link ActiveAdmin} of the caller.
     *
     * @param permission The name of the permission being checked.
     * @param targetUserId The userId of the user which the caller needs permission to act on.
     * @throws SecurityException if the caller has not been granted the given permission,
     * the associated cross-user permission if the caller's user is different to the target user.
     */
    private EnforcingAdmin enforcePermissionAndGetEnforcingAdmin(@Nullable ComponentName admin,
            String permission, int targetUserId) {
        enforcePermission(permission, targetUserId);
        return getEnforcingAdminForCaller(admin, getCallerIdentity());
    }
    /**
     * Checks whether the calling process has been granted permission to query a device policy on
     * a specific user.
     * The given permission will be checked along with its associated cross-user permission if it
     * exists and the target user is different to the calling user.
     *
     * @param permission The name of the permission being checked.
     * @param targetUserId The userId of the user which the caller needs permission to act on.
     * @throws SecurityException if the caller has not been granted the given permission,
     * the associated cross-user permission if the caller's user is different to the target user.
     */
    private EnforcingAdmin enforceCanQueryAndGetEnforcingAdmin(@Nullable ComponentName admin,
            String permission, int targetUserId) {
        enforceCanQuery(permission, targetUserId);
        return getEnforcingAdminForCaller(admin, getCallerIdentity());
    }
    /**
@@ -19957,7 +20021,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
     * @param permission The name of the permission being checked.
     * @param targetUserId The userId of the user which the caller needs permission to act on.
     * @throws SecurityException if the caller has not been granted the given permission,
     * the associtated cross-user permission if the caller's user is different to the target user.
     * the associated cross-user permission if the caller's user is different to the target user.
     */
    private void enforcePermission(String permission, int targetUserId)
            throws SecurityException {
@@ -19972,13 +20036,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    }
    /**
     * Return whether the calling process has been granted permission to query a device policy on
     * Checks whether the calling process has been granted permission to query a device policy on
     * a specific user.
     * The given permission will be checked along with its associated cross-user permission if it
     * exists and the target user is different to the calling user.
     *
     * @param permission The name of the permission being checked.
     * @param targetUserId The userId of the user which the caller needs permission to act on.
     * @throws SecurityException if the caller has not been granted the given permission,
     * the associatated cross-user permission if the caller's user is different to the target user
     * the associated cross-user permission if the caller's user is different to the target user
     * and if the user has not been granted {@link QUERY_ADMIN_POLICY}.
     */
    private void enforceCanQuery(String permission, int targetUserId) throws SecurityException {
@@ -20043,10 +20109,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        }
        // Check if the caller is an active admin that uses a certain policy.
        if (ACTIVE_ADMIN_POLICIES.containsKey(permission)) {
            try {
                return getActiveAdminForCallerLocked(
                        null, ACTIVE_ADMIN_POLICIES.get(permission), false) != null;
            } catch (SecurityException e) {
                // A security exception means there is not an active admin with permission and
                // therefore
                return false;
            }
        }
        return false;
    }
@@ -20076,6 +20147,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        return false;
    }
    private EnforcingAdmin getEnforcingAdminForCaller(@Nullable ComponentName who,
            CallerIdentity caller) {
        int userId = caller.getUserId();
        ActiveAdmin admin = null;
        synchronized (getLockObject()) {
            admin = getActiveAdminUncheckedLocked(who, userId);
        }
        if (isDeviceOwner(caller) || isProfileOwner(caller)) {
            return EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userId, admin);
        }
        if (getActiveAdminUncheckedLocked(who, userId) != null) {
            return EnforcingAdmin.createDeviceAdminEnforcingAdmin(who, userId, admin);
        }
        return  EnforcingAdmin.createEnforcingAdmin(caller.getPackageName(), userId);
    }
    private boolean isPermissionCheckFlagEnabled() {
        return DeviceConfig.getBoolean(
                NAMESPACE_DEVICE_POLICY_MANAGER,
+30 −4
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ final class EnforcingAdmin {
    private Set<String> mAuthorities;
    private final int mUserId;
    private final boolean mIsRoleAuthority;
    private final ActiveAdmin mActiveAdmin;

    static EnforcingAdmin createEnforcingAdmin(@NonNull String packageName, int userId) {
        Objects.requireNonNull(packageName);
@@ -73,14 +74,31 @@ final class EnforcingAdmin {
            @NonNull ComponentName componentName, int userId) {
        Objects.requireNonNull(componentName);
        return new EnforcingAdmin(
                componentName.getPackageName(), componentName, Set.of(DPC_AUTHORITY), userId);
                componentName.getPackageName(), componentName, Set.of(DPC_AUTHORITY), userId,
                /* activeAdmin=*/ null);
    }

    static EnforcingAdmin createEnterpriseEnforcingAdmin(
            @NonNull ComponentName componentName, int userId, ActiveAdmin activeAdmin) {
        Objects.requireNonNull(componentName);
        return new EnforcingAdmin(
                componentName.getPackageName(), componentName, Set.of(DPC_AUTHORITY), userId,
                activeAdmin);
    }

    static EnforcingAdmin createDeviceAdminEnforcingAdmin(ComponentName componentName, int userId) {
        Objects.requireNonNull(componentName);
        return new EnforcingAdmin(
                componentName.getPackageName(), componentName, Set.of(DEVICE_ADMIN_AUTHORITY),
                userId);
                userId, /* activeAdmin=*/ null);
    }

    static EnforcingAdmin createDeviceAdminEnforcingAdmin(ComponentName componentName, int userId,
            ActiveAdmin activeAdmin) {
        Objects.requireNonNull(componentName);
        return new EnforcingAdmin(
                componentName.getPackageName(), componentName, Set.of(DEVICE_ADMIN_AUTHORITY),
                userId, activeAdmin);
    }

    static String getRoleAuthorityOf(String roleName) {
@@ -88,7 +106,8 @@ final class EnforcingAdmin {
    }

    private EnforcingAdmin(
            String packageName, ComponentName componentName, Set<String> authorities, int userId) {
            String packageName, ComponentName componentName, Set<String> authorities, int userId,
            ActiveAdmin activeAdmin) {
        Objects.requireNonNull(packageName);
        Objects.requireNonNull(componentName);
        Objects.requireNonNull(authorities);
@@ -99,6 +118,7 @@ final class EnforcingAdmin {
        mComponentName = componentName;
        mAuthorities = new HashSet<>(authorities);
        mUserId = userId;
        mActiveAdmin = activeAdmin;
    }

    private EnforcingAdmin(String packageName, int userId) {
@@ -111,6 +131,7 @@ final class EnforcingAdmin {
        mComponentName = null;
        // authorities will be loaded when needed
        mAuthorities = null;
        mActiveAdmin = null;
    }

    private static Set<String> getRoleAuthoritiesOrDefault(String packageName, int userId) {
@@ -156,6 +177,11 @@ final class EnforcingAdmin {
        return mUserId;
    }

    @Nullable
    public ActiveAdmin getActiveAdmin() {
        return mActiveAdmin;
    }

    /**
     * For two EnforcingAdmins to be equal they must:
     *
@@ -224,7 +250,7 @@ final class EnforcingAdmin {
            String className = parser.getAttributeValue(/* namespace= */ null, ATTR_CLASS_NAME);
            ComponentName componentName = new ComponentName(packageName, className);
            Set<String> authorities = Set.of(authoritiesStr.split(ATTR_AUTHORITIES_SEPARATOR));
            return new EnforcingAdmin(packageName, componentName, authorities, userId);
            return new EnforcingAdmin(packageName, componentName, authorities, userId, null);
        }
    }