Merge "Recognize numeric PIN in resetPasswordWithToken()" into sc-dev

This commit is contained in:
Rubin Xu
2021-04-09 23:21:18 +00:00
committed by Android (Google) Code Review
3 changed files with 62 additions and 4 deletions

View File

@@ -691,6 +691,19 @@ public final class PasswordMetrics implements Parcelable {
return minMetrics; return minMetrics;
} }
/**
* Returns true if password is non-empty and contains digits only.
* @param password
* @return
*/
public static boolean isNumericOnly(@NonNull String password) {
if (password.length() == 0) return false;
for (int i = 0; i < password.length(); i++) {
if (categoryChar(password.charAt(i)) != CHAR_DIGIT) return false;
}
return true;
}
@Override @Override
public boolean equals(@Nullable Object o) { public boolean equals(@Nullable Object o) {
if (this == o) return true; if (this == o) return true;

View File

@@ -4954,6 +4954,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
int flags, CallerIdentity caller) { int flags, CallerIdentity caller) {
final int callingUid = caller.getUid(); final int callingUid = caller.getUid();
final int userHandle = UserHandle.getUserId(callingUid); final int userHandle = UserHandle.getUserId(callingUid);
final boolean isPin = PasswordMetrics.isNumericOnly(password);
synchronized (getLockObject()) { synchronized (getLockObject()) {
final PasswordMetrics minMetrics = getPasswordMinimumMetricsUnchecked(userHandle); final PasswordMetrics minMetrics = getPasswordMinimumMetricsUnchecked(userHandle);
final List<PasswordValidationError> validationErrors; final List<PasswordValidationError> validationErrors;
@@ -4961,12 +4962,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// TODO: Consider changing validation API to take LockscreenCredential. // TODO: Consider changing validation API to take LockscreenCredential.
if (password.isEmpty()) { if (password.isEmpty()) {
validationErrors = PasswordMetrics.validatePasswordMetrics( validationErrors = PasswordMetrics.validatePasswordMetrics(
minMetrics, complexity, false /* isPin */, minMetrics, complexity, isPin,
new PasswordMetrics(CREDENTIAL_TYPE_NONE)); new PasswordMetrics(CREDENTIAL_TYPE_NONE));
} else { } else {
// TODO(b/120484642): remove getBytes() below // TODO(b/120484642): remove getBytes() below
validationErrors = PasswordMetrics.validatePassword( validationErrors = PasswordMetrics.validatePassword(
minMetrics, complexity, false, password.getBytes()); minMetrics, complexity, isPin, password.getBytes());
} }
if (!validationErrors.isEmpty()) { if (!validationErrors.isEmpty()) {
@@ -4992,8 +4993,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// Don't do this with the lock held, because it is going to call // Don't do this with the lock held, because it is going to call
// back in to the service. // back in to the service.
final long ident = mInjector.binderClearCallingIdentity(); final long ident = mInjector.binderClearCallingIdentity();
final LockscreenCredential newCredential = final LockscreenCredential newCredential;
LockscreenCredential.createPasswordOrNone(password); if (isPin) {
newCredential = LockscreenCredential.createPin(password);
} else {
newCredential = LockscreenCredential.createPasswordOrNone(password);
}
try { try {
if (tokenHandle == 0 || token == null) { if (tokenHandle == 0 || token == null) {
if (!mLockPatternUtils.setLockCredential(newCredential, if (!mLockPatternUtils.setLockCredential(newCredential,

View File

@@ -5089,6 +5089,46 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertThat(dpm.clearResetPasswordToken(admin1)).isTrue(); assertThat(dpm.clearResetPasswordToken(admin1)).isTrue();
} }
@Test
public void resetPasswordWithToken_NumericPin() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
// adding a token
final byte[] token = new byte[32];
final long handle = 123456;
when(getServices().lockPatternUtils.addEscrowToken(eq(token), eq(UserHandle.USER_SYSTEM),
nullable(EscrowTokenStateChangeCallback.class)))
.thenReturn(handle);
assertThat(dpm.setResetPasswordToken(admin1, token)).isTrue();
// Test resetting with a numeric pin
final String pin = "123456";
when(getServices().lockPatternUtils.setLockCredentialWithToken(
LockscreenCredential.createPin(pin), handle, token,
UserHandle.USER_SYSTEM)).thenReturn(true);
assertThat(dpm.resetPasswordWithToken(admin1, pin, token, 0)).isTrue();
}
@Test
public void resetPasswordWithToken_EmptyPassword() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
// adding a token
final byte[] token = new byte[32];
final long handle = 123456;
when(getServices().lockPatternUtils.addEscrowToken(eq(token), eq(UserHandle.USER_SYSTEM),
nullable(EscrowTokenStateChangeCallback.class)))
.thenReturn(handle);
assertThat(dpm.setResetPasswordToken(admin1, token)).isTrue();
// Test resetting with an empty password
final String password = "";
when(getServices().lockPatternUtils.setLockCredentialWithToken(
LockscreenCredential.createNone(), handle, token,
UserHandle.USER_SYSTEM)).thenReturn(true);
assertThat(dpm.resetPasswordWithToken(admin1, password, token, 0)).isTrue();
}
@Test @Test
public void testIsActivePasswordSufficient() throws Exception { public void testIsActivePasswordSufficient() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;