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

Commit 92c8f95c authored by Chaohui Wang's avatar Chaohui Wang Committed by Automerger Merge Worker
Browse files

Merge "Add validation TOO_SHORT_WHEN_ALL_NUMERIC" into tm-dev am: 4f4e8dd3

parents f65980ca 4f4e8dd3
Loading
Loading
Loading
Loading
+21 −18
Original line number Original line Diff line number Diff line
@@ -41,6 +41,7 @@ import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_SYM
import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_UPPER_CASE;
import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_UPPER_CASE;
import static com.android.internal.widget.PasswordValidationError.TOO_LONG;
import static com.android.internal.widget.PasswordValidationError.TOO_LONG;
import static com.android.internal.widget.PasswordValidationError.TOO_SHORT;
import static com.android.internal.widget.PasswordValidationError.TOO_SHORT;
import static com.android.internal.widget.PasswordValidationError.TOO_SHORT_WHEN_ALL_NUMERIC;
import static com.android.internal.widget.PasswordValidationError.WEAK_CREDENTIAL_TYPE;
import static com.android.internal.widget.PasswordValidationError.WEAK_CREDENTIAL_TYPE;


import android.annotation.IntDef;
import android.annotation.IntDef;
@@ -569,21 +570,15 @@ public final class PasswordMetrics implements Parcelable {
            result.add(new PasswordValidationError(TOO_LONG, MAX_PASSWORD_LENGTH));
            result.add(new PasswordValidationError(TOO_LONG, MAX_PASSWORD_LENGTH));
        }
        }


        // A flag indicating whether the provided password already has non-numeric characters in
        final PasswordMetrics minMetrics = applyComplexity(adminMetrics,
        // it or if the admin imposes the requirement of any non-numeric characters.
                actualMetrics.credType == CREDENTIAL_TYPE_PIN, bucket);
        final boolean hasOrWouldNeedNonNumeric =
                actualMetrics.nonNumeric > 0 || adminMetrics.nonNumeric > 0
                        || adminMetrics.letters > 0 || adminMetrics.lowerCase > 0
                        || adminMetrics.upperCase > 0 || adminMetrics.symbols > 0;
        final PasswordMetrics minMetrics =
                applyComplexity(adminMetrics, hasOrWouldNeedNonNumeric, bucket);


        // Clamp required length between maximum and minimum valid values.
        // Clamp required length between maximum and minimum valid values.
        minMetrics.length = Math.min(MAX_PASSWORD_LENGTH,
        minMetrics.length = Math.min(MAX_PASSWORD_LENGTH,
                Math.max(minMetrics.length, MIN_LOCK_PASSWORD_SIZE));
                Math.max(minMetrics.length, MIN_LOCK_PASSWORD_SIZE));
        minMetrics.removeOverlapping();
        minMetrics.removeOverlapping();


        comparePasswordMetrics(minMetrics, actualMetrics, result);
        comparePasswordMetrics(minMetrics, bucket, actualMetrics, result);


        return result;
        return result;
    }
    }
