Enforce minimum pattern length in PasswordMetrics
For patterns, currently PasswordMetrics#validateCredential() does nothing except validate that the pattern credential type is allowed. Pattern length is supposed to be >= MIN_LOCK_PATTERN_SIZE, but that is hardcoded into the ChooseLockPattern activity in Settings. Since there are other places that can set a pattern lockscreen credential, such as LockSettingsShellCommand, let's add the pattern length validation to PasswordMetrics#validatePasswordMetrics() so that it gets done in the same place as PIN and password validation. Note that this required starting to populate the length field of PasswordMetrics created for patterns. Bug: 219511761 Bug: 232900169 Bug: 243881358 Test: atest PasswordMetricsTest Change-Id: I9f33f86045ea5f674b8ab79f9fda62c988436c53
This commit is contained in:
@@ -30,6 +30,7 @@ import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSW
|
||||
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
|
||||
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN;
|
||||
import static com.android.internal.widget.LockPatternUtils.MIN_LOCK_PASSWORD_SIZE;
|
||||
import static com.android.internal.widget.LockPatternUtils.MIN_LOCK_PATTERN_SIZE;
|
||||
import static com.android.internal.widget.PasswordValidationError.CONTAINS_INVALID_CHARACTERS;
|
||||
import static com.android.internal.widget.PasswordValidationError.CONTAINS_SEQUENCE;
|
||||
import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_DIGITS;
|
||||
@@ -201,7 +202,9 @@ public final class PasswordMetrics implements Parcelable {
|
||||
return PasswordMetrics.computeForPasswordOrPin(credential.getCredential(),
|
||||
credential.isPin());
|
||||
} else if (credential.isPattern()) {
|
||||
return new PasswordMetrics(CREDENTIAL_TYPE_PATTERN);
|
||||
PasswordMetrics metrics = new PasswordMetrics(CREDENTIAL_TYPE_PATTERN);
|
||||
metrics.length = credential.size();
|
||||
return metrics;
|
||||
} else if (credential.isNone()) {
|
||||
return new PasswordMetrics(CREDENTIAL_TYPE_NONE);
|
||||
} else {
|
||||
@@ -529,13 +532,8 @@ public final class PasswordMetrics implements Parcelable {
|
||||
return Collections.singletonList(
|
||||
new PasswordValidationError(CONTAINS_INVALID_CHARACTERS, 0));
|
||||
}
|
||||
if (credential.isPassword() || credential.isPin()) {
|
||||
return validatePassword(adminMetrics, minComplexity, credential.isPin(),
|
||||
credential.getCredential());
|
||||
} else {
|
||||
return validatePasswordMetrics(adminMetrics, minComplexity,
|
||||
new PasswordMetrics(credential.getType()));
|
||||
}
|
||||
PasswordMetrics actualMetrics = computeForCredential(credential);
|
||||
return validatePasswordMetrics(adminMetrics, minComplexity, actualMetrics);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -584,9 +582,18 @@ public final class PasswordMetrics implements Parcelable {
|
||||
|| !bucket.allowsCredType(actualMetrics.credType)) {
|
||||
return Collections.singletonList(new PasswordValidationError(WEAK_CREDENTIAL_TYPE, 0));
|
||||
}
|
||||
if (actualMetrics.credType != CREDENTIAL_TYPE_PASSWORD
|
||||
&& actualMetrics.credType != CREDENTIAL_TYPE_PIN) {
|
||||
return Collections.emptyList(); // Nothing to check for pattern or none.
|
||||
if (actualMetrics.credType == CREDENTIAL_TYPE_PATTERN) {
|
||||
// For pattern, only need to check the length against the hardcoded minimum. If the
|
||||
// pattern length is unavailable (e.g., PasswordMetrics that was stored on-disk before
|
||||
// the pattern length started being included in it), assume it is okay.
|
||||
if (actualMetrics.length != 0 && actualMetrics.length < MIN_LOCK_PATTERN_SIZE) {
|
||||
return Collections.singletonList(new PasswordValidationError(TOO_SHORT,
|
||||
MIN_LOCK_PATTERN_SIZE));
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (actualMetrics.credType == CREDENTIAL_TYPE_NONE) {
|
||||
return Collections.emptyList(); // Nothing to check for none.
|
||||
}
|
||||
|
||||
if (actualMetrics.credType == CREDENTIAL_TYPE_PIN && actualMetrics.nonNumeric > 0) {
|
||||
|
||||
@@ -42,6 +42,7 @@ import android.platform.test.annotations.Presubmit;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.LockscreenCredential;
|
||||
import com.android.internal.widget.PasswordValidationError;
|
||||
|
||||
@@ -419,6 +420,21 @@ public class PasswordMetricsTest {
|
||||
PasswordValidationError.TOO_SHORT, 6);
|
||||
}
|
||||
|
||||
private LockscreenCredential createPattern(String patternString) {
|
||||
return LockscreenCredential.createPattern(LockPatternUtils.byteArrayToPattern(
|
||||
patternString.getBytes()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateCredential_pattern() {
|
||||
PasswordMetrics adminMetrics = new PasswordMetrics(CREDENTIAL_TYPE_NONE);
|
||||
assertValidationErrors(
|
||||
validateCredential(adminMetrics, PASSWORD_COMPLEXITY_NONE, createPattern("123")),
|
||||
PasswordValidationError.TOO_SHORT, 4);
|
||||
assertValidationErrors(
|
||||
validateCredential(adminMetrics, PASSWORD_COMPLEXITY_NONE, createPattern("1234")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param expected sequence of validation error codes followed by requirement values, must have
|
||||
* even number of elements. Empty means no errors.
|
||||
|
||||
Reference in New Issue
Block a user