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

Commit fe0f24cc authored by Esteban Talavera's avatar Esteban Talavera
Browse files

Wipe only managed profile when max number of incorrect passwords exceeded

When the maximum number of retries that has been exceeded is not for the primary profile of the user, wipe only the profile that set that policy (e.g. the managed profile) rather than the entire user. At the moment the whole device is wiped if the max number of incorrect passwords for a managed profile is reached, as the password is shared with the USER_OWNER.

Bug: 14453697
Change-Id: I5746de104133c0ea0a51d75b9c92e1516d365d8c
parent 3f1ddf83
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -57,7 +57,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
    }

    public KeyguardSecurityContainer(Context context) {
        this(null, null, 0);
        this(context, null, 0);
    }

    public KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle) {
@@ -240,10 +240,13 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe

        boolean showTimeout = false;
        if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) {
            // If we reach this code, it means the user has installed a DevicePolicyManager
            // that requests device wipe after N attempts.  Once we get below the grace
            // period, we'll post this dialog every time as a clear warning until the
            // bombshell hits and the device is wiped.
            // The user has installed a DevicePolicyManager that requests a user/profile to be wiped
            // N attempts. Once we get below the grace period, we post this dialog every time as a
            // clear warning until the deletion fires.
            //
            // TODO: Show a different dialog depending on whether the device will be completely
            // wiped (i.e. policy is set for the primary profile of the USER_OWNER) or a single
            // secondary user or managed profile will be removed.
            if (remainingBeforeWipe > 0) {
                showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe);
            } else {
+38 −22
Original line number Diff line number Diff line
@@ -2229,30 +2229,39 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
        enforceCrossUserPermission(userHandle);
        synchronized (this) {
            int count = 0;

            if (who != null) {
                ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
                return admin != null ? admin.maximumFailedPasswordsForWipe : count;
            ActiveAdmin admin = (who != null) ? getActiveAdminUncheckedLocked(who, userHandle)
                    : getAdminWithMinimumFailedPasswordsForWipeLocked(userHandle);
            return admin != null ? admin.maximumFailedPasswordsForWipe : 0;
        }
    }

            // Return strictest policy for this user and profiles that are visible from this user.
            List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
            for (UserInfo userInfo : profiles) {
    /**
     * Returns the admin with the strictest policy on maximum failed passwords for this user and all
     * profiles that are visible from this user. If the policy for the primary and any other profile
     * are equal, it returns the admin for the primary profile.
     * Returns {@code null} if none of them have that policy set.
     */
    private ActiveAdmin getAdminWithMinimumFailedPasswordsForWipeLocked(int userHandle) {
        int count = 0;
        ActiveAdmin strictestAdmin = null;
        for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
            DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
                final int N = policy.mAdminList.size();
                for (int i=0; i<N; i++) {
                    ActiveAdmin admin = policy.mAdminList.get(i);
                    if (count == 0) {
                        count = admin.maximumFailedPasswordsForWipe;
                    } else if (admin.maximumFailedPasswordsForWipe != 0
                            && count > admin.maximumFailedPasswordsForWipe) {
                        count = admin.maximumFailedPasswordsForWipe;
            for (ActiveAdmin admin : policy.mAdminList) {
                if (admin.maximumFailedPasswordsForWipe ==
                        ActiveAdmin.DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) {
                    continue;  // No max number of failed passwords policy set for this profile.
                }

                // We always favor the primary profile if several profiles have the same value set.
                if (count == 0 ||
                        count > admin.maximumFailedPasswordsForWipe ||
                        (userInfo.isPrimary() && count >= admin.maximumFailedPasswordsForWipe)) {
                    count = admin.maximumFailedPasswordsForWipe;
                    strictestAdmin = admin;
                }
            }
            return count;
        }
        return strictestAdmin;
    }

    public boolean resetPassword(String password, int flags, int userHandle) {
@@ -2627,7 +2636,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                public void run() {
                    try {
                        ActivityManagerNative.getDefault().switchUser(UserHandle.USER_OWNER);
                        mUserManager.removeUser(userHandle);
                        if (!mUserManager.removeUser(userHandle)) {
                            Slog.w(LOG_TAG, "Couldn't remove user " + userHandle);
                        }
                    } catch (RemoteException re) {
                        // Shouldn't happen
                    }
@@ -2751,9 +2762,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                policy.mFailedPasswordAttempts++;
                saveSettingsLocked(userHandle);
                if (mHasFeature) {
                    int max = getMaximumFailedPasswordsForWipe(null, userHandle);
                    ActiveAdmin strictestAdmin =
                            getAdminWithMinimumFailedPasswordsForWipeLocked(userHandle);
                    int max = strictestAdmin.maximumFailedPasswordsForWipe;
                    if (max > 0 && policy.mFailedPasswordAttempts >= max) {
                        wipeDeviceOrUserLocked(0, userHandle);
                        // Wipe the user/profile associated with the policy that was violated. This
                        // is not necessarily calling user: if the policy that fired was from a
                        // managed profile rather than the main user profile, we wipe former only.
                        wipeDeviceOrUserLocked(0, strictestAdmin.getUserHandle().getIdentifier());
                    }
                    sendAdminCommandToSelfAndProfilesLocked(
                            DeviceAdminReceiver.ACTION_PASSWORD_FAILED,