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

Commit d375476b authored by Rubin Xu's avatar Rubin Xu Committed by android-build-merger
Browse files

Merge "Fix resetPasswordWithToken before user unlock" into oc-mr1-dev am: 2e21fba2

am: c17f1d41

Change-Id: If147939b9c74803ca2c6177e770736b0e82fdc96
parents 3d6e6a63 c17f1d41
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -2533,7 +2533,7 @@ public class DevicePolicyManager {
     * @return Returns true if the password meets the current requirements, else false.
     * @return Returns true if the password meets the current requirements, else false.
     * @throws SecurityException if the calling application does not own an active administrator
     * @throws SecurityException if the calling application does not own an active administrator
     *             that uses {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
     *             that uses {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
     * @throws InvalidStateException if the user is not unlocked.
     * @throws IllegalStateException if the user is not unlocked.
     */
     */
    public boolean isActivePasswordSufficient() {
    public boolean isActivePasswordSufficient() {
        if (mService != null) {
        if (mService != null) {
+17 −3
Original line number Original line Diff line number Diff line
@@ -18,13 +18,11 @@ package android.app.admin;


import android.annotation.IntDef;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.app.admin.DevicePolicyManager;
import android.os.Parcelable;
import android.os.Parcel;
import android.os.Parcel;
import android.os.Parcelable;


import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
import java.io.IOException;


/**
/**
 * A class that represents the metrics of a password that are used to decide whether or not a
 * A class that represents the metrics of a password that are used to decide whether or not a
@@ -159,6 +157,22 @@ public class PasswordMetrics implements Parcelable {
                quality, length, letters, upperCase, lowerCase, numeric, symbols, nonLetter);
                quality, length, letters, upperCase, lowerCase, numeric, symbols, nonLetter);
    }
    }


    @Override
    public boolean equals(Object other) {
        if (!(other instanceof PasswordMetrics)) {
            return false;
        }
        PasswordMetrics o = (PasswordMetrics) other;
        return this.quality == o.quality
                && this.length == o.length
                && this.letters == o.letters
                && this.upperCase == o.upperCase
                && this.lowerCase == o.lowerCase
                && this.numeric == o.numeric
                && this.symbols == o.symbols
                && this.nonLetter == o.nonLetter;
    }

    /*
    /*
     * Returns the maximum length of a sequential characters. A sequence is defined as
     * Returns the maximum length of a sequential characters. A sequence is defined as
     * monotonically increasing characters with a constant interval or the same character repeated.
     * monotonically increasing characters with a constant interval or the same character repeated.
+39 −10
Original line number Original line Diff line number Diff line
@@ -803,12 +803,14 @@ public class LockPatternUtils {
                        + "of length " + MIN_LOCK_PASSWORD_SIZE);
                        + "of length " + MIN_LOCK_PASSWORD_SIZE);
            }
            }


            final int computedQuality = PasswordMetrics.computeForPassword(password).quality;
            setLong(PASSWORD_TYPE_KEY,
            setLong(PASSWORD_TYPE_KEY, Math.max(requestedQuality, computedQuality), userHandle);
                    computePasswordQuality(CREDENTIAL_TYPE_PASSWORD, password, requestedQuality),
                    userHandle);
            getLockSettings().setLockCredential(password, CREDENTIAL_TYPE_PASSWORD, savedPassword,
            getLockSettings().setLockCredential(password, CREDENTIAL_TYPE_PASSWORD, savedPassword,
                    requestedQuality, userHandle);
                    requestedQuality, userHandle);


            updateEncryptionPasswordIfNeeded(password, computedQuality, userHandle);
            updateEncryptionPasswordIfNeeded(password,
                    PasswordMetrics.computeForPassword(password).quality, userHandle);
            updatePasswordHistory(password, userHandle);
            updatePasswordHistory(password, userHandle);
        } catch (RemoteException re) {
        } catch (RemoteException re) {
            // Cant do much
            // Cant do much
@@ -897,6 +899,24 @@ public class LockPatternUtils {
                DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userHandle);
                DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userHandle);
    }
    }


    /**
     * Returns the password quality of the given credential, promoting it to a higher level
     * if DevicePolicyManager has a stronger quality requirement. This value will be written
     * to PASSWORD_TYPE_KEY.
     */
    private int computePasswordQuality(int type, String credential, int requestedQuality) {
        final int quality;
        if (type == CREDENTIAL_TYPE_PASSWORD) {
            int computedQuality = PasswordMetrics.computeForPassword(credential).quality;
            quality = Math.max(requestedQuality, computedQuality);
        } else if (type == CREDENTIAL_TYPE_PATTERN)  {
            quality = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
        } else /* if (type == CREDENTIAL_TYPE_NONE) */ {
            quality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
        }
        return quality;
    }

    /**
    /**
     * Enables/disables the Separate Profile Challenge for this {@param userHandle}. This is a no-op
     * Enables/disables the Separate Profile Challenge for this {@param userHandle}. This is a no-op
     * for user handles that do not belong to a managed profile.
     * for user handles that do not belong to a managed profile.
@@ -1505,25 +1525,34 @@ public class LockPatternUtils {
        }
        }
    }
    }


    public boolean setLockCredentialWithToken(String credential, int type, long tokenHandle,
    /**
            byte[] token, int userId) {
     * Change a user's lock credential with a pre-configured escrow token.
     *
     * @param credential The new credential to be set
     * @param type Credential type: password / pattern / none.
     * @param requestedQuality the requested password quality by DevicePolicyManager.
     *        See {@link DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
     * @param tokenHandle Handle of the escrow token
     * @param token Escrow token
     * @param userId The user who's lock credential to be changed
     * @return {@code true} if the operation is successful.
     */
    public boolean setLockCredentialWithToken(String credential, int type, int requestedQuality,
            long tokenHandle, byte[] token, int userId) {
        try {
        try {
            if (type != CREDENTIAL_TYPE_NONE) {
            if (type != CREDENTIAL_TYPE_NONE) {
                if (TextUtils.isEmpty(credential) || credential.length() < MIN_LOCK_PASSWORD_SIZE) {
                if (TextUtils.isEmpty(credential) || credential.length() < MIN_LOCK_PASSWORD_SIZE) {
                    throw new IllegalArgumentException("password must not be null and at least "
                    throw new IllegalArgumentException("password must not be null and at least "
                            + "of length " + MIN_LOCK_PASSWORD_SIZE);
                            + "of length " + MIN_LOCK_PASSWORD_SIZE);
                }
                }

                final int quality = computePasswordQuality(type, credential, requestedQuality);
                final int computedQuality = PasswordMetrics.computeForPassword(credential).quality;
                int quality = Math.max(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
                        computedQuality);
                if (!getLockSettings().setLockCredentialWithToken(credential, type, tokenHandle,
                if (!getLockSettings().setLockCredentialWithToken(credential, type, tokenHandle,
                        token, quality, userId)) {
                        token, quality, userId)) {
                    return false;
                    return false;
                }
                }
                setLong(PASSWORD_TYPE_KEY, quality, userId);
                setLong(PASSWORD_TYPE_KEY, quality, userId);


                updateEncryptionPasswordIfNeeded(credential, computedQuality, userId);
                updateEncryptionPasswordIfNeeded(credential, quality, userId);
                updatePasswordHistory(credential, userId);
                updatePasswordHistory(credential, userId);
            } else {
            } else {
                if (!TextUtils.isEmpty(credential)) {
                if (!TextUtils.isEmpty(credential)) {
+45 −0
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package android.app.admin;
package android.app.admin;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;


import android.os.Parcel;
import android.os.Parcel;
import android.support.test.filters.SmallTest;
import android.support.test.filters.SmallTest;
@@ -119,4 +120,48 @@ public class PasswordMetricsTest {
        // ordered, but not composed of alphas or digits
        // ordered, but not composed of alphas or digits
        assertEquals(1, PasswordMetrics.maxLengthSequence(":;<=>"));
        assertEquals(1, PasswordMetrics.maxLengthSequence(":;<=>"));
    }
    }

    @Test
    public void testEquals() {
        PasswordMetrics metrics0 = new PasswordMetrics();
        PasswordMetrics metrics1 = new PasswordMetrics();
        assertNotEquals(metrics0, null);
        assertNotEquals(metrics0, new Object());
        assertEquals(metrics0, metrics0);
        assertEquals(metrics0, metrics1);

        assertEquals(new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 4),
                new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 4));

        assertNotEquals(new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 4),
                new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 5));

        assertNotEquals(new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 4),
                new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_COMPLEX, 4));

        metrics0 = PasswordMetrics.computeForPassword("1234abcd,./");
        metrics1 = PasswordMetrics.computeForPassword("1234abcd,./");
        assertEquals(metrics0, metrics1);
        metrics1.letters++;
        assertNotEquals(metrics0, metrics1);
        metrics1.letters--;
        metrics1.upperCase++;
        assertNotEquals(metrics0, metrics1);
        metrics1.upperCase--;
        metrics1.lowerCase++;
        assertNotEquals(metrics0, metrics1);
        metrics1.lowerCase--;
        metrics1.numeric++;
        assertNotEquals(metrics0, metrics1);
        metrics1.numeric--;
        metrics1.symbols++;
        assertNotEquals(metrics0, metrics1);
        metrics1.symbols--;
        metrics1.nonLetter++;
        assertNotEquals(metrics0, metrics1);
        metrics1.nonLetter--;
        assertEquals(metrics0, metrics1);


    }
}
}
+14 −3
Original line number Original line Diff line number Diff line
@@ -154,7 +154,8 @@ public class LockSettingsService extends ILockSettings.Stub {


    private final Injector mInjector;
    private final Injector mInjector;
    private final Context mContext;
    private final Context mContext;
    private final Handler mHandler;
    @VisibleForTesting
    protected final Handler mHandler;
    @VisibleForTesting
    @VisibleForTesting
    protected final LockSettingsStorage mStorage;
    protected final LockSettingsStorage mStorage;
    private final LockSettingsStrongAuth mStrongAuth;
    private final LockSettingsStrongAuth mStrongAuth;
@@ -1736,6 +1737,10 @@ public class LockSettingsService extends ILockSettings.Stub {
        return response;
        return response;
    }
    }


    /**
     * Call this method to notify DPMS regarding the latest password metric. This should be called
     * when the user is authenticating or when a new password is being set.
     */
    private void notifyActivePasswordMetricsAvailable(String password, @UserIdInt int userId) {
    private void notifyActivePasswordMetricsAvailable(String password, @UserIdInt int userId) {
        final PasswordMetrics metrics;
        final PasswordMetrics metrics;
        if (password == null) {
        if (password == null) {
@@ -2197,6 +2202,8 @@ public class LockSettingsService extends ILockSettings.Stub {
        }
        }
        setLong(SYNTHETIC_PASSWORD_HANDLE_KEY, newHandle, userId);
        setLong(SYNTHETIC_PASSWORD_HANDLE_KEY, newHandle, userId);
        synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords);
        synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords);

        notifyActivePasswordMetricsAvailable(credential, userId);
        return newHandle;
        return newHandle;
    }
    }


@@ -2246,13 +2253,13 @@ public class LockSettingsService extends ILockSettings.Stub {
                    userId);
                    userId);
            synchronizeUnifiedWorkChallengeForProfiles(userId, null);
            synchronizeUnifiedWorkChallengeForProfiles(userId, null);
            mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
            mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);

            notifyActivePasswordMetricsAvailable(credential, userId);
        } else /* response == null || responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ {
        } else /* response == null || responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ {
            Slog.w(TAG, "spBasedSetLockCredentialInternalLocked: " +
            Slog.w(TAG, "spBasedSetLockCredentialInternalLocked: " +
                    (response != null ? "rate limit exceeded" : "failed"));
                    (response != null ? "rate limit exceeded" : "failed"));
            return;
            return;
        }
        }
        notifyActivePasswordMetricsAvailable(credential, userId);

    }
    }


    @Override
    @Override
@@ -2358,6 +2365,10 @@ public class LockSettingsService extends ILockSettings.Stub {
                Slog.w(TAG, "Invalid escrow token supplied");
                Slog.w(TAG, "Invalid escrow token supplied");
                return false;
                return false;
            }
            }
            // Update PASSWORD_TYPE_KEY since it's needed by notifyActivePasswordMetricsAvailable()
            // called by setLockCredentialWithAuthTokenLocked().
            // TODO: refactor usage of PASSWORD_TYPE_KEY b/65239740
            setLong(LockPatternUtils.PASSWORD_TYPE_KEY, requestedQuality, userId);
            long oldHandle = getSyntheticPasswordHandleLocked(userId);
            long oldHandle = getSyntheticPasswordHandleLocked(userId);
            setLockCredentialWithAuthTokenLocked(credential, type, result.authToken,
            setLockCredentialWithAuthTokenLocked(credential, type, result.authToken,
                    requestedQuality, userId);
                    requestedQuality, userId);
Loading