summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Miller <jaggies@google.com>2014-01-31 17:08:37 -0800
committerJim Miller <jaggies@google.com>2014-07-10 01:54:49 +0000
commit85516d028b2dcc7ebc09f4a68085836aa26191d5 (patch)
treea36227d94fd559b29cdb7ed6240324808e3c7d78
parent9f6414d0e6348e2f9ebbaede0424608220cba24c (diff)
downloadframeworks_base-85516d028b2dcc7ebc09f4a68085836aa26191d5.zip
frameworks_base-85516d028b2dcc7ebc09f4a68085836aa26191d5.tar.gz
frameworks_base-85516d028b2dcc7ebc09f4a68085836aa26191d5.tar.bz2
Add new "pin complex" type to supported keyguard PINs
This adds a feature to allow DevicePolicyAdmins to prevent using simple PINs, which are defined as those containing more than 3 repeated values. Examples include '1234', '2468', '1111', '9876', etc. Bug 12081139 Change-Id: I4ebe1c76a48087dcd7c878e9bd79a4e3ee2a27fe
-rw-r--r--api/current.txt1
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java25
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java77
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java1
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java1
5 files changed, 96 insertions, 9 deletions
diff --git a/api/current.txt b/api/current.txt
index 29ec56b..60a18d8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5372,6 +5372,7 @@ package android.app.admin {
field public static final int PASSWORD_QUALITY_BIOMETRIC_WEAK = 32768; // 0x8000
field public static final int PASSWORD_QUALITY_COMPLEX = 393216; // 0x60000
field public static final int PASSWORD_QUALITY_NUMERIC = 131072; // 0x20000
+ field public static final int PASSWORD_QUALITY_NUMERIC_COMPLEX = 196608; // 0x30000
field public static final int PASSWORD_QUALITY_SOMETHING = 65536; // 0x10000
field public static final int PASSWORD_QUALITY_UNSPECIFIED = 0; // 0x0
field public static final java.lang.String PROVISIONING_NFC_MIME_TYPE = "application/com.android.managedprovisioning";
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 49b1d10..2feec1b 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -509,6 +509,14 @@ public class DevicePolicyManager {
/**
* Constant for {@link #setPasswordQuality}: the user must have entered a
+ * password containing at least numeric characters with no repeating (4444)
+ * or ordered (1234, 4321, 2468) sequences. Note that quality
+ * constants are ordered so that higher values are more restrictive.
+ */
+ public static final int PASSWORD_QUALITY_NUMERIC_COMPLEX = 0x30000;
+
+ /**
+ * Constant for {@link #setPasswordQuality}: the user must have entered a
* password containing at least alphabetic (or other symbol) characters.
* Note that quality constants are ordered so that higher values are more
* restrictive.
@@ -556,8 +564,9 @@ public class DevicePolicyManager {
* @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_SOMETHING},
- * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_ALPHABETIC},
- * {@link #PASSWORD_QUALITY_ALPHANUMERIC} or {@link #PASSWORD_QUALITY_COMPLEX}.
+ * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX},
+ * {@link #PASSWORD_QUALITY_ALPHABETIC}, {@link #PASSWORD_QUALITY_ALPHANUMERIC}
+ * or {@link #PASSWORD_QUALITY_COMPLEX}.
*/
public void setPasswordQuality(ComponentName admin, int quality) {
if (mService != null) {
@@ -600,9 +609,9 @@ public class DevicePolicyManager {
* take place immediately. To prompt the user for a new password, use
* {@link #ACTION_SET_NEW_PASSWORD} after setting this value. This
* constraint is only imposed if the administrator has also requested either
- * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_ALPHABETIC}
- * {@link #PASSWORD_QUALITY_ALPHANUMERIC}, or {@link #PASSWORD_QUALITY_COMPLEX}
- * with {@link #setPasswordQuality}.
+ * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX},
+ * {@link #PASSWORD_QUALITY_ALPHABETIC}, {@link #PASSWORD_QUALITY_ALPHANUMERIC},
+ * or {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}.
*
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
@@ -1008,9 +1017,9 @@ public class DevicePolicyManager {
* the change does not take place immediately. To prompt the user for a new
* password, use {@link #ACTION_SET_NEW_PASSWORD} after setting this value.
* This constraint is only imposed if the administrator has also requested
- * either {@link #PASSWORD_QUALITY_NUMERIC},
- * {@link #PASSWORD_QUALITY_ALPHABETIC}, or
- * {@link #PASSWORD_QUALITY_ALPHANUMERIC} with {@link #setPasswordQuality}.
+ * either {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX}
+ * {@link #PASSWORD_QUALITY_ALPHABETIC}, or {@link #PASSWORD_QUALITY_ALPHANUMERIC}
+ * with {@link #setPasswordQuality}.
*
* <p>
* The calling device admin must have requested
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 5409de7..f40b84c 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -150,6 +150,10 @@ public class LockPatternUtils {
private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents";
+ // Maximum allowed number of repeated or ordered characters in a sequence before we'll
+ // consider it a complex PIN/password.
+ public static final int MAX_ALLOWED_SEQUENCE = 3;
+
private final Context mContext;
private final ContentResolver mContentResolver;
private DevicePolicyManager mDevicePolicyManager;
@@ -441,6 +445,11 @@ public class LockPatternUtils {
activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
}
break;
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
+ if (isLockPasswordEnabled()) {
+ activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
+ }
+ break;
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
if (isLockPasswordEnabled()) {
activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
@@ -625,11 +634,74 @@ public class LockPatternUtils {
return DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
}
if (hasDigit) {
- return DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+ return maxLengthSequence(password) > MAX_ALLOWED_SEQUENCE
+ ? DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
+ : DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
}
return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
}
+ private static int categoryChar(char c) {
+ if ('a' <= c && c <= 'z') return 0;
+ if ('A' <= c && c <= 'Z') return 1;
+ if ('0' <= c && c <= '9') return 2;
+ return 3;
+ }
+
+ private static int maxDiffCategory(int category) {
+ if (category == 0 || category == 1) return 1;
+ else if (category == 2) return 10;
+ return 0;
+ }
+
+ /*
+ * 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.
+ *
+ * For example:
+ * maxLengthSequence("1234") == 4
+ * maxLengthSequence("1234abc") == 4
+ * maxLengthSequence("aabc") == 3
+ * maxLengthSequence("qwertyuio") == 1
+ * maxLengthSequence("@ABC") == 3
+ * maxLengthSequence(";;;;") == 4 (anything that repeats)
+ * maxLengthSequence(":;<=>") == 1 (ordered, but not composed of alphas or digits)
+ *
+ * @param string the pass
+ * @return the number of sequential letters or digits
+ */
+ public static int maxLengthSequence(String string) {
+ if (string.length() == 0) return 0;
+ char previousChar = string.charAt(0);
+ int category = categoryChar(previousChar); //current category of the sequence
+ int diff = 0; //difference between two consecutive characters
+ boolean hasDiff = false; //if we are currently targeting a sequence
+ int maxLength = 0; //maximum length of a sequence already found
+ int startSequence = 0; //where the current sequence started
+ for (int current = 1; current < string.length(); current++) {
+ char currentChar = string.charAt(current);
+ int categoryCurrent = categoryChar(currentChar);
+ int currentDiff = (int) currentChar - (int) previousChar;
+ if (categoryCurrent != category || Math.abs(currentDiff) > maxDiffCategory(category)) {
+ maxLength = Math.max(maxLength, current - startSequence);
+ startSequence = current;
+ hasDiff = false;
+ category = categoryCurrent;
+ }
+ else {
+ if(hasDiff && currentDiff != diff) {
+ maxLength = Math.max(maxLength, current - startSequence);
+ startSequence = current - 1;
+ }
+ diff = currentDiff;
+ hasDiff = true;
+ }
+ previousChar = currentChar;
+ }
+ maxLength = Math.max(maxLength, string.length() - startSequence);
+ return maxLength;
+ }
+
/** Update the encryption password if it is enabled **/
private void updateEncryptionPassword(int type, String password) {
DevicePolicyManager dpm = getDevicePolicyManager();
@@ -926,10 +998,12 @@ public class LockPatternUtils {
long backupMode = getLong(PASSWORD_TYPE_ALTERNATE_KEY, 0);
final boolean passwordEnabled = mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
+ || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
|| mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
final boolean backupEnabled = backupMode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
|| backupMode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
+ || backupMode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
|| backupMode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
|| backupMode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
@@ -1307,6 +1381,7 @@ public class LockPatternUtils {
long mode = getKeyguardStoredPasswordQuality();
final boolean isPattern = mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
final boolean isPassword = mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
+ || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
|| mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
index 5ef41c9..3166ad4 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -87,6 +87,7 @@ public class KeyguardSecurityModel {
final int security = mLockPatternUtils.getKeyguardStoredPasswordQuality();
switch (security) {
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
mode = mLockPatternUtils.isLockPasswordEnabled() ?
SecurityMode.PIN : SecurityMode.None;
break;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e956dfb..61f09f6 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1190,6 +1190,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
case DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK:
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: