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

Commit 64247a16 authored by Pavel Grafov's avatar Pavel Grafov Committed by Android (Google) Code Review
Browse files

Merge "Throw if admin sets password constraints that have no effect."

parents b1c0a256 26fccb7d
Loading
Loading
Loading
Loading
+51 −9
Original line number Diff line number Diff line
@@ -2678,7 +2678,10 @@ public class DevicePolicyManager {
     * only imposed if the administrator has also requested either {@link #PASSWORD_QUALITY_NUMERIC}
     * , {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX}, {@link #PASSWORD_QUALITY_ALPHABETIC},
     * {@link #PASSWORD_QUALITY_ALPHANUMERIC}, or {@link #PASSWORD_QUALITY_COMPLEX} with
     * {@link #setPasswordQuality}.
     * {@link #setPasswordQuality}. If an app targeting SDK level
     * {@link android.os.Build.VERSION_CODES#R} and above enforces this constraint without settings
     * password quality to one of these values first, this method will throw
     * {@link IllegalStateException}.
     * <p>
     * On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
     * password is always treated as empty.
@@ -2696,6 +2699,9 @@ public class DevicePolicyManager {
     *     restriction.
     * @throws SecurityException if {@code admin} is not an active administrator or {@code admin}
     *     does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
     * @throws IllegalStateException if the calling app is targeting SDK level
     *     {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password
     *     quality requirement prior to calling this method.
     */
    public void setPasswordMinimumLength(@NonNull ComponentName admin, int length) {
        if (mService != null) {
@@ -2747,7 +2753,10 @@ public class DevicePolicyManager {
     * place immediately. To prompt the user for a new password, use
     * {@link #ACTION_SET_NEW_PASSWORD} or {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after
     * setting this value. This constraint is only imposed if the administrator has also requested
     * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The default value is 0.
     * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. If an app targeting
     * SDK level {@link android.os.Build.VERSION_CODES#R} and above enforces this constraint without
     * settings password quality to {@link #PASSWORD_QUALITY_COMPLEX} first, this method will throw
     * {@link IllegalStateException}. The default value is 0.
     * <p>
     * On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
     * password is always treated as empty.
@@ -2765,6 +2774,9 @@ public class DevicePolicyManager {
     *            A value of 0 means there is no restriction.
     * @throws SecurityException if {@code admin} is not an active administrator or {@code admin}
     *             does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
     * @throws IllegalStateException if the calling app is targeting SDK level
     *     {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password
     *     quality requirement prior to calling this method.
     */
    public void setPasswordMinimumUpperCase(@NonNull ComponentName admin, int length) {
        if (mService != null) {
@@ -2823,7 +2835,10 @@ public class DevicePolicyManager {
     * place immediately. To prompt the user for a new password, use
     * {@link #ACTION_SET_NEW_PASSWORD} or {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after
     * setting this value. This constraint is only imposed if the administrator has also requested
     * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The default value is 0.
     * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. If an app targeting
     * SDK level {@link android.os.Build.VERSION_CODES#R} and above enforces this constraint without
     * settings password quality to {@link #PASSWORD_QUALITY_COMPLEX} first, this method will throw
     * {@link IllegalStateException}. The default value is 0.
     * <p>
     * On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
     * password is always treated as empty.
@@ -2841,6 +2856,9 @@ public class DevicePolicyManager {
     *            A value of 0 means there is no restriction.
     * @throws SecurityException if {@code admin} is not an active administrator or {@code admin}
     *             does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
     * @throws IllegalStateException if the calling app is targeting SDK level
     *     {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password
     *     quality requirement prior to calling this method.
     */
    public void setPasswordMinimumLowerCase(@NonNull ComponentName admin, int length) {
        if (mService != null) {
@@ -2899,7 +2917,10 @@ public class DevicePolicyManager {
     * immediately. To prompt the user for a new password, use {@link #ACTION_SET_NEW_PASSWORD} or
     * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This constraint is
     * only imposed if the administrator has also requested {@link #PASSWORD_QUALITY_COMPLEX} with
     * {@link #setPasswordQuality}. The default value is 1.
     * {@link #setPasswordQuality}. If an app targeting SDK level
     * {@link android.os.Build.VERSION_CODES#R} and above enforces this constraint without settings
     * password quality to {@link #PASSWORD_QUALITY_COMPLEX} first, this method will throw
     * {@link IllegalStateException}. The default value is 1.
     * <p>
     * On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
     * password is always treated as empty.
@@ -2917,6 +2938,9 @@ public class DevicePolicyManager {
     *            0 means there is no restriction.
     * @throws SecurityException if {@code admin} is not an active administrator or {@code admin}
     *             does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
     * @throws IllegalStateException if the calling app is targeting SDK level
     *     {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password
     *     quality requirement prior to calling this method.
     */
    public void setPasswordMinimumLetters(@NonNull ComponentName admin, int length) {
        if (mService != null) {
@@ -2974,7 +2998,10 @@ public class DevicePolicyManager {
     * place immediately. To prompt the user for a new password, use
     * {@link #ACTION_SET_NEW_PASSWORD} or {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after
     * setting this value. This constraint is only imposed if the administrator has also requested
     * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The default value is 1.
     * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. If an app targeting
     * SDK level {@link android.os.Build.VERSION_CODES#R} and above enforces this constraint without
     * settings password quality to {@link #PASSWORD_QUALITY_COMPLEX} first, this method will throw
     * {@link IllegalStateException}. The default value is 1.
     * <p>
     * On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
     * password is always treated as empty.
@@ -2992,6 +3019,9 @@ public class DevicePolicyManager {
     *            value of 0 means there is no restriction.
     * @throws SecurityException if {@code admin} is not an active administrator or {@code admin}
     *             does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
     * @throws IllegalStateException if the calling app is targeting SDK level
     *     {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password
     *     quality requirement prior to calling this method.
     */
    public void setPasswordMinimumNumeric(@NonNull ComponentName admin, int length) {
        if (mService != null) {
@@ -3049,7 +3079,10 @@ public class DevicePolicyManager {
     * immediately. To prompt the user for a new password, use {@link #ACTION_SET_NEW_PASSWORD} or
     * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This constraint is
     * only imposed if the administrator has also requested {@link #PASSWORD_QUALITY_COMPLEX} with
     * {@link #setPasswordQuality}. The default value is 1.
     * {@link #setPasswordQuality}. If an app targeting SDK level
     * {@link android.os.Build.VERSION_CODES#R} and above enforces this constraint without settings
     * password quality to {@link #PASSWORD_QUALITY_COMPLEX} first, this method will throw
     * {@link IllegalStateException}. The default value is 1.
     * <p>
     * On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
     * password is always treated as empty.
@@ -3067,6 +3100,9 @@ public class DevicePolicyManager {
     *            0 means there is no restriction.
     * @throws SecurityException if {@code admin} is not an active administrator or {@code admin}
     *             does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
     * @throws IllegalStateException if the calling app is targeting SDK level
     *     {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password
     *     quality requirement prior to calling this method.
     */
    public void setPasswordMinimumSymbols(@NonNull ComponentName admin, int length) {
        if (mService != null) {
@@ -3123,7 +3159,10 @@ public class DevicePolicyManager {
     * one, so the change does not take place immediately. To prompt the user for a new password,
     * use {@link #ACTION_SET_NEW_PASSWORD} or {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after
     * setting this value. This constraint is only imposed if the administrator has also requested
     * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The default value is 0.
     * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. If an app targeting
     * SDK level {@link android.os.Build.VERSION_CODES#R} and above enforces this constraint without
     * settings password quality to {@link #PASSWORD_QUALITY_COMPLEX} first, this method will throw
     * {@link IllegalStateException}. The default value is 0.
     * <p>
     * On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
     * password is always treated as empty.
@@ -3141,6 +3180,9 @@ public class DevicePolicyManager {
     *            0 means there is no restriction.
     * @throws SecurityException if {@code admin} is not an active administrator or {@code admin}
     *             does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
     * @throws IllegalStateException if the calling app is targeting SDK level
     *     {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password
     *     quality requirement prior to calling this method.
     */
    public void setPasswordMinimumNonLetter(@NonNull ComponentName admin, int length) {
        if (mService != null) {
+42 −1
Original line number Diff line number Diff line
@@ -4133,6 +4133,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                final PasswordMetrics metrics = ap.minimumPasswordMetrics;
                if (metrics.quality != quality) {
                    metrics.quality = quality;
                    resetInactivePasswordRequirementsIfRPlus(userId, ap);
                    updatePasswordValidityCheckpointLocked(userId, parent);
                    updatePasswordQualityCacheForUserGroup(userId);
                    saveSettingsLocked(userId);
@@ -4150,6 +4151,27 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                .write();
    }
    /**
     * For admins targeting R+ reset various password constraints to default values when quality is
     * set to a value that makes those constraints that have no effect.
     */
    private void resetInactivePasswordRequirementsIfRPlus(int userId, ActiveAdmin admin) {
        if (getTargetSdk(admin.info.getPackageName(), userId) > Build.VERSION_CODES.Q) {
            final PasswordMetrics metrics = admin.minimumPasswordMetrics;
            if (metrics.quality < PASSWORD_QUALITY_NUMERIC) {
                metrics.length = ActiveAdmin.DEF_MINIMUM_PASSWORD_LENGTH;
            }
            if (metrics.quality < PASSWORD_QUALITY_COMPLEX) {
                metrics.letters = ActiveAdmin.DEF_MINIMUM_PASSWORD_LETTERS;
                metrics.upperCase = ActiveAdmin.DEF_MINIMUM_PASSWORD_UPPER_CASE;
                metrics.lowerCase = ActiveAdmin.DEF_MINIMUM_PASSWORD_LOWER_CASE;
                metrics.numeric = ActiveAdmin.DEF_MINIMUM_PASSWORD_NUMERIC;
                metrics.symbols = ActiveAdmin.DEF_MINIMUM_PASSWORD_SYMBOLS;
                metrics.nonLetter = ActiveAdmin.DEF_MINIMUM_PASSWORD_NON_LETTER;
            }
        }
    }
    /**
     * Updates a flag that tells us whether the user's password currently satisfies the
     * requirements set by all of the user's active admins. The flag is updated both in memory
@@ -4281,6 +4303,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            ActiveAdmin ap = getActiveAdminForCallerLocked(
                    who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
            final PasswordMetrics metrics = ap.minimumPasswordMetrics;
            ensureMinimumQuality(userId, ap, PASSWORD_QUALITY_NUMERIC, "setPasswordMinimumLength");
            if (metrics.length != length) {
                metrics.length = length;
                updatePasswordValidityCheckpointLocked(userId, parent);
@@ -4295,10 +4318,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                .write();
    }
    private void ensureMinimumQuality(
            int userId, ActiveAdmin admin, int minimumQuality, String operation) {
        if (admin.minimumPasswordMetrics.quality < minimumQuality
                && getTargetSdk(admin.info.getPackageName(), userId) > Build.VERSION_CODES.Q) {
            throw new IllegalStateException(String.format(
                    "password quality should be at least %d for %s", minimumQuality, operation));
        }
    }
    @Override
    public int getPasswordMinimumLength(ComponentName who, int userHandle, boolean parent) {
        return getStrictestPasswordRequirement(who, userHandle, parent,
                admin -> admin.minimumPasswordMetrics.length, PASSWORD_QUALITY_UNSPECIFIED);
                admin -> admin.minimumPasswordMetrics.length, PASSWORD_QUALITY_NUMERIC);
    }
    @Override
@@ -4525,6 +4557,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        synchronized (getLockObject()) {
            final ActiveAdmin ap = getActiveAdminForCallerLocked(
                    who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
            ensureMinimumQuality(
                    userId, ap, PASSWORD_QUALITY_COMPLEX, "setPasswordMinimumUpperCase");
            final PasswordMetrics metrics = ap.minimumPasswordMetrics;
            if (metrics.upperCase != length) {
                metrics.upperCase = length;
@@ -4553,6 +4587,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        synchronized (getLockObject()) {
            ActiveAdmin ap = getActiveAdminForCallerLocked(
                    who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
            ensureMinimumQuality(
                    userId, ap, PASSWORD_QUALITY_COMPLEX, "setPasswordMinimumLowerCase");
            final PasswordMetrics metrics = ap.minimumPasswordMetrics;
            if (metrics.lowerCase != length) {
                metrics.lowerCase = length;
@@ -4584,6 +4620,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        synchronized (getLockObject()) {
            ActiveAdmin ap = getActiveAdminForCallerLocked(
                    who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
            ensureMinimumQuality(userId, ap, PASSWORD_QUALITY_COMPLEX, "setPasswordMinimumLetters");
            final PasswordMetrics metrics = ap.minimumPasswordMetrics;
            if (metrics.letters != length) {
                metrics.letters = length;
@@ -4615,6 +4652,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        synchronized (getLockObject()) {
            ActiveAdmin ap = getActiveAdminForCallerLocked(
                    who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
            ensureMinimumQuality(userId, ap, PASSWORD_QUALITY_COMPLEX, "setPasswordMinimumNumeric");
            final PasswordMetrics metrics = ap.minimumPasswordMetrics;
            if (metrics.numeric != length) {
                metrics.numeric = length;
@@ -4646,6 +4684,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        synchronized (getLockObject()) {
            ActiveAdmin ap = getActiveAdminForCallerLocked(
                    who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
            ensureMinimumQuality(userId, ap, PASSWORD_QUALITY_COMPLEX, "setPasswordMinimumSymbols");
            final PasswordMetrics metrics = ap.minimumPasswordMetrics;
            if (metrics.symbols != length) {
                ap.minimumPasswordMetrics.symbols = length;
@@ -4677,6 +4716,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        synchronized (getLockObject()) {
            ActiveAdmin ap = getActiveAdminForCallerLocked(
                    who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
            ensureMinimumQuality(
                    userId, ap, PASSWORD_QUALITY_COMPLEX, "setPasswordMinimumNonLetter");
            final PasswordMetrics metrics = ap.minimumPasswordMetrics;
            if (metrics.nonLetter != length) {
                ap.minimumPasswordMetrics.nonLetter = length;