From c90674dcc2f8676afa72665626d630de031f7701 Mon Sep 17 00:00:00 2001 From: Irina Dumitrescu Date: Thu, 28 Feb 2019 17:34:19 +0000 Subject: [PATCH] Change existing LockPatternUtil APIs to fail untrusted password updates. Add alternative APIs to allow untrusted password changes explicitly, so the caller can choose to use them if needed. Test: atest frameworks/base/services/tests/servicestests/src/com/android/server/locksettings/ Bug: 120039091 Change-Id: I4ca03c9185081d300d7e325965b1e20515e33d51 --- config/hiddenapi-greylist.txt | 1 - .../internal/widget/ILockSettings.aidl | 2 +- .../internal/widget/LockPatternUtils.java | 78 +++++++++++++++---- .../locksettings/LockSettingsService.java | 57 ++++++++------ .../DevicePolicyManagerService.java | 7 +- .../CachedSyntheticPasswordTests.java | 14 ++-- .../LockSettingsServiceTests.java | 27 +++---- .../locksettings/SyntheticPasswordTests.java | 34 ++++---- 8 files changed, 140 insertions(+), 80 deletions(-) diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt index 76d69cdce5cfc..79cdb77bbd11b 100644 --- a/config/hiddenapi-greylist.txt +++ b/config/hiddenapi-greylist.txt @@ -1680,7 +1680,6 @@ Lcom/android/internal/widget/LockPatternUtils;->patternToHash(Ljava/util/List;)[ Lcom/android/internal/widget/LockPatternUtils;->patternToString(Ljava/util/List;)Ljava/lang/String; Lcom/android/internal/widget/LockPatternUtils;->reportFailedPasswordAttempt(I)V Lcom/android/internal/widget/LockPatternUtils;->reportSuccessfulPasswordAttempt(I)V -Lcom/android/internal/widget/LockPatternUtils;->saveLockPassword(Ljava/lang/String;Ljava/lang/String;II)V Lcom/android/internal/widget/LockPatternUtils;->setLockoutAttemptDeadline(II)J Lcom/android/internal/widget/LockPatternUtils;->setLong(Ljava/lang/String;JI)V Lcom/android/internal/widget/LockPatternUtils;->setOwnerInfo(Ljava/lang/String;I)V diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl index 41e2fc84593e9..b36c3fa792513 100644 --- a/core/java/com/android/internal/widget/ILockSettings.aidl +++ b/core/java/com/android/internal/widget/ILockSettings.aidl @@ -42,7 +42,7 @@ interface ILockSettings { long getLong(in String key, in long defaultValue, in int userId); @UnsupportedAppUsage String getString(in String key, in String defaultValue, in int userId); - void setLockCredential(in byte[] credential, int type, in byte[] savedCredential, int requestedQuality, int userId); + void setLockCredential(in byte[] credential, int type, in byte[] savedCredential, int requestedQuality, int userId, boolean allowUntrustedChange); void resetKeyStore(int userId); VerifyCredentialResponse checkCredential(in byte[] credential, int type, int userId, in ICheckCredentialProgressCallback progressCallback); diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 30f4d6fe417a0..dd48c15e836b4 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -669,17 +669,25 @@ public class LockPatternUtils { /** * Clear any lock pattern or password. */ - public void clearLock(byte[] savedCredential, int userHandle) { + public boolean clearLock(byte[] savedCredential, int userHandle) { + return clearLock(savedCredential, userHandle, false); + } + + /** + * Clear any lock pattern or password, with the option to ignore incorrect existing credential. + */ + public boolean clearLock(byte[] savedCredential, int userHandle, boolean allowUntrustedChange) { final int currentQuality = getKeyguardStoredPasswordQuality(userHandle); setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED, userHandle); try{ getLockSettings().setLockCredential(null, CREDENTIAL_TYPE_NONE, - savedCredential, PASSWORD_QUALITY_UNSPECIFIED, userHandle); + savedCredential, PASSWORD_QUALITY_UNSPECIFIED, userHandle, + allowUntrustedChange); } catch (Exception e) { Log.e(TAG, "Failed to clear lock", e); setKeyguardStoredPasswordQuality(currentQuality, userHandle); - return; + return false; } if (userHandle == UserHandle.USER_SYSTEM) { @@ -689,6 +697,7 @@ public class LockPatternUtils { } onAfterChangingPassword(userHandle); + return true; } /** @@ -726,19 +735,28 @@ public class LockPatternUtils { /** * Save a lock pattern. * @param pattern The new pattern to save. + * @param savedPattern The previously saved pattern, converted to byte[] format * @param userId the user whose pattern is to be saved. + * + * @return whether this was successful or not. */ - public void saveLockPattern(List pattern, int userId) { - this.saveLockPattern(pattern, null, userId); + public boolean saveLockPattern(List pattern, byte[] savedPattern, + int userId) { + return saveLockPattern(pattern, savedPattern, userId, false); } + /** * Save a lock pattern. * @param pattern The new pattern to save. * @param savedPattern The previously saved pattern, converted to byte[] format * @param userId the user whose pattern is to be saved. + * @param allowUntrustedChange whether we want to allow saving a new password if the existing + * password being provided is incorrect. + * + * @return whether this was successful or not. */ - public void saveLockPattern(List pattern, byte[] savedPattern, - int userId) { + public boolean saveLockPattern(List pattern, byte[] savedPattern, + int userId, boolean allowUntrustedChange) { if (!hasSecureLockScreen()) { throw new UnsupportedOperationException( "This operation requires the lock screen feature."); @@ -753,11 +771,11 @@ public class LockPatternUtils { setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_SOMETHING, userId); try { getLockSettings().setLockCredential(bytePattern, CREDENTIAL_TYPE_PATTERN, savedPattern, - PASSWORD_QUALITY_SOMETHING, userId); + PASSWORD_QUALITY_SOMETHING, userId, allowUntrustedChange); } catch (Exception e) { Log.e(TAG, "Couldn't save lock pattern", e); setKeyguardStoredPasswordQuality(currentQuality, userId); - return; + return false; } // Update the device encryption password. if (userId == UserHandle.USER_SYSTEM @@ -771,6 +789,7 @@ public class LockPatternUtils { reportPatternWasChosen(userId); onAfterChangingPassword(userId); + return true; } private void updateCryptoUserInfo(int userId) { @@ -873,17 +892,20 @@ public class LockPatternUtils { * password. * @param password The password to save * @param savedPassword The previously saved lock password, or null if none - * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} + * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality( + * android.content.ComponentName)} * @param userHandle The userId of the user to change the password for * + * @return whether this was successful or not. + * * @deprecated Pass password as a byte array */ @Deprecated - public void saveLockPassword(String password, String savedPassword, int requestedQuality, + public boolean saveLockPassword(String password, String savedPassword, int requestedQuality, int userHandle) { byte[] passwordBytes = password != null ? password.getBytes() : null; byte[] savedPasswordBytes = savedPassword != null ? savedPassword.getBytes() : null; - saveLockPassword(passwordBytes, savedPasswordBytes, requestedQuality, userHandle); + return saveLockPassword(passwordBytes, savedPasswordBytes, requestedQuality, userHandle); } /** @@ -893,11 +915,34 @@ public class LockPatternUtils { * @param password The password to save * @param savedPassword The previously saved lock password, or null if none * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality( - * android.content.ComponentName)} + * android.content.ComponentName)} * @param userHandle The userId of the user to change the password for + * + * @return whether this was successful or not. */ - public void saveLockPassword(byte[] password, byte[] savedPassword, int requestedQuality, + public boolean saveLockPassword(byte[] password, byte[] savedPassword, int requestedQuality, int userHandle) { + return saveLockPassword(password, savedPassword, requestedQuality, + userHandle, false); + } + + /** + * Save a lock password. Does not ensure that the password is as good + * as the requested mode, but will adjust the mode to be as good as the + * password. + * @param password The password to save + * @param savedPassword The previously saved lock password, or null if none + * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality( + * android.content.ComponentName)} + * @param userHandle The userId of the user to change the password for + * @param allowUntrustedChange whether we want to allow saving a new password if the existing + * password being provided is incorrect. + * + * @return whether this method saved the new password successfully or not. This flow will fail + * and return false if the given credential is wrong and allowUntrustedChange is false. + */ + public boolean saveLockPassword(byte[] password, byte[] savedPassword, + int requestedQuality, int userHandle, boolean allowUntrustedChange) { if (!hasSecureLockScreen()) { throw new UnsupportedOperationException( "This operation requires the lock screen feature."); @@ -919,16 +964,17 @@ public class LockPatternUtils { setKeyguardStoredPasswordQuality(newKeyguardQuality, userHandle); try { getLockSettings().setLockCredential(password, CREDENTIAL_TYPE_PASSWORD, savedPassword, - requestedQuality, userHandle); + requestedQuality, userHandle, allowUntrustedChange); } catch (Exception e) { Log.e(TAG, "Unable to save lock password", e); setKeyguardStoredPasswordQuality(currentQuality, userHandle); - return; + return false; } updateEncryptionPasswordIfNeeded(password, passwordQuality, userHandle); updatePasswordHistory(password, userHandle); onAfterChangingPassword(userHandle); + return true; } /** diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 0c5fb7998c78f..3e134b266a888 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -323,8 +323,8 @@ public class LockSettingsService extends ILockSettings.Stub { } Arrays.fill(newPasswordChars, '\u0000'); final int quality = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC; - setLockCredentialInternal(newPassword, CREDENTIAL_TYPE_PASSWORD, - managedUserPassword, quality, managedUserId); + setLockCredentialInternal(newPassword, CREDENTIAL_TYPE_PASSWORD, managedUserPassword, + quality, managedUserId, false); // We store a private credential for the managed user that's unlocked by the primary // account holder's credential. As such, the user will never be prompted to enter this // password directly, so we always store a password. @@ -1302,12 +1302,14 @@ public class LockSettingsService extends ILockSettings.Stub { if (profilePasswordMap != null && profilePasswordMap.containsKey(managedUserId)) { setLockCredentialInternal(null, CREDENTIAL_TYPE_NONE, profilePasswordMap.get(managedUserId), - DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, managedUserId); + DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, managedUserId, + false); } else { Slog.wtf(TAG, "clear tied profile challenges, but no password supplied."); // Supplying null here would lead to untrusted credential change setLockCredentialInternal(null, CREDENTIAL_TYPE_NONE, null, - DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, managedUserId); + DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, managedUserId, + true); } mStorage.removeChildProfileLock(managedUserId); removeKeystoreProfileKey(managedUserId); @@ -1330,8 +1332,8 @@ public class LockSettingsService extends ILockSettings.Stub { // should call setLockCredentialInternal. @Override public void setLockCredential(byte[] credential, int type, - byte[] savedCredential, int requestedQuality, int userId) - throws RemoteException { + byte[] savedCredential, int requestedQuality, int userId, + boolean allowUntrustedChange) throws RemoteException { if (!mLockPatternUtils.hasSecureLockScreen()) { throw new UnsupportedOperationException( @@ -1339,7 +1341,8 @@ public class LockSettingsService extends ILockSettings.Stub { } checkWritePermission(userId); synchronized (mSeparateChallengeLock) { - setLockCredentialInternal(credential, type, savedCredential, requestedQuality, userId); + setLockCredentialInternal(credential, type, savedCredential, requestedQuality, userId, + allowUntrustedChange); setSeparateProfileChallengeEnabledLocked(userId, true, null); notifyPasswordChanged(userId); } @@ -1347,7 +1350,8 @@ public class LockSettingsService extends ILockSettings.Stub { } private void setLockCredentialInternal(byte[] credential, @CredentialType int credentialType, - byte[] savedCredential, int requestedQuality, int userId) throws RemoteException { + byte[] savedCredential, int requestedQuality, int userId, + boolean allowUntrustedChange) throws RemoteException { // Normalize savedCredential and credential such that empty string is always represented // as null. if (savedCredential == null || savedCredential.length == 0) { @@ -1359,7 +1363,7 @@ public class LockSettingsService extends ILockSettings.Stub { synchronized (mSpManager) { if (isSyntheticPasswordBasedCredentialLocked(userId)) { spBasedSetLockCredentialInternalLocked(credential, credentialType, savedCredential, - requestedQuality, userId); + requestedQuality, userId, allowUntrustedChange); return; } } @@ -1410,7 +1414,7 @@ public class LockSettingsService extends ILockSettings.Stub { initializeSyntheticPasswordLocked(currentHandle.hash, savedCredential, currentHandle.type, requestedQuality, userId); spBasedSetLockCredentialInternalLocked(credential, credentialType, savedCredential, - requestedQuality, userId); + requestedQuality, userId, allowUntrustedChange); return; } } @@ -1705,7 +1709,7 @@ public class LockSettingsService extends ILockSettings.Stub { mStrongAuth.reportSuccessfulStrongAuthUnlock(userId); if (shouldReEnrollBaseZero) { setLockCredentialInternal(credential, storedHash.type, credentialToVerify, - DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId); + DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId, false); } } @@ -1796,7 +1800,7 @@ public class LockSettingsService extends ILockSettings.Stub { storedHash.type == CREDENTIAL_TYPE_PATTERN ? DevicePolicyManager.PASSWORD_QUALITY_SOMETHING : DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC - /* TODO(roosa): keep the same password quality */, userId); + /* TODO(roosa): keep the same password quality */, userId, false); if (!hasChallenge) { notifyActivePasswordMetricsAvailable(storedHash.type, credential, userId); // Use credentials to create recoverable keystore snapshot. @@ -1841,7 +1845,7 @@ public class LockSettingsService extends ILockSettings.Stub { /* TODO(roosa): keep the same password quality */; if (shouldReEnroll) { setLockCredentialInternal(credential, storedHash.type, credential, - reEnrollQuality, userId); + reEnrollQuality, userId, false); } else { // Now that we've cleared of all required GK migration, let's do the final // migration to synthetic password. @@ -2544,7 +2548,8 @@ public class LockSettingsService extends ILockSettings.Stub { @GuardedBy("mSpManager") private void spBasedSetLockCredentialInternalLocked(byte[] credential, int credentialType, - byte[] savedCredential, int requestedQuality, int userId) throws RemoteException { + byte[] savedCredential, int requestedQuality, int userId, + boolean allowUntrustedChange) throws RemoteException { if (DEBUG) Slog.d(TAG, "spBasedSetLockCredentialInternalLocked: user=" + userId); if (isManagedProfileWithUnifiedLock(userId)) { // get credential from keystore when managed profile has unified lock @@ -2565,27 +2570,31 @@ public class LockSettingsService extends ILockSettings.Stub { VerifyCredentialResponse response = authResult.gkResponse; AuthenticationToken auth = authResult.authToken; - // If existing credential is provided, then it must match. + // If existing credential is provided, the existing credential must match. if (savedCredential != null && auth == null) { - throw new RemoteException("Failed to enroll " + - (credentialType == CREDENTIAL_TYPE_PASSWORD ? "password" : "pattern")); + throw new IllegalStateException("Failed to enroll " + + (credentialType == CREDENTIAL_TYPE_PASSWORD + ? "password" : "pattern")); } - boolean untrustedReset = false; if (auth != null) { onAuthTokenKnownForUser(userId, auth); - } else if (response != null - && response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR) { + } else if (response == null) { + throw new IllegalStateException("Password change failed."); + } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR) { // We are performing an untrusted credential change, by DevicePolicyManager or other // internal callers that don't provide the existing credential Slog.w(TAG, "Untrusted credential change invoked"); // Try to get a cached auth token, so we can keep SP unchanged. auth = mSpCache.get(userId); + if (!allowUntrustedChange) { + throw new IllegalStateException("Untrusted credential change was invoked but it was" + + " not allowed. This is likely a bug. Auth token is null: " + + Boolean.toString(auth == null)); + } untrustedReset = true; - } else /* response == null || responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ { - Slog.w(TAG, "spBasedSetLockCredentialInternalLocked: " + - (response != null ? "rate limit exceeded" : "failed")); - return; + } else /* responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ { + throw new IllegalStateException("Rate limit exceeded, so password was not changed."); } if (auth != null) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 2d014718a47bf..4ff5d61b29d1e 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -5133,11 +5133,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final boolean result; try { if (token == null) { + // This is the legacy reset password for DPM. Here we want to be able to override + // the old device password without necessarily knowing it. if (!TextUtils.isEmpty(password)) { mLockPatternUtils.saveLockPassword(password.getBytes(), null, quality, - userHandle); + userHandle, /*allowUntrustedChange */true); } else { - mLockPatternUtils.clearLock(null, userHandle); + mLockPatternUtils.clearLock(null, userHandle, + /*allowUntrustedChange */ true); } result = true; } else { diff --git a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java index 94d21ddeaa2b4..ca4330fa7a5d2 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java @@ -61,12 +61,12 @@ public class CachedSyntheticPasswordTests extends SyntheticPasswordTests { long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); // clear password mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, null, - PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID); + PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, true); assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); // set a new password mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID) .getResponseCode()); @@ -81,7 +81,7 @@ public class CachedSyntheticPasswordTests extends SyntheticPasswordTests { long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); // Untrusted change password mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, true); assertNotEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); @@ -99,7 +99,7 @@ public class CachedSyntheticPasswordTests extends SyntheticPasswordTests { initializeCredentialUnderSP(password, PRIMARY_USER_ID); // Untrusted change password mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, true); // Verify the password assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(newPassword, @@ -124,10 +124,12 @@ public class CachedSyntheticPasswordTests extends SyntheticPasswordTests { initializeCredentialUnderSP(password, PRIMARY_USER_ID); long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); // Untrusted change password - assertExpectException(IllegalStateException.class, /* messageRegex= */ null, + assertExpectException( + IllegalStateException.class, + /* messageRegex= */ "Untrusted credential reset not possible without cached SP", () -> mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID)); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, true)); assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); // Verify the new password doesn't work but the old one still does diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java index 6e0ba3cb366cf..255e694bffaf4 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java @@ -85,9 +85,9 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { try { mService.setLockCredential("newpwd".getBytes(), CREDENTIAL_TYPE_PASSWORD, - "badpwd".getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + "badpwd".getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); fail("Did not fail when enrolling using incorrect credential"); - } catch (RemoteException expected) { + } catch (IllegalStateException expected) { assertTrue(expected.getMessage().equals(FAILED_MESSAGE)); } assertVerifyCredentials(PRIMARY_USER_ID, "password", CREDENTIAL_TYPE_PASSWORD, sid); @@ -97,7 +97,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { final String PASSWORD = "password"; initializeStorageWithCredential(PRIMARY_USER_ID, PASSWORD, CREDENTIAL_TYPE_PASSWORD, 1234); mService.setLockCredential(null, CREDENTIAL_TYPE_NONE, PASSWORD.getBytes(), - PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID); + PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false); assertFalse(mService.havePassword(PRIMARY_USER_ID)); assertFalse(mService.havePattern(PRIMARY_USER_ID)); assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); @@ -108,7 +108,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { final String secondUnifiedPassword = "testManagedProfileUnifiedChallenge-pwd-2"; mService.setLockCredential(firstUnifiedPassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, - null, PASSWORD_QUALITY_COMPLEX, PRIMARY_USER_ID); + null, PASSWORD_QUALITY_COMPLEX, PRIMARY_USER_ID, false); mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null); final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID); @@ -143,15 +143,16 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { mStorageManager.setIgnoreBadUnlock(true); // Change primary password and verify that profile SID remains mService.setLockCredential(secondUnifiedPassword.getBytes(), - LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, - firstUnifiedPassword.getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, firstUnifiedPassword.getBytes(), + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); mStorageManager.setIgnoreBadUnlock(false); assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID)); assertNull(mGateKeeperService.getAuthToken(TURNED_OFF_PROFILE_USER_ID)); // Clear unified challenge mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, - secondUnifiedPassword.getBytes(), PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID); + secondUnifiedPassword.getBytes(), PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, + false); assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); assertEquals(0, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID)); assertEquals(0, mGateKeeperService.getSecureUserId(TURNED_OFF_PROFILE_USER_ID)); @@ -162,7 +163,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { final String profilePassword = "testManagedProfileSeparateChallenge-profile"; mService.setLockCredential(primaryPassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_COMPLEX, PRIMARY_USER_ID); + PASSWORD_QUALITY_COMPLEX, PRIMARY_USER_ID, false); /* Currently in LockSettingsService.setLockCredential, unlockUser() is called with the new * credential as part of verifyCredential() before the new credential is committed in * StorageManager. So we relax the check in our mock StorageManager to allow that. @@ -170,7 +171,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { mStorageManager.setIgnoreBadUnlock(true); mService.setLockCredential(profilePassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_COMPLEX, MANAGED_PROFILE_USER_ID); + PASSWORD_QUALITY_COMPLEX, MANAGED_PROFILE_USER_ID, false); mStorageManager.setIgnoreBadUnlock(false); final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); @@ -197,7 +198,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { // Change primary credential and make sure we don't affect profile mStorageManager.setIgnoreBadUnlock(true); mService.setLockCredential("pwd".getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, - primaryPassword.getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + primaryPassword.getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); mStorageManager.setIgnoreBadUnlock(false); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( profilePassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, @@ -208,7 +209,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { private void testCreateCredential(int userId, String credential, int type, int quality) throws RemoteException { mService.setLockCredential(credential.getBytes(), type, null, quality, - userId); + userId, false); assertVerifyCredentials(userId, credential, type, -1); } @@ -218,7 +219,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { try { mService.setLockCredential(credential.getBytes(), type, null, quality, - userId); + userId, false); fail("An exception should have been thrown."); } catch (UnsupportedOperationException e) { // Success - the exception was expected. @@ -233,7 +234,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { final long sid = 1234; initializeStorageWithCredential(userId, oldCredential, oldType, sid); mService.setLockCredential(newCredential.getBytes(), newType, oldCredential.getBytes(), - quality, userId); + quality, userId, false); assertVerifyCredentials(userId, newCredential, newType, sid); } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java index 6a07a45ed3606..58055e58fce3f 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java @@ -102,7 +102,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { disableSyntheticPassword(); mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID); enableSyntheticPassword(); @@ -127,7 +127,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { : PASSWORD_QUALITY_UNSPECIFIED; int type = password != null ? LockPatternUtils.CREDENTIAL_TYPE_PASSWORD : LockPatternUtils.CREDENTIAL_TYPE_NONE; - mService.setLockCredential(password, type, null, quality, userId); + mService.setLockCredential(password, type, null, quality, userId, false); } public void testSyntheticPasswordChangeCredential() throws RemoteException { @@ -137,7 +137,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { initializeCredentialUnderSP(password, PRIMARY_USER_ID); long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, password, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID) .getResponseCode()); @@ -166,12 +166,12 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); // clear password mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, password, - PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID); + PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false); assertEquals(0 ,mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); // set a new password mService.setLockCredential(badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID) .getResponseCode()); @@ -186,7 +186,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { initializeCredentialUnderSP(password, PRIMARY_USER_ID); mService.setLockCredential(badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, password, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID) .getResponseCode()); @@ -245,7 +245,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { final byte[] password = "getASyntheticPassword".getBytes(); initializeCredentialUnderSP(password, PRIMARY_USER_ID); mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, password, - PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID); + PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false); reset(mAuthSecretService); mService.onUnlockUser(PRIMARY_USER_ID); @@ -257,7 +257,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { final byte[] UnifiedPassword = "testManagedProfileUnifiedChallengeMigration-pwd".getBytes(); disableSyntheticPassword(); mService.setLockCredential(UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null); final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID); @@ -294,9 +294,9 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { "testManagedProfileSeparateChallengeMigration-profile".getBytes(); disableSyntheticPassword(); mService.setLockCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); mService.setLockCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, MANAGED_PROFILE_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, MANAGED_PROFILE_USER_ID, false); final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID); final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID); @@ -404,7 +404,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); mService.setLockCredential(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, password, - PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID); + PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID, false); mLocalService.setLockCredentialWithToken(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, handle, token, @@ -443,7 +443,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { // Set up pre-SP user password disableSyntheticPassword(); mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); enableSyntheticPassword(); long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); @@ -491,12 +491,12 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { public void testgetHashFactorPrimaryUser() throws RemoteException { final byte[] password = "password".getBytes(); mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); final byte[] hashFactor = mService.getHashFactor(password, PRIMARY_USER_ID); assertNotNull(hashFactor); mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, - password, PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID); + password, PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false); final byte[] newHashFactor = mService.getHashFactor(null, PRIMARY_USER_ID); assertNotNull(newHashFactor); // Hash factor should never change after password change/removal @@ -506,7 +506,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { public void testgetHashFactorManagedProfileUnifiedChallenge() throws RemoteException { final byte[] pattern = "1236".getBytes(); mService.setLockCredential(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, - null, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID); + null, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID, false); mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null); assertNotNull(mService.getHashFactor(null, MANAGED_PROFILE_USER_ID)); } @@ -515,9 +515,9 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { final byte[] primaryPassword = "primary".getBytes(); final byte[] profilePassword = "profile".getBytes(); mService.setLockCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); mService.setLockCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, - PASSWORD_QUALITY_ALPHABETIC, MANAGED_PROFILE_USER_ID); + PASSWORD_QUALITY_ALPHABETIC, MANAGED_PROFILE_USER_ID, false); assertNotNull(mService.getHashFactor(profilePassword, MANAGED_PROFILE_USER_ID)); }