@@ -591,11 +586,23 @@ public final class PasswordMetrics implements Parcelable {
    /**
    /**
     * TODO: move to PasswordPolicy
     * TODO: move to PasswordPolicy
     */
     */
    private static void comparePasswordMetrics(PasswordMetrics minMetrics,
    private static void comparePasswordMetrics(PasswordMetrics minMetrics, ComplexityBucket bucket,
            PasswordMetrics actualMetrics, ArrayList<PasswordValidationError> result) {
            PasswordMetrics actualMetrics, ArrayList<PasswordValidationError> result) {
        if (actualMetrics.length < minMetrics.length) {
        if (actualMetrics.length < minMetrics.length) {
            result.add(new PasswordValidationError(TOO_SHORT, minMetrics.length));
            result.add(new PasswordValidationError(TOO_SHORT, minMetrics.length));
        }
        }
        if (actualMetrics.nonNumeric == 0 && minMetrics.nonNumeric == 0 && minMetrics.letters == 0
                && minMetrics.lowerCase == 0 && minMetrics.upperCase == 0
                && minMetrics.symbols == 0) {
            // When provided password is all numeric and all numeric password is allowed.
            int allNumericMinimumLength = bucket.getMinimumLength(false);
            if (allNumericMinimumLength > minMetrics.length
                    && allNumericMinimumLength > minMetrics.numeric
                    && actualMetrics.length < allNumericMinimumLength) {
                result.add(new PasswordValidationError(
                        TOO_SHORT_WHEN_ALL_NUMERIC, allNumericMinimumLength));
            }
        }
        if (actualMetrics.letters < minMetrics.letters) {
        if (actualMetrics.letters < minMetrics.letters) {
            result.add(new PasswordValidationError(NOT_ENOUGH_LETTERS, minMetrics.letters));
            result.add(new PasswordValidationError(NOT_ENOUGH_LETTERS, minMetrics.letters));
        }
        }
@@ -668,15 +675,12 @@ public final class PasswordMetrics implements Parcelable {
     *
     *
     * TODO: move to PasswordPolicy
     * TODO: move to PasswordPolicy
     */
     */
    public static PasswordMetrics applyComplexity(
    public static PasswordMetrics applyComplexity(PasswordMetrics adminMetrics, boolean isPin,
            PasswordMetrics adminMetrics, boolean withNonNumericCharacters,
            int complexity) {
            int complexity) {
        return applyComplexity(adminMetrics, withNonNumericCharacters,
        return applyComplexity(adminMetrics, isPin, ComplexityBucket.forComplexity(complexity));
                ComplexityBucket.forComplexity(complexity));
    }
    }


    private static PasswordMetrics applyComplexity(
    private static PasswordMetrics applyComplexity(PasswordMetrics adminMetrics, boolean isPin,
            PasswordMetrics adminMetrics, boolean withNonNumericCharacters,
            ComplexityBucket bucket) {
            ComplexityBucket bucket) {
        final PasswordMetrics minMetrics = new PasswordMetrics(adminMetrics);
        final PasswordMetrics minMetrics = new PasswordMetrics(adminMetrics);


@@ -684,8 +688,7 @@ public final class PasswordMetrics implements Parcelable {
            minMetrics.seqLength = Math.min(minMetrics.seqLength, MAX_ALLOWED_SEQUENCE);
            minMetrics.seqLength = Math.min(minMetrics.seqLength, MAX_ALLOWED_SEQUENCE);
        }
        }


        minMetrics.length = Math.max(minMetrics.length,
        minMetrics.length = Math.max(minMetrics.length, bucket.getMinimumLength(!isPin));
                bucket.getMinimumLength(withNonNumericCharacters));


        return minMetrics;
        return minMetrics;
    }
    }
+12 −10
Original line number Original line Diff line number Diff line
@@ -24,16 +24,17 @@ public class PasswordValidationError {
    public static final int WEAK_CREDENTIAL_TYPE = 1;
    public static final int WEAK_CREDENTIAL_TYPE = 1;
    public static final int CONTAINS_INVALID_CHARACTERS = 2;
    public static final int CONTAINS_INVALID_CHARACTERS = 2;
    public static final int TOO_SHORT = 3;
    public static final int TOO_SHORT = 3;
    public static final int TOO_LONG = 4;
    public static final int TOO_SHORT_WHEN_ALL_NUMERIC = 4;
    public static final int CONTAINS_SEQUENCE = 5;
    public static final int TOO_LONG = 5;
    public static final int NOT_ENOUGH_LETTERS = 6;
    public static final int CONTAINS_SEQUENCE = 6;
    public static final int NOT_ENOUGH_UPPER_CASE = 7;
    public static final int NOT_ENOUGH_LETTERS = 7;
    public static final int NOT_ENOUGH_LOWER_CASE = 8;
    public static final int NOT_ENOUGH_UPPER_CASE = 8;
    public static final int NOT_ENOUGH_DIGITS = 9;
    public static final int NOT_ENOUGH_LOWER_CASE = 9;
    public static final int NOT_ENOUGH_SYMBOLS = 10;
    public static final int NOT_ENOUGH_DIGITS = 10;
    public static final int NOT_ENOUGH_NON_LETTER = 11;
    public static final int NOT_ENOUGH_SYMBOLS = 11;
    public static final int NOT_ENOUGH_NON_DIGITS = 12;
    public static final int NOT_ENOUGH_NON_LETTER = 12;
    public static final int RECENTLY_USED = 13;
    public static final int NOT_ENOUGH_NON_DIGITS = 13;
    public static final int RECENTLY_USED = 14;
    // WARNING: if you add a new error, make sure it is presented to the user correctly in Settings.
    // WARNING: if you add a new error, make sure it is presented to the user correctly in Settings.


    public final int errorCode;
    public final int errorCode;
@@ -61,6 +62,7 @@ public class PasswordValidationError {
            case WEAK_CREDENTIAL_TYPE: return "Weak credential type";
            case WEAK_CREDENTIAL_TYPE: return "Weak credential type";
            case CONTAINS_INVALID_CHARACTERS: return "Contains an invalid character";
            case CONTAINS_INVALID_CHARACTERS: return "Contains an invalid character";
            case TOO_SHORT: return "Password too short";
            case TOO_SHORT: return "Password too short";
            case TOO_SHORT_WHEN_ALL_NUMERIC: return "Password too short";
            case TOO_LONG: return "Password too long";
            case TOO_LONG: return "Password too long";
            case CONTAINS_SEQUENCE: return "Sequence too long";
            case CONTAINS_SEQUENCE: return "Sequence too long";
            case NOT_ENOUGH_LETTERS: return "Too few letters";
            case NOT_ENOUGH_LETTERS: return "Too few letters";
+52 −2
Original line number Original line Diff line number Diff line
@@ -38,8 +38,8 @@ import static org.junit.Assert.assertTrue;
import android.os.Parcel;
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.Presubmit;


import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;


import com.android.internal.widget.PasswordValidationError;
import com.android.internal.widget.PasswordValidationError;


@@ -324,6 +324,56 @@ public class PasswordMetricsTest {
                PasswordValidationError.WEAK_CREDENTIAL_TYPE, 0);
                PasswordValidationError.WEAK_CREDENTIAL_TYPE, 0);
    }
    }


    @Test
    public void testValidatePasswordMetrics_pinAndComplexityHigh() {
        PasswordMetrics adminMetrics = new PasswordMetrics(CREDENTIAL_TYPE_PIN);
        PasswordMetrics actualMetrics = new PasswordMetrics(CREDENTIAL_TYPE_PIN);
        actualMetrics.length = 6;
        actualMetrics.seqLength = 1;

        assertValidationErrors(
                validatePasswordMetrics(adminMetrics, PASSWORD_COMPLEXITY_HIGH, actualMetrics),
                PasswordValidationError.TOO_SHORT, 8);
    }

    @Test
    public void testValidatePasswordMetrics_nonAllNumberPasswordAndComplexityHigh() {
        PasswordMetrics adminMetrics = new PasswordMetrics(CREDENTIAL_TYPE_PASSWORD);
        PasswordMetrics actualMetrics = new PasswordMetrics(CREDENTIAL_TYPE_PASSWORD);
        actualMetrics.length = 5;
        actualMetrics.nonNumeric = 1;
        actualMetrics.seqLength = 1;

        assertValidationErrors(
                validatePasswordMetrics(adminMetrics, PASSWORD_COMPLEXITY_HIGH, actualMetrics),
                PasswordValidationError.TOO_SHORT, 6);
    }

    @Test
    public void testValidatePasswordMetrics_allNumberPasswordAndComplexityHigh() {
        PasswordMetrics adminMetrics = new PasswordMetrics(CREDENTIAL_TYPE_PASSWORD);
        PasswordMetrics actualMetrics = new PasswordMetrics(CREDENTIAL_TYPE_PASSWORD);
        actualMetrics.length = 6;
        actualMetrics.seqLength = 1;

        assertValidationErrors(
                validatePasswordMetrics(adminMetrics, PASSWORD_COMPLEXITY_HIGH, actualMetrics),
                PasswordValidationError.TOO_SHORT_WHEN_ALL_NUMERIC, 8);
    }

    @Test
    public void testValidatePasswordMetrics_allNumberPasswordAndRequireNonNumeric() {
        PasswordMetrics adminMetrics = new PasswordMetrics(CREDENTIAL_TYPE_PASSWORD);
        adminMetrics.nonNumeric = 1;
        PasswordMetrics actualMetrics = new PasswordMetrics(CREDENTIAL_TYPE_PASSWORD);
        actualMetrics.length = 6;
        actualMetrics.seqLength = 1;

        assertValidationErrors(
                validatePasswordMetrics(adminMetrics, PASSWORD_COMPLEXITY_HIGH, actualMetrics),
                PasswordValidationError.NOT_ENOUGH_NON_DIGITS, 1);
    }

    /**
    /**
     * @param expected sequense of validation error codes followed by requirement values, must have
     * @param expected sequense of validation error codes followed by requirement values, must have
     *                 even number of elements. Empty means no errors.
     *                 even number of elements. Empty means no errors.