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

Commit 1641c5c4 authored by Eran Messeri's avatar Eran Messeri
Browse files

Implement setRequiredPasswordComplexity

Implement setRequiredPasswordComplexity and
getRequiredPasswordComplexity, which enforce password requiremets
according to one of four, platform-defined complexity levels.

Start adjusting the platform to take the complexity into account:
* isActivePasswordSufficient would return false if complexity is set
  but the current password does not meet the complexity criteria.
* resetPasswordWithToken would not allow resetting the password to a
  value that does not meet the complexity criteria.

Bug: 165573442
Test: atest FrameworksServicesTests:DevicePolicyManagerTest
Test: atest com.android.cts.devicepolicy.MixedDeviceOwnerTest#testResetPasswordWithToken
Change-Id: I4e66af0b03c521de70bba3192751164736d01c62
parent 1a9bdc12
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -6950,6 +6950,7 @@ package android.app.admin {
    method @Nullable public java.util.List<java.lang.String> getPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName);
    method @Nullable public java.util.List<java.lang.String> getPermittedInputMethods(@NonNull android.content.ComponentName);
    method public int getPersonalAppsSuspendedReasons(@NonNull android.content.ComponentName);
    method public int getRequiredPasswordComplexity();
    method public long getRequiredStrongAuthTimeout(@Nullable android.content.ComponentName);
    method public boolean getScreenCaptureDisabled(@Nullable android.content.ComponentName);
    method public java.util.List<android.os.UserHandle> getSecondaryUsers(@NonNull android.content.ComponentName);
