Merge "Add encryption to SecurityPolicy" into honeycomb
This commit is contained in:
commit
4f721a1625
@ -22,5 +22,6 @@
|
|||||||
<force-lock />
|
<force-lock />
|
||||||
<wipe-data />
|
<wipe-data />
|
||||||
<expire-password />
|
<expire-password />
|
||||||
|
<encrypted-storage />
|
||||||
</uses-policies>
|
</uses-policies>
|
||||||
</device-admin>
|
</device-admin>
|
||||||
|
@ -48,7 +48,7 @@ public class SecurityPolicy {
|
|||||||
private PolicySet mAggregatePolicy;
|
private PolicySet mAggregatePolicy;
|
||||||
|
|
||||||
/* package */ static final PolicySet NO_POLICY_SET =
|
/* package */ static final PolicySet NO_POLICY_SET =
|
||||||
new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, false, 0, 0, 0);
|
new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, false, 0, 0, 0, false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This projection on Account is for scanning/reading
|
* This projection on Account is for scanning/reading
|
||||||
@ -104,6 +104,7 @@ public class SecurityPolicy {
|
|||||||
* password history take the max (strongest mode)
|
* password history take the max (strongest mode)
|
||||||
* password expiration take the min (strongest mode)
|
* password expiration take the min (strongest mode)
|
||||||
* password complex chars take the max (strongest mode)
|
* password complex chars take the max (strongest mode)
|
||||||
|
* encryption take the max (logical or)
|
||||||
*
|
*
|
||||||
* @return a policy representing the strongest aggregate. If no policy sets are defined,
|
* @return a policy representing the strongest aggregate. If no policy sets are defined,
|
||||||
* a lightweight "nothing required" policy will be returned. Never null.
|
* a lightweight "nothing required" policy will be returned. Never null.
|
||||||
@ -119,6 +120,7 @@ public class SecurityPolicy {
|
|||||||
int passwordHistory = Integer.MIN_VALUE;
|
int passwordHistory = Integer.MIN_VALUE;
|
||||||
int passwordExpirationDays = Integer.MAX_VALUE;
|
int passwordExpirationDays = Integer.MAX_VALUE;
|
||||||
int passwordComplexChars = Integer.MIN_VALUE;
|
int passwordComplexChars = Integer.MIN_VALUE;
|
||||||
|
boolean requireEncryption = false;
|
||||||
|
|
||||||
Cursor c = mContext.getContentResolver().query(Account.CONTENT_URI,
|
Cursor c = mContext.getContentResolver().query(Account.CONTENT_URI,
|
||||||
ACCOUNT_SECURITY_PROJECTION, Account.SECURITY_NONZERO_SELECTION, null, null);
|
ACCOUNT_SECURITY_PROJECTION, Account.SECURITY_NONZERO_SELECTION, null, null);
|
||||||
@ -147,6 +149,7 @@ public class SecurityPolicy {
|
|||||||
passwordComplexChars);
|
passwordComplexChars);
|
||||||
}
|
}
|
||||||
requireRemoteWipe |= p.mRequireRemoteWipe;
|
requireRemoteWipe |= p.mRequireRemoteWipe;
|
||||||
|
requireEncryption |= p.mRequireEncryption;
|
||||||
policiesFound = true;
|
policiesFound = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,7 +168,7 @@ public class SecurityPolicy {
|
|||||||
|
|
||||||
return new PolicySet(minPasswordLength, passwordMode, maxPasswordFails,
|
return new PolicySet(minPasswordLength, passwordMode, maxPasswordFails,
|
||||||
maxScreenLockTime, requireRemoteWipe, passwordExpirationDays, passwordHistory,
|
maxScreenLockTime, requireRemoteWipe, passwordExpirationDays, passwordHistory,
|
||||||
passwordComplexChars);
|
passwordComplexChars, requireEncryption);
|
||||||
} else {
|
} else {
|
||||||
return NO_POLICY_SET;
|
return NO_POLICY_SET;
|
||||||
}
|
}
|
||||||
@ -210,6 +213,57 @@ public class SecurityPolicy {
|
|||||||
setActivePolicies();
|
setActivePolicies();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API: Query if the proposed set of policies are supported on the device.
|
||||||
|
*
|
||||||
|
* @param policies requested
|
||||||
|
* @return boolean if supported
|
||||||
|
*/
|
||||||
|
public boolean isSupported(PolicySet policies) {
|
||||||
|
// IMPLEMENTATION: At this time, the only policy which might not be supported is
|
||||||
|
// encryption (which requires low-level systems support). Other policies are fully
|
||||||
|
// supported by the framework and do not need to be checked.
|
||||||
|
if (policies.mRequireEncryption) {
|
||||||
|
int encryptionStatus = getDPM().getStorageEncryption(null);
|
||||||
|
if (encryptionStatus == DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API: Query used to determine if a given policy is "active" (the device is operating at
|
||||||
|
* the required security level).
|
||||||
|
*
|
||||||
|
* @param policies the policies requested, or null to check aggregate stored policies
|
||||||
|
* @return true if the requested policies are active, false if not.
|
||||||
|
*/
|
||||||
|
public boolean isActive(PolicySet policies) {
|
||||||
|
int reasons = getInactiveReasons(policies);
|
||||||
|
return reasons == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return bits from isActive: Device Policy Manager has not been activated
|
||||||
|
*/
|
||||||
|
public final static int INACTIVE_NEED_ACTIVATION = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return bits from isActive: Some required configuration is not correct (no user action).
|
||||||
|
*/
|
||||||
|
public final static int INACTIVE_NEED_CONFIGURATION = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return bits from isActive: Password needs to be set or updated
|
||||||
|
*/
|
||||||
|
public final static int INACTIVE_NEED_PASSWORD = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return bits from isActive: Encryption has not be enabled
|
||||||
|
*/
|
||||||
|
public final static int INACTIVE_NEED_ENCRYPTION = 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API: Query used to determine if a given policy is "active" (the device is operating at
|
* API: Query used to determine if a given policy is "active" (the device is operating at
|
||||||
* the required security level).
|
* the required security level).
|
||||||
@ -227,37 +281,39 @@ public class SecurityPolicy {
|
|||||||
* based on the requirements of the account with the shortest interval.
|
* based on the requirements of the account with the shortest interval.
|
||||||
*
|
*
|
||||||
* @param policies the policies requested, or null to check aggregate stored policies
|
* @param policies the policies requested, or null to check aggregate stored policies
|
||||||
* @return true if the policies are active, false if not active
|
* @return zero if the requested policies are active, non-zero bits indicates that more work
|
||||||
|
* is needed (typically, by the user) before the required security polices are fully active.
|
||||||
*/
|
*/
|
||||||
public boolean isActive(PolicySet policies) {
|
public int getInactiveReasons(PolicySet policies) {
|
||||||
// select aggregate set if needed
|
// select aggregate set if needed
|
||||||
if (policies == null) {
|
if (policies == null) {
|
||||||
policies = getAggregatePolicy();
|
policies = getAggregatePolicy();
|
||||||
}
|
}
|
||||||
// quick check for the "empty set" of no policies
|
// quick check for the "empty set" of no policies
|
||||||
if (policies == NO_POLICY_SET) {
|
if (policies == NO_POLICY_SET) {
|
||||||
return true;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int reasons = 0;
|
||||||
DevicePolicyManager dpm = getDPM();
|
DevicePolicyManager dpm = getDPM();
|
||||||
if (isActiveAdmin()) {
|
if (isActiveAdmin()) {
|
||||||
// check each policy explicitly
|
// check each policy explicitly
|
||||||
if (policies.mMinPasswordLength > 0) {
|
if (policies.mMinPasswordLength > 0) {
|
||||||
if (dpm.getPasswordMinimumLength(mAdminName) < policies.mMinPasswordLength) {
|
if (dpm.getPasswordMinimumLength(mAdminName) < policies.mMinPasswordLength) {
|
||||||
return false;
|
reasons |= INACTIVE_NEED_PASSWORD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (policies.mPasswordMode > 0) {
|
if (policies.mPasswordMode > 0) {
|
||||||
if (dpm.getPasswordQuality(mAdminName) < policies.getDPManagerPasswordQuality()) {
|
if (dpm.getPasswordQuality(mAdminName) < policies.getDPManagerPasswordQuality()) {
|
||||||
return false;
|
reasons |= INACTIVE_NEED_PASSWORD;
|
||||||
}
|
}
|
||||||
if (!dpm.isActivePasswordSufficient()) {
|
if (!dpm.isActivePasswordSufficient()) {
|
||||||
return false;
|
reasons |= INACTIVE_NEED_PASSWORD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (policies.mMaxScreenLockTime > 0) {
|
if (policies.mMaxScreenLockTime > 0) {
|
||||||
// Note, we use seconds, dpm uses milliseconds
|
// Note, we use seconds, dpm uses milliseconds
|
||||||
if (dpm.getMaximumTimeToLock(mAdminName) > policies.mMaxScreenLockTime * 1000) {
|
if (dpm.getMaximumTimeToLock(mAdminName) > policies.mMaxScreenLockTime * 1000) {
|
||||||
return false;
|
reasons |= INACTIVE_NEED_CONFIGURATION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (policies.mPasswordExpirationDays > 0) {
|
if (policies.mPasswordExpirationDays > 0) {
|
||||||
@ -265,34 +321,40 @@ public class SecurityPolicy {
|
|||||||
long currentTimeout = dpm.getPasswordExpirationTimeout(mAdminName);
|
long currentTimeout = dpm.getPasswordExpirationTimeout(mAdminName);
|
||||||
if (currentTimeout == 0
|
if (currentTimeout == 0
|
||||||
|| currentTimeout > policies.getDPManagerPasswordExpirationTimeout()) {
|
|| currentTimeout > policies.getDPManagerPasswordExpirationTimeout()) {
|
||||||
return false;
|
reasons |= INACTIVE_NEED_PASSWORD;
|
||||||
}
|
}
|
||||||
// confirm that the current password hasn't expired
|
// confirm that the current password hasn't expired
|
||||||
long expirationDate = dpm.getPasswordExpiration(mAdminName);
|
long expirationDate = dpm.getPasswordExpiration(mAdminName);
|
||||||
long timeUntilExpiration = expirationDate - System.currentTimeMillis();
|
long timeUntilExpiration = expirationDate - System.currentTimeMillis();
|
||||||
boolean expired = timeUntilExpiration < 0;
|
boolean expired = timeUntilExpiration < 0;
|
||||||
if (expired) {
|
if (expired) {
|
||||||
return false;
|
reasons |= INACTIVE_NEED_PASSWORD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (policies.mPasswordHistory > 0) {
|
if (policies.mPasswordHistory > 0) {
|
||||||
if (dpm.getPasswordHistoryLength(mAdminName) < policies.mPasswordHistory) {
|
if (dpm.getPasswordHistoryLength(mAdminName) < policies.mPasswordHistory) {
|
||||||
return false;
|
reasons |= INACTIVE_NEED_PASSWORD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (policies.mPasswordComplexChars > 0) {
|
if (policies.mPasswordComplexChars > 0) {
|
||||||
if (dpm.getPasswordMinimumNonLetter(mAdminName) < policies.mPasswordComplexChars) {
|
if (dpm.getPasswordMinimumNonLetter(mAdminName) < policies.mPasswordComplexChars) {
|
||||||
return false;
|
reasons |= INACTIVE_NEED_PASSWORD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (policies.mRequireEncryption) {
|
||||||
|
int encryptionStatus = getDPM().getStorageEncryption(null);
|
||||||
|
if (encryptionStatus != DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE) {
|
||||||
|
reasons |= INACTIVE_NEED_ENCRYPTION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// password failures are counted locally - no test required here
|
// password failures are counted locally - no test required here
|
||||||
// no check required for remote wipe (it's supported, if we're the admin)
|
// no check required for remote wipe (it's supported, if we're the admin)
|
||||||
|
|
||||||
// making it this far means we passed!
|
// If we made it all the way, reasons == 0 here. Otherwise it's a list of grievances.
|
||||||
return true;
|
return reasons;
|
||||||
}
|
}
|
||||||
// return false, not active
|
// return false, not active
|
||||||
return false;
|
return INACTIVE_NEED_ACTIVATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -323,6 +385,8 @@ public class SecurityPolicy {
|
|||||||
dpm.setPasswordHistoryLength(mAdminName, policies.mPasswordHistory);
|
dpm.setPasswordHistoryLength(mAdminName, policies.mPasswordHistory);
|
||||||
// password minimum complex characters
|
// password minimum complex characters
|
||||||
dpm.setPasswordMinimumNonLetter(mAdminName, policies.mPasswordComplexChars);
|
dpm.setPasswordMinimumNonLetter(mAdminName, policies.mPasswordComplexChars);
|
||||||
|
// encryption required
|
||||||
|
dpm.setStorageEncryption(mAdminName, policies.mRequireEncryption);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,14 +486,16 @@ public class SecurityPolicy {
|
|||||||
private static final int PASSWORD_EXPIRATION_SHIFT = 26;
|
private static final int PASSWORD_EXPIRATION_SHIFT = 26;
|
||||||
private static final long PASSWORD_EXPIRATION_MASK = 1023L << PASSWORD_EXPIRATION_SHIFT;
|
private static final long PASSWORD_EXPIRATION_MASK = 1023L << PASSWORD_EXPIRATION_SHIFT;
|
||||||
public static final int PASSWORD_EXPIRATION_MAX = 1023;
|
public static final int PASSWORD_EXPIRATION_MAX = 1023;
|
||||||
// bit 35..42: password history (length; 0=not required)
|
// bit 36..43: password history (length; 0=not required)
|
||||||
private static final int PASSWORD_HISTORY_SHIFT = 36;
|
private static final int PASSWORD_HISTORY_SHIFT = 36;
|
||||||
private static final long PASSWORD_HISTORY_MASK = 255L << PASSWORD_HISTORY_SHIFT;
|
private static final long PASSWORD_HISTORY_MASK = 255L << PASSWORD_HISTORY_SHIFT;
|
||||||
public static final int PASSWORD_HISTORY_MAX = 255;
|
public static final int PASSWORD_HISTORY_MAX = 255;
|
||||||
// bit 42..46: min complex characters (0=not required)
|
// bit 44..48: min complex characters (0=not required)
|
||||||
private static final int PASSWORD_COMPLEX_CHARS_SHIFT = 44;
|
private static final int PASSWORD_COMPLEX_CHARS_SHIFT = 44;
|
||||||
private static final long PASSWORD_COMPLEX_CHARS_MASK = 31L << PASSWORD_COMPLEX_CHARS_SHIFT;
|
private static final long PASSWORD_COMPLEX_CHARS_MASK = 31L << PASSWORD_COMPLEX_CHARS_SHIFT;
|
||||||
public static final int PASSWORD_COMPLEX_CHARS_MAX = 31;
|
public static final int PASSWORD_COMPLEX_CHARS_MAX = 31;
|
||||||
|
// bit 49: requires device encryption
|
||||||
|
private static final long REQUIRE_ENCRYPTION = 1L << 49;
|
||||||
|
|
||||||
/* Convert days to mSec (used for password expiration) */
|
/* Convert days to mSec (used for password expiration) */
|
||||||
private static final long DAYS_TO_MSEC = 24 * 60 * 60 * 1000;
|
private static final long DAYS_TO_MSEC = 24 * 60 * 60 * 1000;
|
||||||
@ -444,6 +510,7 @@ public class SecurityPolicy {
|
|||||||
/*package*/ final int mPasswordExpirationDays;
|
/*package*/ final int mPasswordExpirationDays;
|
||||||
/*package*/ final int mPasswordHistory;
|
/*package*/ final int mPasswordHistory;
|
||||||
/*package*/ final int mPasswordComplexChars;
|
/*package*/ final int mPasswordComplexChars;
|
||||||
|
/*package*/ final boolean mRequireEncryption;
|
||||||
|
|
||||||
public int getMinPasswordLengthForTest() {
|
public int getMinPasswordLengthForTest() {
|
||||||
return mMinPasswordLength;
|
return mMinPasswordLength;
|
||||||
@ -465,6 +532,10 @@ public class SecurityPolicy {
|
|||||||
return mRequireRemoteWipe;
|
return mRequireRemoteWipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRequireEncryptionForTest() {
|
||||||
|
return mRequireEncryption;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create from raw values.
|
* Create from raw values.
|
||||||
* @param minPasswordLength (0=not enforced)
|
* @param minPasswordLength (0=not enforced)
|
||||||
@ -479,7 +550,8 @@ public class SecurityPolicy {
|
|||||||
*/
|
*/
|
||||||
public PolicySet(int minPasswordLength, int passwordMode, int maxPasswordFails,
|
public PolicySet(int minPasswordLength, int passwordMode, int maxPasswordFails,
|
||||||
int maxScreenLockTime, boolean requireRemoteWipe, int passwordExpirationDays,
|
int maxScreenLockTime, boolean requireRemoteWipe, int passwordExpirationDays,
|
||||||
int passwordHistory, int passwordComplexChars) throws IllegalArgumentException {
|
int passwordHistory, int passwordComplexChars, boolean requireEncryption)
|
||||||
|
throws IllegalArgumentException {
|
||||||
// If we're not enforcing passwords, make sure we clean up related values, since EAS
|
// If we're not enforcing passwords, make sure we clean up related values, since EAS
|
||||||
// can send non-zero values for any or all of these
|
// can send non-zero values for any or all of these
|
||||||
if (passwordMode == PASSWORD_MODE_NONE) {
|
if (passwordMode == PASSWORD_MODE_NONE) {
|
||||||
@ -529,6 +601,7 @@ public class SecurityPolicy {
|
|||||||
mPasswordExpirationDays = passwordExpirationDays;
|
mPasswordExpirationDays = passwordExpirationDays;
|
||||||
mPasswordHistory = passwordHistory;
|
mPasswordHistory = passwordHistory;
|
||||||
mPasswordComplexChars = passwordComplexChars;
|
mPasswordComplexChars = passwordComplexChars;
|
||||||
|
mRequireEncryption = requireEncryption;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -558,6 +631,7 @@ public class SecurityPolicy {
|
|||||||
(int) ((flags & PASSWORD_HISTORY_MASK) >> PASSWORD_HISTORY_SHIFT);
|
(int) ((flags & PASSWORD_HISTORY_MASK) >> PASSWORD_HISTORY_SHIFT);
|
||||||
mPasswordComplexChars =
|
mPasswordComplexChars =
|
||||||
(int) ((flags & PASSWORD_COMPLEX_CHARS_MASK) >> PASSWORD_COMPLEX_CHARS_SHIFT);
|
(int) ((flags & PASSWORD_COMPLEX_CHARS_MASK) >> PASSWORD_COMPLEX_CHARS_SHIFT);
|
||||||
|
mRequireEncryption = 0 != (flags & REQUIRE_ENCRYPTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -661,6 +735,7 @@ public class SecurityPolicy {
|
|||||||
dest.writeInt(mPasswordExpirationDays);
|
dest.writeInt(mPasswordExpirationDays);
|
||||||
dest.writeInt(mPasswordHistory);
|
dest.writeInt(mPasswordHistory);
|
||||||
dest.writeInt(mPasswordComplexChars);
|
dest.writeInt(mPasswordComplexChars);
|
||||||
|
dest.writeInt(mRequireEncryption ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -675,6 +750,7 @@ public class SecurityPolicy {
|
|||||||
mPasswordExpirationDays = in.readInt();
|
mPasswordExpirationDays = in.readInt();
|
||||||
mPasswordHistory = in.readInt();
|
mPasswordHistory = in.readInt();
|
||||||
mPasswordComplexChars = in.readInt();
|
mPasswordComplexChars = in.readInt();
|
||||||
|
mRequireEncryption = in.readInt() == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -689,12 +765,11 @@ public class SecurityPolicy {
|
|||||||
flags |= mPasswordMode;
|
flags |= mPasswordMode;
|
||||||
flags |= (long)mMaxPasswordFails << PASSWORD_MAX_FAILS_SHIFT;
|
flags |= (long)mMaxPasswordFails << PASSWORD_MAX_FAILS_SHIFT;
|
||||||
flags |= (long)mMaxScreenLockTime << SCREEN_LOCK_TIME_SHIFT;
|
flags |= (long)mMaxScreenLockTime << SCREEN_LOCK_TIME_SHIFT;
|
||||||
if (mRequireRemoteWipe) {
|
if (mRequireRemoteWipe) flags |= REQUIRE_REMOTE_WIPE;
|
||||||
flags |= REQUIRE_REMOTE_WIPE;
|
|
||||||
}
|
|
||||||
flags |= (long)mPasswordHistory << PASSWORD_HISTORY_SHIFT;
|
flags |= (long)mPasswordHistory << PASSWORD_HISTORY_SHIFT;
|
||||||
flags |= (long)mPasswordExpirationDays << PASSWORD_EXPIRATION_SHIFT;
|
flags |= (long)mPasswordExpirationDays << PASSWORD_EXPIRATION_SHIFT;
|
||||||
flags |= (long)mPasswordComplexChars << PASSWORD_COMPLEX_CHARS_SHIFT;
|
flags |= (long)mPasswordComplexChars << PASSWORD_COMPLEX_CHARS_SHIFT;
|
||||||
|
if (mRequireEncryption) flags |= REQUIRE_ENCRYPTION;
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -705,7 +780,8 @@ public class SecurityPolicy {
|
|||||||
+ mMaxScreenLockTime + " remote-wipe-req=" + mRequireRemoteWipe
|
+ mMaxScreenLockTime + " remote-wipe-req=" + mRequireRemoteWipe
|
||||||
+ " pw-expiration=" + mPasswordExpirationDays
|
+ " pw-expiration=" + mPasswordExpirationDays
|
||||||
+ " pw-history=" + mPasswordHistory
|
+ " pw-history=" + mPasswordHistory
|
||||||
+ " pw-complex-chars=" + mPasswordComplexChars + "}";
|
+ " pw-complex-chars=" + mPasswordComplexChars
|
||||||
|
+ " require-encryption=" + mRequireEncryption + "}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,12 +37,15 @@ import android.os.Bundle;
|
|||||||
* 3. When we are actively administrating, check current policies and see if they're sufficient
|
* 3. When we are actively administrating, check current policies and see if they're sufficient
|
||||||
* 4. If not, set policies
|
* 4. If not, set policies
|
||||||
* 5. If necessary, request for user to update device password
|
* 5. If necessary, request for user to update device password
|
||||||
|
* 6. If necessary, request for user to activate device encryption
|
||||||
*/
|
*/
|
||||||
public class AccountSecurity extends Activity {
|
public class AccountSecurity extends Activity {
|
||||||
|
|
||||||
private static final String EXTRA_ACCOUNT_ID = "com.android.email.activity.setup.ACCOUNT_ID";
|
private static final String EXTRA_ACCOUNT_ID = "com.android.email.activity.setup.ACCOUNT_ID";
|
||||||
|
|
||||||
private static final int REQUEST_ENABLE = 1;
|
private static final int REQUEST_ENABLE = 1;
|
||||||
|
private static final int REQUEST_PASSWORD = 2;
|
||||||
|
private static final int REQUEST_ENCRYPTION = 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for generating intent for this activity (which is intended to be launched
|
* Used for generating intent for this activity (which is intended to be launched
|
||||||
@ -91,7 +94,11 @@ public class AccountSecurity extends Activity {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// already active - try to set actual policies, finish, and return
|
// already active - try to set actual policies, finish, and return
|
||||||
setActivePolicies();
|
boolean startedActivity = setActivePolicies();
|
||||||
|
if (startedActivity) {
|
||||||
|
// keep this activity on stack to process result
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,11 +111,17 @@ public class AccountSecurity extends Activity {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
boolean startedActivity = false;
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
|
case REQUEST_PASSWORD:
|
||||||
|
case REQUEST_ENCRYPTION:
|
||||||
|
// Force the result code and just check the DPM to check for actual success
|
||||||
|
resultCode = Activity.RESULT_OK;
|
||||||
|
//$FALL-THROUGH$
|
||||||
case REQUEST_ENABLE:
|
case REQUEST_ENABLE:
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
// now active - try to set actual policies
|
// now active - try to set actual policies
|
||||||
setActivePolicies();
|
startedActivity = setActivePolicies();
|
||||||
} else {
|
} else {
|
||||||
// failed - repost notification, and exit
|
// failed - repost notification, and exit
|
||||||
final long accountId = getIntent().getLongExtra(EXTRA_ACCOUNT_ID, -1);
|
final long accountId = getIntent().getLongExtra(EXTRA_ACCOUNT_ID, -1);
|
||||||
@ -123,30 +136,45 @@ public class AccountSecurity extends Activity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finish();
|
if (!startedActivity) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Now that we are connected as an active device admin, try to set the device to the
|
* Now that we are connected as an active device admin, try to set the device to the
|
||||||
* correct security level, and ask for a password if necessary.
|
* correct security level, and ask for a password if necessary.
|
||||||
|
* @return true if we started another activity (and should not finish(), as we're waiting for
|
||||||
|
* their result.)
|
||||||
*/
|
*/
|
||||||
private void setActivePolicies() {
|
private boolean setActivePolicies() {
|
||||||
SecurityPolicy sp = SecurityPolicy.getInstance(this);
|
SecurityPolicy sp = SecurityPolicy.getInstance(this);
|
||||||
// check current security level - if sufficient, we're done!
|
// check current security level - if sufficient, we're done!
|
||||||
if (sp.isActive(null)) {
|
if (sp.isActive(null)) {
|
||||||
Account.clearSecurityHoldOnAllAccounts(this);
|
Account.clearSecurityHoldOnAllAccounts(this);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
// set current security level
|
// set current security level
|
||||||
sp.setActivePolicies();
|
sp.setActivePolicies();
|
||||||
// check current security level - if sufficient, we're done!
|
// check current security level - if sufficient, we're done!
|
||||||
if (sp.isActive(null)) {
|
int inactiveReasons = sp.getInactiveReasons(null);
|
||||||
|
if (inactiveReasons == 0) {
|
||||||
Account.clearSecurityHoldOnAllAccounts(this);
|
Account.clearSecurityHoldOnAllAccounts(this);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
// if not sufficient, launch the activity to have the user set a new password.
|
// If password or encryption required, launch relevant intent
|
||||||
Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
|
if ((inactiveReasons & SecurityPolicy.INACTIVE_NEED_PASSWORD) != 0) {
|
||||||
startActivity(intent);
|
// launch the activity to have the user set a new password.
|
||||||
|
Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
|
||||||
|
startActivityForResult(intent, REQUEST_PASSWORD);
|
||||||
|
return true;
|
||||||
|
} else if ((inactiveReasons & SecurityPolicy.INACTIVE_NEED_ENCRYPTION) != 0) {
|
||||||
|
// launch the activity to start up encryption.
|
||||||
|
Intent intent = new Intent(DevicePolicyManager.ACTION_START_ENCRYPTION);
|
||||||
|
startActivityForResult(intent, REQUEST_ENCRYPTION);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,7 +196,7 @@ public class ProvisionParser extends Parser {
|
|||||||
|
|
||||||
mPolicySet = new SecurityPolicy.PolicySet(minPasswordLength, passwordMode,
|
mPolicySet = new SecurityPolicy.PolicySet(minPasswordLength, passwordMode,
|
||||||
maxPasswordFails, maxScreenLockTime, true, passwordExpirationDays, passwordHistory,
|
maxPasswordFails, maxScreenLockTime, true, passwordExpirationDays, passwordHistory,
|
||||||
passwordComplexChars);
|
passwordComplexChars, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -253,7 +253,7 @@ public class ProvisionParser extends Parser {
|
|||||||
|
|
||||||
mPolicySet = new PolicySet(sps.mMinPasswordLength, sps.mPasswordMode, sps.mMaxPasswordFails,
|
mPolicySet = new PolicySet(sps.mMinPasswordLength, sps.mPasswordMode, sps.mMaxPasswordFails,
|
||||||
sps.mMaxScreenLockTime, true, sps.mPasswordExpiration, sps.mPasswordHistory,
|
sps.mMaxScreenLockTime, true, sps.mPasswordExpiration, sps.mPasswordHistory,
|
||||||
sps.mPasswordComplexChars);
|
sps.mPasswordComplexChars, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,7 +48,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
private Context mMockContext;
|
private Context mMockContext;
|
||||||
|
|
||||||
private static final PolicySet EMPTY_POLICY_SET =
|
private static final PolicySet EMPTY_POLICY_SET =
|
||||||
new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, false, 0, 0, 0);
|
new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, false, 0, 0, 0, false);
|
||||||
|
|
||||||
public SecurityPolicyTests() {
|
public SecurityPolicyTests() {
|
||||||
super(EmailProvider.class, EmailProvider.EMAIL_AUTHORITY);
|
super(EmailProvider.class, EmailProvider.EMAIL_AUTHORITY);
|
||||||
@ -108,28 +108,28 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
// We know that EMPTY_POLICY_SET doesn't generate an Exception or we wouldn't be here
|
// We know that EMPTY_POLICY_SET doesn't generate an Exception or we wouldn't be here
|
||||||
// Try some illegal parameters
|
// Try some illegal parameters
|
||||||
try {
|
try {
|
||||||
new PolicySet(100, PolicySet.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0);
|
new PolicySet(100, PolicySet.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0, false);
|
||||||
fail("Too-long password allowed");
|
fail("Too-long password allowed");
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
new PolicySet(0, PolicySet.PASSWORD_MODE_STRONG + 1, 0, 0, false, 0, 0, 0);
|
new PolicySet(0, PolicySet.PASSWORD_MODE_STRONG + 1, 0, 0, false, 0, 0, 0, false);
|
||||||
fail("Illegal password mode allowed");
|
fail("Illegal password mode allowed");
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PolicySet ps = new PolicySet(0, PolicySet.PASSWORD_MODE_SIMPLE, 0,
|
PolicySet ps = new PolicySet(0, PolicySet.PASSWORD_MODE_SIMPLE, 0,
|
||||||
PolicySet.SCREEN_LOCK_TIME_MAX + 1, false, 0, 0, 0);
|
PolicySet.SCREEN_LOCK_TIME_MAX + 1, false, 0, 0, 0, false);
|
||||||
assertEquals(PolicySet.SCREEN_LOCK_TIME_MAX, ps.getMaxScreenLockTimeForTest());
|
assertEquals(PolicySet.SCREEN_LOCK_TIME_MAX, ps.getMaxScreenLockTimeForTest());
|
||||||
|
|
||||||
ps = new PolicySet(0, PolicySet.PASSWORD_MODE_SIMPLE,
|
ps = new PolicySet(0, PolicySet.PASSWORD_MODE_SIMPLE,
|
||||||
PolicySet.PASSWORD_MAX_FAILS_MAX + 1, 0, false, 0, 0, 0);
|
PolicySet.PASSWORD_MAX_FAILS_MAX + 1, 0, false, 0, 0, 0, false);
|
||||||
assertEquals(PolicySet.PASSWORD_MAX_FAILS_MAX, ps.getMaxPasswordFailsForTest());
|
assertEquals(PolicySet.PASSWORD_MAX_FAILS_MAX, ps.getMaxPasswordFailsForTest());
|
||||||
// All password related fields should be zero when password mode is NONE
|
// All password related fields should be zero when password mode is NONE
|
||||||
// Illegal values for these fields should be ignored
|
// Illegal values for these fields should be ignored
|
||||||
ps = new PolicySet(999/*length*/, PolicySet.PASSWORD_MODE_NONE,
|
ps = new PolicySet(999/*length*/, PolicySet.PASSWORD_MODE_NONE,
|
||||||
999/*fails*/, 9999/*screenlock*/, false, 999/*expir*/, 999/*history*/,
|
999/*fails*/, 9999/*screenlock*/, false, 999/*expir*/, 999/*history*/,
|
||||||
999/*complex*/);
|
999/*complex*/, false);
|
||||||
assertEquals(0, ps.mMinPasswordLength);
|
assertEquals(0, ps.mMinPasswordLength);
|
||||||
assertEquals(0, ps.mMaxScreenLockTime);
|
assertEquals(0, ps.mMaxScreenLockTime);
|
||||||
assertEquals(0, ps.mMaxPasswordFails);
|
assertEquals(0, ps.mMaxPasswordFails);
|
||||||
@ -139,7 +139,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
|
|
||||||
// With a simple password, we should set complex chars to zero
|
// With a simple password, we should set complex chars to zero
|
||||||
ps = new PolicySet(4/*length*/, PolicySet.PASSWORD_MODE_SIMPLE,
|
ps = new PolicySet(4/*length*/, PolicySet.PASSWORD_MODE_SIMPLE,
|
||||||
0, 0, false, 0, 0, 3/*complex*/);
|
0, 0, false, 0, 0, 3/*complex*/, false);
|
||||||
assertEquals(4, ps.mMinPasswordLength);
|
assertEquals(4, ps.mMinPasswordLength);
|
||||||
assertEquals(0, ps.mPasswordComplexChars);
|
assertEquals(0, ps.mPasswordComplexChars);
|
||||||
}
|
}
|
||||||
@ -165,14 +165,16 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
// with a single account in security mode, should return same security as in account
|
// with a single account in security mode, should return same security as in account
|
||||||
// first test with partially-populated policies
|
// first test with partially-populated policies
|
||||||
Account a3 = ProviderTestUtils.setupAccount("sec-3", false, mMockContext);
|
Account a3 = ProviderTestUtils.setupAccount("sec-3", false, mMockContext);
|
||||||
PolicySet p3ain = new PolicySet(10, PolicySet.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0);
|
PolicySet p3ain = new PolicySet(10, PolicySet.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0,
|
||||||
|
false);
|
||||||
p3ain.writeAccount(a3, null, true, mMockContext);
|
p3ain.writeAccount(a3, null, true, mMockContext);
|
||||||
PolicySet p3aout = sp.computeAggregatePolicy();
|
PolicySet p3aout = sp.computeAggregatePolicy();
|
||||||
assertNotNull(p3aout);
|
assertNotNull(p3aout);
|
||||||
assertEquals(p3ain, p3aout);
|
assertEquals(p3ain, p3aout);
|
||||||
|
|
||||||
// Repeat that test with fully-populated policies
|
// Repeat that test with fully-populated policies
|
||||||
PolicySet p3bin = new PolicySet(10, PolicySet.PASSWORD_MODE_SIMPLE, 15, 16, false, 6, 2, 3);
|
PolicySet p3bin = new PolicySet(10, PolicySet.PASSWORD_MODE_SIMPLE, 15, 16, false, 6, 2, 3,
|
||||||
|
false);
|
||||||
p3bin.writeAccount(a3, null, true, mMockContext);
|
p3bin.writeAccount(a3, null, true, mMockContext);
|
||||||
PolicySet p3bout = sp.computeAggregatePolicy();
|
PolicySet p3bout = sp.computeAggregatePolicy();
|
||||||
assertNotNull(p3bout);
|
assertNotNull(p3bout);
|
||||||
@ -184,7 +186,9 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
// wipe required - OR logic - will *not* change here because false
|
// wipe required - OR logic - will *not* change here because false
|
||||||
// expiration - will not change because 0 (unspecified)
|
// expiration - will not change because 0 (unspecified)
|
||||||
// max complex chars - max logic - will change
|
// max complex chars - max logic - will change
|
||||||
PolicySet p4in = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 0, 5, 7);
|
// encryption required - OR logic - will *not* change here because false
|
||||||
|
PolicySet p4in = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 0, 5, 7,
|
||||||
|
false);
|
||||||
Account a4 = ProviderTestUtils.setupAccount("sec-4", false, mMockContext);
|
Account a4 = ProviderTestUtils.setupAccount("sec-4", false, mMockContext);
|
||||||
p4in.writeAccount(a4, null, true, mMockContext);
|
p4in.writeAccount(a4, null, true, mMockContext);
|
||||||
PolicySet p4out = sp.computeAggregatePolicy();
|
PolicySet p4out = sp.computeAggregatePolicy();
|
||||||
@ -197,6 +201,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
assertEquals(5, p4out.mPasswordHistory);
|
assertEquals(5, p4out.mPasswordHistory);
|
||||||
assertEquals(7, p4out.mPasswordComplexChars);
|
assertEquals(7, p4out.mPasswordComplexChars);
|
||||||
assertFalse(p4out.mRequireRemoteWipe);
|
assertFalse(p4out.mRequireRemoteWipe);
|
||||||
|
assertFalse(p4out.mRequireEncryption);
|
||||||
|
|
||||||
// add another account which mixes it up (the remaining fields will change)
|
// add another account which mixes it up (the remaining fields will change)
|
||||||
// pw length and pw mode - max logic - will *not* change because smaller #s here
|
// pw length and pw mode - max logic - will *not* change because smaller #s here
|
||||||
@ -204,7 +209,9 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
// wipe required - OR logic - will change here because true
|
// wipe required - OR logic - will change here because true
|
||||||
// expiration time - min logic - will change because lower here
|
// expiration time - min logic - will change because lower here
|
||||||
// history & complex chars - will not change because 0 (unspecified)
|
// history & complex chars - will not change because 0 (unspecified)
|
||||||
PolicySet p5in = new PolicySet(4, PolicySet.PASSWORD_MODE_SIMPLE, 5, 6, true, 1, 0, 0);
|
// encryption required - OR logic - will change here because true
|
||||||
|
PolicySet p5in = new PolicySet(4, PolicySet.PASSWORD_MODE_SIMPLE, 5, 6, true, 1, 0, 0,
|
||||||
|
true);
|
||||||
Account a5 = ProviderTestUtils.setupAccount("sec-5", false, mMockContext);
|
Account a5 = ProviderTestUtils.setupAccount("sec-5", false, mMockContext);
|
||||||
p5in.writeAccount(a5, null, true, mMockContext);
|
p5in.writeAccount(a5, null, true, mMockContext);
|
||||||
PolicySet p5out = sp.computeAggregatePolicy();
|
PolicySet p5out = sp.computeAggregatePolicy();
|
||||||
@ -214,9 +221,10 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
assertEquals(5, p5out.mMaxPasswordFails);
|
assertEquals(5, p5out.mMaxPasswordFails);
|
||||||
assertEquals(6, p5out.mMaxScreenLockTime);
|
assertEquals(6, p5out.mMaxScreenLockTime);
|
||||||
assertEquals(1, p5out.mPasswordExpirationDays);
|
assertEquals(1, p5out.mPasswordExpirationDays);
|
||||||
assertEquals(5, p4out.mPasswordHistory);
|
assertEquals(5, p5out.mPasswordHistory);
|
||||||
assertEquals(7, p4out.mPasswordComplexChars);
|
assertEquals(7, p5out.mPasswordComplexChars);
|
||||||
assertTrue(p5out.mRequireRemoteWipe);
|
assertTrue(p5out.mRequireRemoteWipe);
|
||||||
|
assertTrue(p5out.mRequireEncryption);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -244,8 +252,9 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
*/
|
*/
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public void testFieldIsolation() {
|
public void testFieldIsolation() {
|
||||||
|
// Check PASSWORD_LENGTH
|
||||||
PolicySet p = new PolicySet(PolicySet.PASSWORD_LENGTH_MAX, PolicySet.PASSWORD_MODE_SIMPLE,
|
PolicySet p = new PolicySet(PolicySet.PASSWORD_LENGTH_MAX, PolicySet.PASSWORD_MODE_SIMPLE,
|
||||||
0, 0, false, 0, 0 ,0);
|
0, 0, false, 0, 0 ,0, false);
|
||||||
assertEquals(PolicySet.PASSWORD_MODE_SIMPLE, p.mPasswordMode);
|
assertEquals(PolicySet.PASSWORD_MODE_SIMPLE, p.mPasswordMode);
|
||||||
assertEquals(PolicySet.PASSWORD_LENGTH_MAX, p.mMinPasswordLength);
|
assertEquals(PolicySet.PASSWORD_LENGTH_MAX, p.mMinPasswordLength);
|
||||||
assertEquals(0, p.mMaxPasswordFails);
|
assertEquals(0, p.mMaxPasswordFails);
|
||||||
@ -254,8 +263,10 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
assertEquals(0, p.mPasswordHistory);
|
assertEquals(0, p.mPasswordHistory);
|
||||||
assertEquals(0, p.mPasswordComplexChars);
|
assertEquals(0, p.mPasswordComplexChars);
|
||||||
assertFalse(p.mRequireRemoteWipe);
|
assertFalse(p.mRequireRemoteWipe);
|
||||||
|
assertFalse(p.mRequireEncryption);
|
||||||
|
|
||||||
p = new PolicySet(0, PolicySet.PASSWORD_MODE_STRONG, 0, 0, false, 0, 0, 0);
|
// Check PASSWORD_MODE
|
||||||
|
p = new PolicySet(0, PolicySet.PASSWORD_MODE_STRONG, 0, 0, false, 0, 0, 0, false);
|
||||||
assertEquals(PolicySet.PASSWORD_MODE_STRONG, p.mPasswordMode);
|
assertEquals(PolicySet.PASSWORD_MODE_STRONG, p.mPasswordMode);
|
||||||
assertEquals(0, p.mMinPasswordLength);
|
assertEquals(0, p.mMinPasswordLength);
|
||||||
assertEquals(0, p.mMaxPasswordFails);
|
assertEquals(0, p.mMaxPasswordFails);
|
||||||
@ -264,9 +275,11 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
assertEquals(0, p.mPasswordHistory);
|
assertEquals(0, p.mPasswordHistory);
|
||||||
assertEquals(0, p.mPasswordComplexChars);
|
assertEquals(0, p.mPasswordComplexChars);
|
||||||
assertFalse(p.mRequireRemoteWipe);
|
assertFalse(p.mRequireRemoteWipe);
|
||||||
|
assertFalse(p.mRequireEncryption);
|
||||||
|
|
||||||
|
// Check PASSWORD_FAILS (note, mode must be set for this to be non-zero)
|
||||||
p = new PolicySet(0, PolicySet.PASSWORD_MODE_SIMPLE, PolicySet.PASSWORD_MAX_FAILS_MAX, 0,
|
p = new PolicySet(0, PolicySet.PASSWORD_MODE_SIMPLE, PolicySet.PASSWORD_MAX_FAILS_MAX, 0,
|
||||||
false, 0, 0, 0);
|
false, 0, 0, 0, false);
|
||||||
assertEquals(PolicySet.PASSWORD_MODE_SIMPLE, p.mPasswordMode);
|
assertEquals(PolicySet.PASSWORD_MODE_SIMPLE, p.mPasswordMode);
|
||||||
assertEquals(0, p.mMinPasswordLength);
|
assertEquals(0, p.mMinPasswordLength);
|
||||||
assertEquals(PolicySet.PASSWORD_MAX_FAILS_MAX, p.mMaxPasswordFails);
|
assertEquals(PolicySet.PASSWORD_MAX_FAILS_MAX, p.mMaxPasswordFails);
|
||||||
@ -275,9 +288,11 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
assertEquals(0, p.mPasswordHistory);
|
assertEquals(0, p.mPasswordHistory);
|
||||||
assertEquals(0, p.mPasswordComplexChars);
|
assertEquals(0, p.mPasswordComplexChars);
|
||||||
assertFalse(p.mRequireRemoteWipe);
|
assertFalse(p.mRequireRemoteWipe);
|
||||||
|
assertFalse(p.mRequireEncryption);
|
||||||
|
|
||||||
|
// Check SCREEN_LOCK_TIME (note, mode must be set for this to be non-zero)
|
||||||
p = new PolicySet(0, PolicySet.PASSWORD_MODE_SIMPLE, 0, PolicySet.SCREEN_LOCK_TIME_MAX,
|
p = new PolicySet(0, PolicySet.PASSWORD_MODE_SIMPLE, 0, PolicySet.SCREEN_LOCK_TIME_MAX,
|
||||||
false, 0, 0, 0);
|
false, 0, 0, 0, false);
|
||||||
assertEquals(PolicySet.PASSWORD_MODE_SIMPLE, p.mPasswordMode);
|
assertEquals(PolicySet.PASSWORD_MODE_SIMPLE, p.mPasswordMode);
|
||||||
assertEquals(0, p.mMinPasswordLength);
|
assertEquals(0, p.mMinPasswordLength);
|
||||||
assertEquals(0, p.mMaxPasswordFails);
|
assertEquals(0, p.mMaxPasswordFails);
|
||||||
@ -286,8 +301,10 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
assertEquals(0, p.mPasswordHistory);
|
assertEquals(0, p.mPasswordHistory);
|
||||||
assertEquals(0, p.mPasswordComplexChars);
|
assertEquals(0, p.mPasswordComplexChars);
|
||||||
assertFalse(p.mRequireRemoteWipe);
|
assertFalse(p.mRequireRemoteWipe);
|
||||||
|
assertFalse(p.mRequireEncryption);
|
||||||
|
|
||||||
p = new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, true, 0, 0, 0);
|
// Check REQUIRE_REMOTE_WIPE
|
||||||
|
p = new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, true, 0, 0, 0, false);
|
||||||
assertEquals(PolicySet.PASSWORD_MODE_NONE, p.mPasswordMode);
|
assertEquals(PolicySet.PASSWORD_MODE_NONE, p.mPasswordMode);
|
||||||
assertEquals(0, p.mMinPasswordLength);
|
assertEquals(0, p.mMinPasswordLength);
|
||||||
assertEquals(0, p.mMaxPasswordFails);
|
assertEquals(0, p.mMaxPasswordFails);
|
||||||
@ -296,9 +313,11 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
assertEquals(0, p.mPasswordHistory);
|
assertEquals(0, p.mPasswordHistory);
|
||||||
assertEquals(0, p.mPasswordComplexChars);
|
assertEquals(0, p.mPasswordComplexChars);
|
||||||
assertTrue(p.mRequireRemoteWipe);
|
assertTrue(p.mRequireRemoteWipe);
|
||||||
|
assertFalse(p.mRequireEncryption);
|
||||||
|
|
||||||
|
// Check PASSWORD_EXPIRATION (note, mode must be set for this to be non-zero)
|
||||||
p = new PolicySet(0, PolicySet.PASSWORD_MODE_SIMPLE, 0, 0, false,
|
p = new PolicySet(0, PolicySet.PASSWORD_MODE_SIMPLE, 0, 0, false,
|
||||||
PolicySet.PASSWORD_EXPIRATION_MAX, 0, 0);
|
PolicySet.PASSWORD_EXPIRATION_MAX, 0, 0, false);
|
||||||
assertEquals(PolicySet.PASSWORD_MODE_SIMPLE, p.mPasswordMode);
|
assertEquals(PolicySet.PASSWORD_MODE_SIMPLE, p.mPasswordMode);
|
||||||
assertEquals(0, p.mMinPasswordLength);
|
assertEquals(0, p.mMinPasswordLength);
|
||||||
assertEquals(0, p.mMaxPasswordFails);
|
assertEquals(0, p.mMaxPasswordFails);
|
||||||
@ -307,9 +326,11 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
assertEquals(0, p.mPasswordHistory);
|
assertEquals(0, p.mPasswordHistory);
|
||||||
assertEquals(0, p.mPasswordComplexChars);
|
assertEquals(0, p.mPasswordComplexChars);
|
||||||
assertFalse(p.mRequireRemoteWipe);
|
assertFalse(p.mRequireRemoteWipe);
|
||||||
|
assertFalse(p.mRequireEncryption);
|
||||||
|
|
||||||
|
// Check PASSWORD_HISTORY (note, mode must be set for this to be non-zero)
|
||||||
p = new PolicySet(0, PolicySet.PASSWORD_MODE_SIMPLE, 0, 0, false, 0,
|
p = new PolicySet(0, PolicySet.PASSWORD_MODE_SIMPLE, 0, 0, false, 0,
|
||||||
PolicySet.PASSWORD_HISTORY_MAX, 0);
|
PolicySet.PASSWORD_HISTORY_MAX, 0, false);
|
||||||
assertEquals(PolicySet.PASSWORD_MODE_SIMPLE, p.mPasswordMode);
|
assertEquals(PolicySet.PASSWORD_MODE_SIMPLE, p.mPasswordMode);
|
||||||
assertEquals(0, p.mMinPasswordLength);
|
assertEquals(0, p.mMinPasswordLength);
|
||||||
assertEquals(0, p.mMaxPasswordFails);
|
assertEquals(0, p.mMaxPasswordFails);
|
||||||
@ -318,9 +339,11 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
assertEquals(PolicySet.PASSWORD_HISTORY_MAX, p.mPasswordHistory);
|
assertEquals(PolicySet.PASSWORD_HISTORY_MAX, p.mPasswordHistory);
|
||||||
assertEquals(0, p.mPasswordComplexChars);
|
assertEquals(0, p.mPasswordComplexChars);
|
||||||
assertFalse(p.mRequireRemoteWipe);
|
assertFalse(p.mRequireRemoteWipe);
|
||||||
|
assertFalse(p.mRequireEncryption);
|
||||||
|
|
||||||
|
// Check PASSWORD_COMPLEX_CHARS (note, mode must be set for this to be non-zero)
|
||||||
p = new PolicySet(0, PolicySet.PASSWORD_MODE_STRONG, 0, 0, false, 0, 0,
|
p = new PolicySet(0, PolicySet.PASSWORD_MODE_STRONG, 0, 0, false, 0, 0,
|
||||||
PolicySet.PASSWORD_COMPLEX_CHARS_MAX);
|
PolicySet.PASSWORD_COMPLEX_CHARS_MAX, false);
|
||||||
assertEquals(PolicySet.PASSWORD_MODE_STRONG, p.mPasswordMode);
|
assertEquals(PolicySet.PASSWORD_MODE_STRONG, p.mPasswordMode);
|
||||||
assertEquals(0, p.mMinPasswordLength);
|
assertEquals(0, p.mMinPasswordLength);
|
||||||
assertEquals(0, p.mMaxPasswordFails);
|
assertEquals(0, p.mMaxPasswordFails);
|
||||||
@ -329,6 +352,19 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
assertEquals(0, p.mPasswordHistory);
|
assertEquals(0, p.mPasswordHistory);
|
||||||
assertEquals(PolicySet.PASSWORD_COMPLEX_CHARS_MAX, p.mPasswordComplexChars);
|
assertEquals(PolicySet.PASSWORD_COMPLEX_CHARS_MAX, p.mPasswordComplexChars);
|
||||||
assertFalse(p.mRequireRemoteWipe);
|
assertFalse(p.mRequireRemoteWipe);
|
||||||
|
assertFalse(p.mRequireEncryption);
|
||||||
|
|
||||||
|
// Check REQUIRE_ENCRYPTION
|
||||||
|
p = new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, false, 0, 0, 0, true);
|
||||||
|
assertEquals(PolicySet.PASSWORD_MODE_NONE, p.mPasswordMode);
|
||||||
|
assertEquals(0, p.mMinPasswordLength);
|
||||||
|
assertEquals(0, p.mMaxPasswordFails);
|
||||||
|
assertEquals(0, p.mMaxScreenLockTime);
|
||||||
|
assertEquals(0, p.mPasswordExpirationDays);
|
||||||
|
assertEquals(0, p.mPasswordHistory);
|
||||||
|
assertEquals(0, p.mPasswordComplexChars);
|
||||||
|
assertFalse(p.mRequireRemoteWipe);
|
||||||
|
assertTrue(p.mRequireEncryption);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -336,7 +372,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
*/
|
*/
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public void testAccountEncoding() {
|
public void testAccountEncoding() {
|
||||||
PolicySet p1 = new PolicySet(1, PolicySet.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9);
|
PolicySet p1 = new PolicySet(1, PolicySet.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false);
|
||||||
Account a = new Account();
|
Account a = new Account();
|
||||||
final String SYNC_KEY = "test_sync_key";
|
final String SYNC_KEY = "test_sync_key";
|
||||||
p1.writeAccount(a, SYNC_KEY, false, null);
|
p1.writeAccount(a, SYNC_KEY, false, null);
|
||||||
@ -350,9 +386,9 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
*/
|
*/
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public void testEquals() {
|
public void testEquals() {
|
||||||
PolicySet p1 = new PolicySet(1, PolicySet.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9);
|
PolicySet p1 = new PolicySet(1, PolicySet.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false);
|
||||||
PolicySet p2 = new PolicySet(1, PolicySet.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9);
|
PolicySet p2 = new PolicySet(1, PolicySet.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false);
|
||||||
PolicySet p3 = new PolicySet(2, PolicySet.PASSWORD_MODE_SIMPLE, 5, 6, true, 7, 8, 9);
|
PolicySet p3 = new PolicySet(2, PolicySet.PASSWORD_MODE_SIMPLE, 5, 6, true, 7, 8, 9, false);
|
||||||
assertTrue(p1.equals(p2));
|
assertTrue(p1.equals(p2));
|
||||||
assertFalse(p2.equals(p3));
|
assertFalse(p2.equals(p3));
|
||||||
}
|
}
|
||||||
@ -401,11 +437,13 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
*/
|
*/
|
||||||
public void testDisableAdmin() {
|
public void testDisableAdmin() {
|
||||||
Account a1 = ProviderTestUtils.setupAccount("disable-1", false, mMockContext);
|
Account a1 = ProviderTestUtils.setupAccount("disable-1", false, mMockContext);
|
||||||
PolicySet p1 = new PolicySet(10, PolicySet.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0);
|
PolicySet p1 = new PolicySet(10, PolicySet.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0,
|
||||||
|
false);
|
||||||
p1.writeAccount(a1, "sync-key-1", true, mMockContext);
|
p1.writeAccount(a1, "sync-key-1", true, mMockContext);
|
||||||
|
|
||||||
Account a2 = ProviderTestUtils.setupAccount("disable-2", false, mMockContext);
|
Account a2 = ProviderTestUtils.setupAccount("disable-2", false, mMockContext);
|
||||||
PolicySet p2 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0);
|
PolicySet p2 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0,
|
||||||
|
false);
|
||||||
p2.writeAccount(a2, "sync-key-2", true, mMockContext);
|
p2.writeAccount(a2, "sync-key-2", true, mMockContext);
|
||||||
|
|
||||||
Account a3 = ProviderTestUtils.setupAccount("disable-3", false, mMockContext);
|
Account a3 = ProviderTestUtils.setupAccount("disable-3", false, mMockContext);
|
||||||
@ -460,7 +498,8 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
|
|
||||||
// Add a single expiring account
|
// Add a single expiring account
|
||||||
Account a2 = ProviderTestUtils.setupAccount("expiring-2", false, mMockContext);
|
Account a2 = ProviderTestUtils.setupAccount("expiring-2", false, mMockContext);
|
||||||
PolicySet p2 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0);
|
PolicySet p2 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0,
|
||||||
|
false);
|
||||||
p2.writeAccount(a2, "sync-key-2", true, mMockContext);
|
p2.writeAccount(a2, "sync-key-2", true, mMockContext);
|
||||||
|
|
||||||
// The expiring account should be returned
|
// The expiring account should be returned
|
||||||
@ -469,7 +508,8 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
|
|
||||||
// Add an account with a longer expiration
|
// Add an account with a longer expiration
|
||||||
Account a3 = ProviderTestUtils.setupAccount("expiring-3", false, mMockContext);
|
Account a3 = ProviderTestUtils.setupAccount("expiring-3", false, mMockContext);
|
||||||
PolicySet p3 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 60, 0, 0);
|
PolicySet p3 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 60, 0, 0,
|
||||||
|
false);
|
||||||
p3.writeAccount(a3, "sync-key-3", true, mMockContext);
|
p3.writeAccount(a3, "sync-key-3", true, mMockContext);
|
||||||
|
|
||||||
// The original expiring account (a2) should be returned
|
// The original expiring account (a2) should be returned
|
||||||
@ -478,7 +518,8 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
|
|
||||||
// Add an account with a shorter expiration
|
// Add an account with a shorter expiration
|
||||||
Account a4 = ProviderTestUtils.setupAccount("expiring-4", false, mMockContext);
|
Account a4 = ProviderTestUtils.setupAccount("expiring-4", false, mMockContext);
|
||||||
PolicySet p4 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 15, 0, 0);
|
PolicySet p4 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 15, 0, 0,
|
||||||
|
false);
|
||||||
p4.writeAccount(a4, "sync-key-4", true, mMockContext);
|
p4.writeAccount(a4, "sync-key-4", true, mMockContext);
|
||||||
|
|
||||||
// The new expiring account (a4) should be returned
|
// The new expiring account (a4) should be returned
|
||||||
@ -507,7 +548,8 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
// Two accounts - a1 is normal, a2 has security (but no expiration)
|
// Two accounts - a1 is normal, a2 has security (but no expiration)
|
||||||
Account a1 = ProviderTestUtils.setupAccount("expired-1", true, mMockContext);
|
Account a1 = ProviderTestUtils.setupAccount("expired-1", true, mMockContext);
|
||||||
Account a2 = ProviderTestUtils.setupAccount("expired-2", false, mMockContext);
|
Account a2 = ProviderTestUtils.setupAccount("expired-2", false, mMockContext);
|
||||||
PolicySet p2 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0);
|
PolicySet p2 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0,
|
||||||
|
false);
|
||||||
p2.writeAccount(a2, "sync-key-2", true, mMockContext);
|
p2.writeAccount(a2, "sync-key-2", true, mMockContext);
|
||||||
|
|
||||||
// Add a mailbox & messages to each account
|
// Add a mailbox & messages to each account
|
||||||
@ -532,7 +574,8 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|||||||
|
|
||||||
// Add 3rd account that really expires
|
// Add 3rd account that really expires
|
||||||
Account a3 = ProviderTestUtils.setupAccount("expired-3", false, mMockContext);
|
Account a3 = ProviderTestUtils.setupAccount("expired-3", false, mMockContext);
|
||||||
PolicySet p3 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0);
|
PolicySet p3 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0,
|
||||||
|
false);
|
||||||
p3.writeAccount(a3, "sync-key-3", true, mMockContext);
|
p3.writeAccount(a3, "sync-key-3", true, mMockContext);
|
||||||
|
|
||||||
// Add mailbox & messages to 3rd account
|
// Add mailbox & messages to 3rd account
|
||||||
|
Loading…
Reference in New Issue
Block a user