Merge "Don't save the password metrics to disk."
This commit is contained in:
@@ -2304,7 +2304,7 @@ public class DevicePolicyManager {
|
||||
* Determine whether the current password the user has set is sufficient to meet the policy
|
||||
* requirements (e.g. quality, minimum length) that have been requested by the admins of this
|
||||
* user and its participating profiles. Restrictions on profiles that have a separate challenge
|
||||
* are not taken into account.
|
||||
* are not taken into account. The user must be unlocked in order to perform the check.
|
||||
* <p>
|
||||
* The calling device admin must have requested
|
||||
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
|
||||
@@ -2317,6 +2317,7 @@ public class DevicePolicyManager {
|
||||
* @return Returns true if the password meets the current requirements, else false.
|
||||
* @throws SecurityException if the calling application does not own an active administrator
|
||||
* that uses {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
|
||||
* @throws InvalidStateException if the user is not unlocked.
|
||||
*/
|
||||
public boolean isActivePasswordSufficient() {
|
||||
if (mService != null) {
|
||||
@@ -3824,6 +3825,19 @@ public class DevicePolicyManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public void reportPasswordChanged(@UserIdInt int userId) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService.reportPasswordChanged(userId);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -123,6 +123,7 @@ interface IDevicePolicyManager {
|
||||
boolean hasGrantedPolicy(in ComponentName policyReceiver, int usesPolicy, int userHandle);
|
||||
|
||||
void setActivePasswordState(in PasswordMetrics metrics, int userHandle);
|
||||
void reportPasswordChanged(int userId);
|
||||
void reportFailedPasswordAttempt(int userHandle);
|
||||
void reportSuccessfulPasswordAttempt(int userHandle);
|
||||
void reportFailedFingerprintAttempt(int userHandle);
|
||||
|
||||
@@ -590,8 +590,6 @@ public class LockPatternUtils {
|
||||
setCredentialRequiredToDecrypt(false);
|
||||
}
|
||||
|
||||
getDevicePolicyManager().setActivePasswordState(new PasswordMetrics(), userHandle);
|
||||
|
||||
onAfterChangingPassword(userHandle);
|
||||
}
|
||||
|
||||
@@ -644,6 +642,7 @@ public class LockPatternUtils {
|
||||
+ MIN_LOCK_PATTERN_SIZE + " dots long.");
|
||||
}
|
||||
|
||||
setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId);
|
||||
getLockSettings().setLockPattern(patternToString(pattern), savedPattern, userId);
|
||||
DevicePolicyManager dpm = getDevicePolicyManager();
|
||||
|
||||
@@ -659,10 +658,6 @@ public class LockPatternUtils {
|
||||
}
|
||||
|
||||
setBoolean(PATTERN_EVER_CHOSEN_KEY, true, userId);
|
||||
|
||||
setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId);
|
||||
dpm.setActivePasswordState(new PasswordMetrics(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, pattern.size()), userId);
|
||||
onAfterChangingPassword(userId);
|
||||
} catch (RemoteException re) {
|
||||
Log.e(TAG, "Couldn't save lock pattern " + re);
|
||||
@@ -775,10 +770,9 @@ public class LockPatternUtils {
|
||||
+ "of length " + MIN_LOCK_PASSWORD_SIZE);
|
||||
}
|
||||
|
||||
final int computedQuality = PasswordMetrics.computeForPassword(password).quality;
|
||||
setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle);
|
||||
getLockSettings().setLockPassword(password, savedPassword, userHandle);
|
||||
getLockSettings().setSeparateProfileChallengeEnabled(userHandle, true, null);
|
||||
final PasswordMetrics metrics = PasswordMetrics.computeForPassword(password);
|
||||
final int computedQuality = metrics.quality;
|
||||
|
||||
// Update the device encryption password.
|
||||
if (userHandle == UserHandle.USER_SYSTEM
|
||||
@@ -796,15 +790,6 @@ public class LockPatternUtils {
|
||||
}
|
||||
}
|
||||
|
||||
setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle);
|
||||
if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
|
||||
metrics.quality = Math.max(quality, metrics.quality);
|
||||
dpm.setActivePasswordState(metrics, userHandle);
|
||||
} else {
|
||||
// The password is not anything.
|
||||
dpm.setActivePasswordState(new PasswordMetrics(), userHandle);
|
||||
}
|
||||
|
||||
// Add the password to the password history. We assume all
|
||||
// password hashes have the same length for simplicity of implementation.
|
||||
String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
|
||||
package com.android.server;
|
||||
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.KeyguardManager;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.admin.PasswordMetrics;
|
||||
import android.app.backup.BackupManager;
|
||||
import android.app.trust.IStrongAuthTracker;
|
||||
import android.app.trust.TrustManager;
|
||||
@@ -931,6 +933,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
synchronized (mSeparateChallengeLock) {
|
||||
setLockPatternInternal(pattern, savedCredential, userId);
|
||||
setSeparateProfileChallengeEnabled(userId, true, null);
|
||||
notifyPasswordChanged(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -945,6 +948,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
setKeystorePassword(null, userId);
|
||||
fixateNewestUserKeyAuth(userId);
|
||||
onUserLockChanged(userId);
|
||||
notifyActivePasswordMetricsAvailable(null, userId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -994,6 +998,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
synchronized (mSeparateChallengeLock) {
|
||||
setLockPasswordInternal(password, savedCredential, userId);
|
||||
setSeparateProfileChallengeEnabled(userId, true, null);
|
||||
notifyPasswordChanged(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1007,6 +1012,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
setKeystorePassword(null, userId);
|
||||
fixateNewestUserKeyAuth(userId);
|
||||
onUserLockChanged(userId);
|
||||
notifyActivePasswordMetricsAvailable(null, userId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1420,6 +1426,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
// migrate credential to GateKeeper
|
||||
credentialUtil.setCredential(credential, null, userId);
|
||||
if (!hasChallenge) {
|
||||
notifyActivePasswordMetricsAvailable(credential, userId);
|
||||
return VerifyCredentialResponse.OK;
|
||||
}
|
||||
// Fall through to get the auth token. Technically this should never happen,
|
||||
@@ -1459,6 +1466,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
if (progressCallback != null) {
|
||||
progressCallback.onCredentialVerified();
|
||||
}
|
||||
notifyActivePasswordMetricsAvailable(credential, userId);
|
||||
unlockKeystore(credential, userId);
|
||||
|
||||
Slog.i(TAG, "Unlocking user " + userId +
|
||||
@@ -1482,6 +1490,36 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
return response;
|
||||
}
|
||||
|
||||
private void notifyActivePasswordMetricsAvailable(String password, @UserIdInt int userId) {
|
||||
final PasswordMetrics metrics;
|
||||
if (password == null) {
|
||||
metrics = new PasswordMetrics();
|
||||
} else {
|
||||
metrics = PasswordMetrics.computeForPassword(password);
|
||||
metrics.quality = mLockPatternUtils.getKeyguardStoredPasswordQuality(userId);
|
||||
}
|
||||
|
||||
// Asynchronous to avoid dead lock
|
||||
mHandler.post(() -> {
|
||||
DevicePolicyManager dpm = (DevicePolicyManager)
|
||||
mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
|
||||
dpm.setActivePasswordState(metrics, userId);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Call after {@link #notifyActivePasswordMetricsAvailable} so metrics are updated before
|
||||
* reporting the password changed.
|
||||
*/
|
||||
private void notifyPasswordChanged(@UserIdInt int userId) {
|
||||
// Same handler as notifyActivePasswordMetricsAvailable to ensure correct ordering
|
||||
mHandler.post(() -> {
|
||||
DevicePolicyManager dpm = (DevicePolicyManager)
|
||||
mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
|
||||
dpm.reportPasswordChanged(userId);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkVoldPassword(int userId) throws RemoteException {
|
||||
if (!mFirstCallToVold) {
|
||||
|
||||
@@ -253,7 +253,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
private static final String ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED =
|
||||
"device-provisioning-config-applied";
|
||||
private static final String ATTR_DEVICE_PAIRED = "device-paired";
|
||||
|
||||
private static final String ATTR_DELEGATED_CERT_INSTALLER = "delegated-cert-installer";
|
||||
private static final String ATTR_APPLICATION_RESTRICTIONS_MANAGER
|
||||
= "application-restrictions-manager";
|
||||
@@ -2342,20 +2341,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
out.endTag(null, "failed-password-attempts");
|
||||
}
|
||||
|
||||
final PasswordMetrics metrics = policy.mActivePasswordMetrics;
|
||||
if (!metrics.isDefault()) {
|
||||
out.startTag(null, "active-password");
|
||||
out.attribute(null, "quality", Integer.toString(metrics.quality));
|
||||
out.attribute(null, "length", Integer.toString(metrics.length));
|
||||
out.attribute(null, "uppercase", Integer.toString(metrics.upperCase));
|
||||
out.attribute(null, "lowercase", Integer.toString(metrics.lowerCase));
|
||||
out.attribute(null, "letters", Integer.toString(metrics.letters));
|
||||
out.attribute(null, "numeric", Integer.toString(metrics.numeric));
|
||||
out.attribute(null, "symbols", Integer.toString(metrics.symbols));
|
||||
out.attribute(null, "nonletter", Integer.toString(metrics.nonLetter));
|
||||
out.endTag(null, "active-password");
|
||||
}
|
||||
|
||||
for (int i = 0; i < policy.mAcceptedCaCertificates.size(); i++) {
|
||||
out.startTag(null, TAG_ACCEPTED_CA_CERTIFICATES);
|
||||
out.attribute(null, ATTR_NAME, policy.mAcceptedCaCertificates.valueAt(i));
|
||||
@@ -2456,6 +2441,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
JournaledFile journal = makeJournaledFile(userHandle);
|
||||
FileInputStream stream = null;
|
||||
File file = journal.chooseForRead();
|
||||
boolean needsRewrite = false;
|
||||
try {
|
||||
stream = new FileInputStream(file);
|
||||
XmlPullParser parser = Xml.newPullParser();
|
||||
@@ -2542,16 +2528,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
} else if ("password-owner".equals(tag)) {
|
||||
policy.mPasswordOwner = Integer.parseInt(
|
||||
parser.getAttributeValue(null, "value"));
|
||||
} else if ("active-password".equals(tag)) {
|
||||
final PasswordMetrics m = policy.mActivePasswordMetrics;
|
||||
m.quality = Integer.parseInt(parser.getAttributeValue(null, "quality"));
|
||||
m.length = Integer.parseInt(parser.getAttributeValue(null, "length"));
|
||||
m.upperCase = Integer.parseInt(parser.getAttributeValue(null, "uppercase"));
|
||||
m.lowerCase = Integer.parseInt(parser.getAttributeValue(null, "lowercase"));
|
||||
m.letters = Integer.parseInt(parser.getAttributeValue(null, "letters"));
|
||||
m.numeric = Integer.parseInt(parser.getAttributeValue(null, "numeric"));
|
||||
m.symbols = Integer.parseInt(parser.getAttributeValue(null, "symbols"));
|
||||
m.nonLetter = Integer.parseInt(parser.getAttributeValue(null, "nonletter"));
|
||||
} else if (TAG_ACCEPTED_CA_CERTIFICATES.equals(tag)) {
|
||||
policy.mAcceptedCaCertificates.add(parser.getAttributeValue(null, ATTR_NAME));
|
||||
} else if (TAG_LOCK_TASK_COMPONENTS.equals(tag)) {
|
||||
@@ -2577,6 +2553,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
policy.mAdminBroadcastPending = Boolean.toString(true).equals(pending);
|
||||
} else if (TAG_INITIALIZATION_BUNDLE.equals(tag)) {
|
||||
policy.mInitBundle = PersistableBundle.restoreFromXml(parser);
|
||||
} else if ("active-password".equals(tag)) {
|
||||
needsRewrite = true;
|
||||
} else {
|
||||
Slog.w(LOG_TAG, "Unknown tag: " + tag);
|
||||
XmlUtils.skipCurrentTag(parser);
|
||||
@@ -2596,27 +2574,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
// Might need to upgrade the file by rewriting it
|
||||
if (needsRewrite) {
|
||||
saveSettingsLocked(userHandle);
|
||||
}
|
||||
|
||||
// Generate a list of admins from the admin map
|
||||
policy.mAdminList.addAll(policy.mAdminMap.values());
|
||||
|
||||
// Validate that what we stored for the password quality matches
|
||||
// sufficiently what is currently set. Note that this is only
|
||||
// a sanity check in case the two get out of sync; this should
|
||||
// never normally happen.
|
||||
final long identity = mInjector.binderClearCallingIdentity();
|
||||
try {
|
||||
int actualPasswordQuality = mLockPatternUtils.getActivePasswordQuality(userHandle);
|
||||
if (actualPasswordQuality < policy.mActivePasswordMetrics.quality) {
|
||||
Slog.w(LOG_TAG, "Active password quality 0x"
|
||||
+ Integer.toHexString(policy.mActivePasswordMetrics.quality)
|
||||
+ " does not match actual quality 0x"
|
||||
+ Integer.toHexString(actualPasswordQuality));
|
||||
policy.mActivePasswordMetrics = new PasswordMetrics();
|
||||
}
|
||||
} finally {
|
||||
mInjector.binderRestoreCallingIdentity(identity);
|
||||
}
|
||||
|
||||
validatePasswordOwnerLocked(policy);
|
||||
updateMaximumTimeToLockLocked(userHandle);
|
||||
updateLockTaskPackagesLocked(policy.mLockTaskPackages, userHandle);
|
||||
@@ -3850,6 +3815,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
|
||||
private boolean isActivePasswordSufficientForUserLocked(
|
||||
DevicePolicyData policy, int userHandle, boolean parent) {
|
||||
enforceUserUnlocked(userHandle, parent);
|
||||
|
||||
final int requiredPasswordQuality = getPasswordQuality(null, userHandle, parent);
|
||||
if (policy.mActivePasswordMetrics.quality < requiredPasswordQuality) {
|
||||
return false;
|
||||
@@ -4924,33 +4891,52 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
return;
|
||||
}
|
||||
enforceFullCrossUsersPermission(userHandle);
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
|
||||
|
||||
// If the managed profile doesn't have a separate password, set the metrics to default
|
||||
if (isManagedProfile(userHandle) && !isSeparateProfileChallengeEnabled(userHandle)) {
|
||||
metrics = new PasswordMetrics();
|
||||
}
|
||||
|
||||
validateQualityConstant(metrics.quality);
|
||||
DevicePolicyData policy = getUserData(userHandle);
|
||||
synchronized (this) {
|
||||
policy.mActivePasswordMetrics = metrics;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportPasswordChanged(@UserIdInt int userId) {
|
||||
if (!mHasFeature) {
|
||||
return;
|
||||
}
|
||||
enforceFullCrossUsersPermission(userId);
|
||||
|
||||
// Managed Profile password can only be changed when it has a separate challenge.
|
||||
if (!isSeparateProfileChallengeEnabled(userHandle)) {
|
||||
enforceNotManagedProfile(userHandle, "set the active password");
|
||||
if (!isSeparateProfileChallengeEnabled(userId)) {
|
||||
enforceNotManagedProfile(userId, "set the active password");
|
||||
}
|
||||
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
|
||||
validateQualityConstant(metrics.quality);
|
||||
|
||||
DevicePolicyData policy = getUserData(userHandle);
|
||||
DevicePolicyData policy = getUserData(userId);
|
||||
|
||||
long ident = mInjector.binderClearCallingIdentity();
|
||||
try {
|
||||
synchronized (this) {
|
||||
policy.mActivePasswordMetrics = metrics;
|
||||
policy.mFailedPasswordAttempts = 0;
|
||||
saveSettingsLocked(userHandle);
|
||||
updatePasswordExpirationsLocked(userHandle);
|
||||
setExpirationAlarmCheckLocked(mContext, userHandle, /* parent */ false);
|
||||
saveSettingsLocked(userId);
|
||||
updatePasswordExpirationsLocked(userId);
|
||||
setExpirationAlarmCheckLocked(mContext, userId, /* parent */ false);
|
||||
|
||||
// Send a broadcast to each profile using this password as its primary unlock.
|
||||
sendAdminCommandForLockscreenPoliciesLocked(
|
||||
DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
|
||||
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, userHandle);
|
||||
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, userId);
|
||||
}
|
||||
removeCaApprovalsIfNeeded(userHandle);
|
||||
removeCaApprovalsIfNeeded(userId);
|
||||
} finally {
|
||||
mInjector.binderRestoreCallingIdentity(ident);
|
||||
}
|
||||
@@ -6598,6 +6584,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
"User must be running and unlocked");
|
||||
}
|
||||
|
||||
private void enforceUserUnlocked(@UserIdInt int userId, boolean parent) {
|
||||
if (parent) {
|
||||
enforceUserUnlocked(getProfileParentId(userId));
|
||||
} else {
|
||||
enforceUserUnlocked(userId);
|
||||
}
|
||||
}
|
||||
|
||||
private void enforceManageUsers() {
|
||||
final int callingUid = mInjector.binderGetCallingUid();
|
||||
if (!(isCallerWithSystemUid() || callingUid == Process.ROOT_UID)) {
|
||||
|
||||
Reference in New Issue
Block a user