@@ -7081,6 +7082,7 @@ package android.app.admin {
    method public void setProfileEnabled(@NonNull android.content.ComponentName);
    method public void setProfileName(@NonNull android.content.ComponentName, String);
    method public void setRecommendedGlobalProxy(@NonNull android.content.ComponentName, @Nullable android.net.ProxyInfo);
    method public void setRequiredPasswordComplexity(int);
    method public void setRequiredStrongAuthTimeout(@NonNull android.content.ComponentName, long);
    method public boolean setResetPasswordToken(android.content.ComponentName, byte[]);
    method public void setRestrictionsProvider(@NonNull android.content.ComponentName, @Nullable android.content.ComponentName);
+2 −0
Original line number Diff line number Diff line
@@ -6950,6 +6950,7 @@ package android.app.admin {
    method @Nullable public java.util.List<java.lang.String> getPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName);
    method @Nullable public java.util.List<java.lang.String> getPermittedInputMethods(@NonNull android.content.ComponentName);
    method public int getPersonalAppsSuspendedReasons(@NonNull android.content.ComponentName);
    method public int getRequiredPasswordComplexity();
    method public long getRequiredStrongAuthTimeout(@Nullable android.content.ComponentName);
    method public boolean getScreenCaptureDisabled(@Nullable android.content.ComponentName);
    method public java.util.List<android.os.UserHandle> getSecondaryUsers(@NonNull android.content.ComponentName);
@@ -7081,6 +7082,7 @@ package android.app.admin {
    method public void setProfileEnabled(@NonNull android.content.ComponentName);
    method public void setProfileName(@NonNull android.content.ComponentName, String);
    method public void setRecommendedGlobalProxy(@NonNull android.content.ComponentName, @Nullable android.net.ProxyInfo);
    method public void setRequiredPasswordComplexity(int);
    method public void setRequiredStrongAuthTimeout(@NonNull android.content.ComponentName, long);
    method public boolean setResetPasswordToken(android.content.ComponentName, byte[]);
    method public void setRestrictionsProvider(@NonNull android.content.ComponentName, @Nullable android.content.ComponentName);
+71 −1
Original line number Diff line number Diff line
@@ -2729,6 +2729,9 @@ public class DevicePolicyManager {
     * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
     * profile.
     *
     * <p><strong>Note:</strong> Specifying password requirements using this method clears the
     * password complexity requirements set using {@link #setRequiredPasswordComplexity(int)}.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param quality The new desired quality. One of {@link #PASSWORD_QUALITY_UNSPECIFIED},
     *            {@link #PASSWORD_QUALITY_BIOMETRIC_WEAK},
@@ -3607,13 +3610,18 @@ public class DevicePolicyManager {
     * <p>Note that when called from a profile which uses an unified challenge with its parent, the
     * screen lock complexity of the parent will be returned.
     *
     * <p>Apps need the {@link permission#REQUEST_PASSWORD_COMPLEXITY} permission to call this
     * method. On Android {@link android.os.Build.VERSION_CODES#S} and above, the calling
     * application does not need this permission if it is a device owner or a profile owner.
     *
     * <p>This method can be called on the {@link DevicePolicyManager} instance
     * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
     * restrictions on the parent profile.
     *
     * @throws IllegalStateException if the user is not unlocked.
     * @throws SecurityException     if the calling application does not have the permission
     *                               {@link permission#REQUEST_PASSWORD_COMPLEXITY}
     *                               {@link permission#REQUEST_PASSWORD_COMPLEXITY}, and is not a
     *                               device owner or a profile owner.
     */
    @PasswordComplexity
    @RequiresPermission(android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY)
@@ -3629,6 +3637,66 @@ public class DevicePolicyManager {
        }
    }
    /**
     * Sets a password complexity requirement for the user's screen lock.
     * The complexity level is one of the pre-defined levels.
     *
     * <p>Note that when called on a profile which uses an unified challenge with its parent, the
     * complexity would apply to the unified challenge.
     *
     * <p>This method can be called on the {@link DevicePolicyManager} instance
     * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
     * restrictions on the parent profile.
     *
     * <p><strong>Note:</strong> Specifying password requirements using this method clears any
     * password requirements set using the obsolete {@link #setPasswordQuality(ComponentName, int)}
     * and any of its associated methods.
     *
     * @throws SecurityException if the calling application is not a device owner or a profile
     * owner.
     * @throws IllegalArgumentException if the complexity level is not one of the four above.
     */
    public void setRequiredPasswordComplexity(@PasswordComplexity int passwordComplexity) {
        if (mService == null) {
            return;
        }
        try {
            mService.setRequiredPasswordComplexity(passwordComplexity, mParentInstance);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    /**
     * Gets the password complexity requirement set by {@link #setRequiredPasswordComplexity(int)},
     * for the current user.
     *
     * <p>The difference between this method and {@link #getPasswordComplexity()} is that this
     * method simply returns the value set by {@link #setRequiredPasswordComplexity(int)} while
     * {@link #getPasswordComplexity()} returns the complexity of the actual password.
     *
     * <p>This method can be called on the {@link DevicePolicyManager} instance
     * returned by {@link #getParentProfileInstance(ComponentName)} in order to get
     * restrictions on the parent profile.
     *
     * @throws SecurityException if the calling application is not a device owner or a profile
     * owner.
     */
    @PasswordComplexity
    public int getRequiredPasswordComplexity() {
        if (mService == null) {
            return PASSWORD_COMPLEXITY_NONE;
        }
        try {
            return mService.getRequiredPasswordComplexity(mParentInstance);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    /**
     * When called by a profile owner of a managed profile returns true if the profile uses unified
     * challenge with its parent user.
@@ -9987,6 +10055,8 @@ public class DevicePolicyManager {
     * <li>{@link #getRequiredStrongAuthTimeout}</li>
     * <li>{@link #setRequiredStrongAuthTimeout}</li>
     * <li>{@link #getAccountTypesWithManagementDisabled}</li>
     * <li>{@link #setRequiredPasswordComplexity(int)} </li>
     * <li>{@link #getRequiredPasswordComplexity()}</li>
     * </ul>
     * <p>
     * The following methods are supported for the parent instance but can only be called by the
+2 −0
Original line number Diff line number Diff line
@@ -87,6 +87,8 @@ interface IDevicePolicyManager {
    boolean isProfileActivePasswordSufficientForParent(int userHandle);
    boolean isPasswordSufficientAfterProfileUnification(int userHandle, int profileUser);
    int getPasswordComplexity(boolean parent);
    void setRequiredPasswordComplexity(int passwordComplexity, boolean parent);
    int getRequiredPasswordComplexity(boolean parent);
    boolean isUsingUnifiedPassword(in ComponentName admin);
    int getCurrentFailedPasswordAttempts(int userHandle, boolean parent);
    int getProfileWithMinimumFailedPasswordsForWipe(int userHandle, boolean parent);
+14 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.devicepolicy;

import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;

import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
@@ -130,6 +131,7 @@ class ActiveAdmin {
    private static final String TAG_ALWAYS_ON_VPN_PACKAGE = "vpn-package";
    private static final String TAG_ALWAYS_ON_VPN_LOCKDOWN = "vpn-lockdown";
    private static final String TAG_COMMON_CRITERIA_MODE = "common-criteria-mode";
    private static final String TAG_PASSWORD_COMPLEXITY = "password-complexity";
    private static final String ATTR_VALUE = "value";
    private static final String ATTR_LAST_NETWORK_LOGGING_NOTIFICATION = "last-notification";
    private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications";
@@ -142,6 +144,9 @@ class ActiveAdmin {
    @NonNull
    PasswordPolicy mPasswordPolicy = new PasswordPolicy();

    @DevicePolicyManager.PasswordComplexity
    int mPasswordComplexity = PASSWORD_COMPLEXITY_NONE;

    @Nullable
    FactoryResetProtectionPolicy mFactoryResetProtectionPolicy = null;

@@ -518,6 +523,10 @@ class ActiveAdmin {
        if (mCommonCriteriaMode) {
            writeAttributeValueToXml(out, TAG_COMMON_CRITERIA_MODE, mCommonCriteriaMode);
        }

        if (mPasswordComplexity != PASSWORD_COMPLEXITY_NONE) {
            writeAttributeValueToXml(out, TAG_PASSWORD_COMPLEXITY, mPasswordComplexity);
        }
    }

    void writeTextToXml(XmlSerializer out, String tag, String text) throws IOException {
@@ -777,6 +786,8 @@ class ActiveAdmin {
            } else if (TAG_COMMON_CRITERIA_MODE.equals(tag)) {
                mCommonCriteriaMode = Boolean.parseBoolean(
                        parser.getAttributeValue(null, ATTR_VALUE));
            } else if (TAG_PASSWORD_COMPLEXITY.equals(tag)) {
                mPasswordComplexity = Integer.parseInt(parser.getAttributeValue(null, ATTR_VALUE));
            } else {
                Slog.w(DevicePolicyManagerService.LOG_TAG, "Unknown admin tag: " + tag);
                XmlUtils.skipCurrentTag(parser);
@@ -1112,5 +1123,8 @@ class ActiveAdmin {

        pw.print("mCommonCriteriaMode=");
        pw.println(mCommonCriteriaMode);

        pw.print("mPasswordComplexity=");
        pw.println(mPasswordComplexity);
    }
}
Loading