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

Commit 9afde363 authored by Eran Messeri's avatar Eran Messeri
Browse files

DPMS: Enforce password complexity in lockscreen setting

Enforce a lock screen that adheres with the required complexity set by
the admin.

To do this, provide a method to let the Settings code query the
DevicePolicyManager for the effective password complexities that applies
to a user.

Bug: 165573442
Test: Manually, set complexity using TestDPC.
Test: m RunSettingsRoboTests
Change-Id: Ia03aebb725cacc7104d7fd765ae6ab53456e33e0
parent 0a993aac
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -3720,6 +3720,27 @@ public class DevicePolicyManager {
        }
    }
    /**
     * Returns the password complexity that applies to this user, aggregated from other users if
     * necessary (for example, if the DPC has set password complexity requirements on the parent
     * profile DPM instance of a managed profile user, they would apply to the primary user on the
     * device).
     * @hide
     */
    @PasswordComplexity
    public int getAggregatedPasswordComplexityForUser(int userId) {
        if (mService == null) {
            return PASSWORD_COMPLEXITY_NONE;
        }
        try {
            return mService.getAggregatedPasswordComplexityForUser(userId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    /**
     * When called by a profile owner of a managed profile returns true if the profile uses unified
     * challenge with its parent user.
+1 −0
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ interface IDevicePolicyManager {
    int getPasswordComplexity(boolean parent);
    void setRequiredPasswordComplexity(int passwordComplexity, boolean parent);
    int getRequiredPasswordComplexity(boolean parent);
    int getAggregatedPasswordComplexityForUser(int userId);
    boolean isUsingUnifiedPassword(in ComponentName admin);
    int getCurrentFailedPasswordAttempts(int userHandle, boolean parent);
    int getProfileWithMinimumFailedPasswordsForWipe(int userHandle, boolean parent);
+9 −0
Original line number Diff line number Diff line
@@ -311,6 +311,15 @@ public class LockPatternUtils {
        return getDevicePolicyManager().getPasswordMinimumMetrics(userId);
    }

    /**
     * Returns the effective complexity for the user.
     * @param userId  The user to return the complexity for.
     * @return complexity level for the user.
     */
    public @DevicePolicyManager.PasswordComplexity int getRequestedPasswordComplexity(int userId) {
        return getDevicePolicyManager().getAggregatedPasswordComplexityForUser(userId);
    }

    public int getRequestedPasswordQuality(int userId) {
        return getDevicePolicyManager().getPasswordQuality(null, userId);
    }
+26 −1
Original line number Diff line number Diff line
@@ -408,7 +408,8 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils {
    }

    /**
     * Checks if an admin has enforced minimum password quality requirements on the given user.
     * Checks if an admin has enforced minimum password quality or complexity requirements on the
     * given user.
     *
     * @return EnforcedAdmin Object containing the enforced admin component and admin user details,
     * or {@code null} if no quality requirements are set. If the requirements are set by
@@ -428,6 +429,30 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils {
        }

        LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
        final int aggregatedComplexity = dpm.getAggregatedPasswordComplexityForUser(userId);
        if (aggregatedComplexity > DevicePolicyManager.PASSWORD_COMPLEXITY_NONE) {
            // First, check if there's a Device Owner. If so, then only it can apply password
            // complexity requiremnts (there can be no secondary profiles).
            final UserHandle deviceOwnerUser = dpm.getDeviceOwnerUser();
            if (deviceOwnerUser != null) {
                return new EnforcedAdmin(dpm.getDeviceOwnerComponentOnAnyUser(), deviceOwnerUser);
            }

            // The complexity could be enforced by a Profile Owner - either in the current user
            // or the current user is the parent user that is affected by the profile owner.
            for (UserInfo userInfo : UserManager.get(context).getProfiles(userId)) {
                final ComponentName profileOwnerComponent = dpm.getProfileOwnerAsUser(userInfo.id);
                if (profileOwnerComponent != null) {
                    return new EnforcedAdmin(profileOwnerComponent, getUserHandleOf(userInfo.id));
                }
            }

            // Should not get here: A Device Owner or Profile Owner should be found.
            throw new IllegalStateException(
                    String.format("Could not find admin enforcing complexity %d for user %d",
                            aggregatedComplexity, userId));
        }

        if (sProxy.isSeparateProfileChallengeEnabled(lockPatternUtils, userId)) {
            // userId is managed profile and has a separate challenge, only consider
            // the admins in that user.
+17 −12
Original line number Diff line number Diff line
@@ -4203,11 +4203,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            int maxRequiredComplexity = PASSWORD_COMPLEXITY_NONE;
            for (ActiveAdmin admin : admins) {
                adminMetrics.add(admin.mPasswordPolicy.getMinMetrics());
                if (isDeviceOwner(admin) || isProfileOwnerUncheckedLocked(admin.info.getComponent(),
                        admin.getUserHandle().getIdentifier())) {
                    maxRequiredComplexity = Math.max(maxRequiredComplexity,
                            admin.mPasswordComplexity);
                }
                maxRequiredComplexity = Math.max(maxRequiredComplexity, admin.mPasswordComplexity);
            }
            return PasswordMetrics.validatePasswordMetrics(PasswordMetrics.merge(adminMetrics),
                    maxRequiredComplexity, false, metrics).isEmpty();
@@ -4320,14 +4316,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        List<ActiveAdmin> admins = getActiveAdminsForLockscreenPoliciesLocked(userHandle);
        int maxRequiredComplexity = PASSWORD_COMPLEXITY_NONE;
        for (ActiveAdmin admin : admins) {
            final ComponentName adminComponent = admin.info.getComponent();
            final int adminUser = admin.getUserHandle().getIdentifier();
            // Password complexity is only taken into account from DO/PO
            if (isDeviceOwner(adminComponent, adminUser)
                    || isProfileOwnerUncheckedLocked(adminComponent, adminUser)) {
            maxRequiredComplexity = Math.max(maxRequiredComplexity, admin.mPasswordComplexity);
        }
        }
        return maxRequiredComplexity;
    }
@@ -4350,6 +4340,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        }
    }
    @Override
    public int getAggregatedPasswordComplexityForUser(int userId) {
        if (!mHasFeature) {
            return PASSWORD_COMPLEXITY_NONE;
        }
        final CallerIdentity caller = getCallerIdentity();
        Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userId));
        synchronized (getLockObject()) {
            return getEffectivePasswordComplexityRequirementLocked(userId);
        }
    }
    @Override
    public int getCurrentFailedPasswordAttempts(int userHandle, boolean parent) {
        if (!mLockPatternUtils.hasSecureLockScreen()) {