Fix 2677197: Adding minimum complex character support.

Change-Id: I520bc5f9aa924bf9b5585b2235a91cc96cb99c25
This commit is contained in:
Konstantin Lopyrev
2010-05-24 17:10:56 -07:00
parent afd52a0b40
commit a15dcfaf2b
7 changed files with 846 additions and 30 deletions

View File

@@ -204,6 +204,14 @@ public class DevicePolicyManager {
*/
public static final int PASSWORD_QUALITY_ALPHANUMERIC = 0x50000;
/**
* Constant for {@link #setPasswordQuality}: the user must have entered a
* password containing numeric <em>and</em> alphabetic characters,
* <em>and</em> special symbols. Note that quality constants are ordered so
* that higher values are more restrictive.
*/
public static final int PASSWORD_QUALITY_COMPLEX = 0x60000;
/**
* Called by an application that is administering the device to set the
* password restrictions it is imposing. After setting this, the user
@@ -226,7 +234,7 @@ public class DevicePolicyManager {
* @param quality The new desired quality. One of
* {@link #PASSWORD_QUALITY_UNSPECIFIED}, {@link #PASSWORD_QUALITY_SOMETHING},
* {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_ALPHABETIC},
* or {@link #PASSWORD_QUALITY_ALPHANUMERIC}.
* {@link #PASSWORD_QUALITY_ALPHANUMERIC} or {@link #PASSWORD_QUALITY_COMPLEX}.
*/
public void setPasswordQuality(ComponentName admin, int quality) {
if (mService != null) {
@@ -264,8 +272,8 @@ 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},
* or {@link #PASSWORD_QUALITY_ALPHANUMERIC}
* {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_ALPHABETIC}
* {@link #PASSWORD_QUALITY_ALPHANUMERIC}, or {@link #PASSWORD_QUALITY_COMPLEX}
* with {@link #setPasswordQuality}.
*
* <p>The calling device admin must have requested
@@ -303,6 +311,255 @@ public class DevicePolicyManager {
return 0;
}
/**
* Called by an application that is administering the device to set the
* minimum number of upper case letters required in the password. After
* setting this, the user will not be able to enter a new password that is
* not at least as restrictive as what has been set. Note that the current
* password will remain until the user has set a new one, so 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
* {@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
* this method; if it has not, a security exception will be thrown.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated
* with.
* @param length The new desired minimum number of upper case letters
* required in the password. A value of 0 means there is no
* restriction.
*/
public void setPasswordMinimumUpperCase(ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumUpperCase(admin, length);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
/**
* Retrieve the current number of upper case letters required in the
* password for all admins or a particular one.
*
* @param admin The name of the admin component to check, or null to
* aggregate all admins.
* @return The minimum number of upper case letters required in the
* password.
*/
public int getPasswordMinimumUpperCase(ComponentName admin) {
if (mService != null) {
try {
return mService.getPasswordMinimumUpperCase(admin);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
return 0;
}
/**
* Called by an application that is administering the device to set the
* minimum number of lower case letters required in the password. After
* setting this, the user will not be able to enter a new password that is
* not at least as restrictive as what has been set. Note that the current
* password will remain until the user has set a new one, so 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
* {@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
* this method; if it has not, a security exception will be thrown.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated
* with.
* @param length The new desired minimum number of lower case letters
* required in the password. A value of 0 means there is no
* restriction.
*/
public void setPasswordMinimumLowerCase(ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumLowerCase(admin, length);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
/**
* Retrieve the current number of lower case letters required in the
* password for all admins or a particular one.
*
* @param admin The name of the admin component to check, or null to
* aggregate all admins.
* @return The minimum number of lower case letters required in the
* password.
*/
public int getPasswordMinimumLowerCase(ComponentName admin) {
if (mService != null) {
try {
return mService.getPasswordMinimumLowerCase(admin);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
return 0;
}
/**
* Called by an application that is administering the device to set the
* minimum number of letters required in the password. After setting this,
* the user will not be able to enter a new password that is not at least as
* restrictive as what has been set. Note that the current password will
* remain until the user has set a new one, so 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
* {@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
* this method; if it has not, a security exception will be thrown.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated
* with.
* @param length The new desired minimum number of letters required in the
* password. A value of 0 means there is no restriction.
*/
public void setPasswordMinimumLetters(ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumLetters(admin, length);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
/**
* Retrieve the current number of letters required in the password for all
* admins or a particular one.
*
* @param admin The name of the admin component to check, or null to
* aggregate all admins.
* @return The minimum number of letters required in the password.
*/
public int getPasswordMinimumLetters(ComponentName admin) {
if (mService != null) {
try {
return mService.getPasswordMinimumLetters(admin);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
return 0;
}
/**
* Called by an application that is administering the device to set the
* minimum number of numerical digits required in the password. After
* setting this, the user will not be able to enter a new password that is
* not at least as restrictive as what has been set. Note that the current
* password will remain until the user has set a new one, so 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
* {@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
* this method; if it has not, a security exception will be thrown.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated
* with.
* @param length The new desired minimum number of numerical digits required
* in the password. A value of 0 means there is no restriction.
*/
public void setPasswordMinimumNumeric(ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumNumeric(admin, length);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
/**
* Retrieve the current number of numerical digits required in the password
* for all admins or a particular one.
*
* @param admin The name of the admin component to check, or null to
* aggregate all admins.
* @return The minimum number of numerical digits required in the password.
*/
public int getPasswordMinimumNumeric(ComponentName admin) {
if (mService != null) {
try {
return mService.getPasswordMinimumNumeric(admin);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
return 0;
}
/**
* Called by an application that is administering the device to set the
* minimum number of symbols required in the password. After setting this,
* the user will not be able to enter a new password that is not at least as
* restrictive as what has been set. Note that the current password will
* remain until the user has set a new one, so 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
* {@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
* this method; if it has not, a security exception will be thrown.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated
* with.
* @param length The new desired minimum number of symbols required in the
* password. A value of 0 means there is no restriction.
*/
public void setPasswordMinimumSymbols(ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumSymbols(admin, length);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
}
/**
* Retrieve the current number of symbols required in the password for all
* admins or a particular one.
*
* @param admin The name of the admin component to check, or null to
* aggregate all admins.
* @return The minimum number of symbols required in the password.
*/
public int getPasswordMinimumSymbols(ComponentName admin) {
if (mService != null) {
try {
return mService.getPasswordMinimumSymbols(admin);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
return 0;
}
/**
* Called by an application that is administering the device to set the length
* of the password history. After setting this, the user will not be able to
@@ -627,10 +884,12 @@ public class DevicePolicyManager {
/**
* @hide
*/
public void setActivePasswordState(int quality, int length) {
public void setActivePasswordState(int quality, int length, int letters, int uppercase,
int lowercase, int numbers, int symbols) {
if (mService != null) {
try {
mService.setActivePasswordState(quality, length);
mService.setActivePasswordState(quality, length, letters, uppercase, lowercase,
numbers, symbols);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}

View File

@@ -27,9 +27,24 @@ import android.os.RemoteCallback;
interface IDevicePolicyManager {
void setPasswordQuality(in ComponentName who, int quality);
int getPasswordQuality(in ComponentName who);
void setPasswordMinimumLength(in ComponentName who, int length);
int getPasswordMinimumLength(in ComponentName who);
void setPasswordMinimumUpperCase(in ComponentName who, int length);
int getPasswordMinimumUpperCase(in ComponentName who);
void setPasswordMinimumLowerCase(in ComponentName who, int length);
int getPasswordMinimumLowerCase(in ComponentName who);
void setPasswordMinimumLetters(in ComponentName who, int length);
int getPasswordMinimumLetters(in ComponentName who);
void setPasswordMinimumNumeric(in ComponentName who, int length);
int getPasswordMinimumNumeric(in ComponentName who);
void setPasswordMinimumSymbols(in ComponentName who, int length);
int getPasswordMinimumSymbols(in ComponentName who);
void setPasswordHistoryLength(in ComponentName who, int length);
int getPasswordHistoryLength(in ComponentName who);
@@ -56,7 +71,7 @@ interface IDevicePolicyManager {
void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result);
void removeActiveAdmin(in ComponentName policyReceiver);
void setActivePasswordState(int quality, int length);
void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase, int numbers, int symbols);
void reportFailedPasswordAttempt();
void reportSuccessfulPasswordAttempt();
}

View File

@@ -144,6 +144,26 @@ public class LockPatternUtils {
return getDevicePolicyManager().getPasswordHistoryLength(null);
}
public int getRequestedPasswordMinimumLetters() {
return getDevicePolicyManager().getPasswordMinimumLetters(null);
}
public int getRequestedPasswordMinimumUpperCase() {
return getDevicePolicyManager().getPasswordMinimumUpperCase(null);
}
public int getRequestedPasswordMinimumLowerCase() {
return getDevicePolicyManager().getPasswordMinimumLowerCase(null);
}
public int getRequestedPasswordMinimumNumeric() {
return getDevicePolicyManager().getPasswordMinimumNumeric(null);
}
public int getRequestedPasswordMinimumSymbols() {
return getDevicePolicyManager().getPasswordMinimumSymbols(null);
}
/**
* Returns the actual password mode, as set by keyguard after updating the password.
*
@@ -308,6 +328,11 @@ public class LockPatternUtils {
activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
}
break;
case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
if (isLockPasswordEnabled()) {
activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
}
break;
}
return activePasswordQuality;
}
@@ -316,8 +341,6 @@ public class LockPatternUtils {
* Clear any lock pattern or password.
*/
public void clearLock() {
getDevicePolicyManager().setActivePasswordState(
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0);
saveLockPassword(null, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
setLockPatternEnabled(false);
saveLockPattern(null);
@@ -330,7 +353,7 @@ public class LockPatternUtils {
*/
public void saveLockPattern(List<LockPatternView.Cell> pattern) {
// Compute the hash
final byte[] hash = LockPatternUtils.patternToHash(pattern);
final byte[] hash = LockPatternUtils.patternToHash(pattern);
try {
// Write the hash to file
RandomAccessFile raf = new RandomAccessFile(sLockPatternFilename, "rw");
@@ -345,14 +368,15 @@ public class LockPatternUtils {
if (pattern != null) {
setBoolean(PATTERN_EVER_CHOSEN_KEY, true);
setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
dpm.setActivePasswordState(
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, pattern.size());
dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, pattern
.size(), 0, 0, 0, 0, 0);
} else {
dpm.setActivePasswordState(
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0);
dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0,
0, 0, 0, 0);
}
} catch (FileNotFoundException fnfe) {
// Cant do much, unless we want to fail over to using the settings provider
// Cant do much, unless we want to fail over to using the settings
// provider
Log.e(TAG, "Unable to save lock pattern to " + sLockPatternFilename);
} catch (IOException ioe) {
// Cant do much
@@ -410,13 +434,33 @@ public class LockPatternUtils {
DevicePolicyManager dpm = getDevicePolicyManager();
if (password != null) {
int computedQuality = computePasswordQuality(password);
setLong(PASSWORD_TYPE_KEY, computedQuality);
setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality));
if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
dpm.setActivePasswordState(computedQuality, password.length());
int letters = 0;
int uppercase = 0;
int lowercase = 0;
int numbers = 0;
int symbols = 0;
for (int i = 0; i < password.length(); i++) {
char c = password.charAt(i);
if (c >= 'A' && c <= 'Z') {
letters++;
uppercase++;
} else if (c >= 'a' && c <= 'z') {
letters++;
lowercase++;
} else if (c >= '0' && c <= '9') {
numbers++;
} else {
symbols++;
}
}
dpm.setActivePasswordState(Math.max(quality, computedQuality), password
.length(), letters, uppercase, lowercase, numbers, symbols);
} else {
// The password is not anything.
dpm.setActivePasswordState(
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0);
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0);
}
// Add the password to the password history. We assume all
// password
@@ -439,7 +483,7 @@ public class LockPatternUtils {
setString(PASSWORD_HISTORY_KEY, passwordHistory);
} else {
dpm.setActivePasswordState(
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0);
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0);
}
} catch (FileNotFoundException fnfe) {
// Cant do much, unless we want to fail over to using the settings provider
@@ -579,7 +623,8 @@ public class LockPatternUtils {
return savedPasswordExists() &&
(mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC);
|| mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX);
}
/**
@@ -716,7 +761,8 @@ public class LockPatternUtils {
final boolean isPattern = mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
final boolean isPassword = mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
|| mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
final boolean secure = isPattern && isLockPatternEnabled() && savedPatternExists()
|| isPassword && savedPasswordExists();
return secure;