Merge "Enable SD card encryption policy when emulated"

This commit is contained in:
Andy Stadler 2011-03-02 20:45:53 -08:00 committed by Android (Google) Code Review
commit 45e161bb5e
3 changed files with 146 additions and 51 deletions

View File

@ -63,8 +63,10 @@ public class PolicySet implements Parcelable {
private static final int PASSWORD_COMPLEX_CHARS_SHIFT = 44;
private static final long PASSWORD_COMPLEX_CHARS_MASK = 31L << PASSWORD_COMPLEX_CHARS_SHIFT;
public static final int PASSWORD_COMPLEX_CHARS_MAX = 31;
// bit 49: requires device encryption
// bit 49: requires device encryption (internal)
private static final long REQUIRE_ENCRYPTION = 1L << 49;
// bit 50: requires external storage encryption
private static final long REQUIRE_ENCRYPTION_EXTERNAL = 1L << 50;
/* Convert days to mSec (used for password expiration) */
private static final long DAYS_TO_MSEC = 24 * 60 * 60 * 1000;
@ -80,6 +82,7 @@ public class PolicySet implements Parcelable {
public final int mPasswordHistory;
public final int mPasswordComplexChars;
public final boolean mRequireEncryption;
public final boolean mRequireEncryptionExternal;
public int getMinPasswordLengthForTest() {
return mMinPasswordLength;
@ -105,6 +108,10 @@ public class PolicySet implements Parcelable {
return mRequireEncryption;
}
public boolean isRequireEncryptionExternalForTest() {
return mRequireEncryptionExternal;
}
/**
* Create from raw values.
* @param minPasswordLength (0=not enforced)
@ -115,12 +122,14 @@ public class PolicySet implements Parcelable {
* @param passwordExpirationDays in days (0=not enforced)
* @param passwordHistory (0=not enforced)
* @param passwordComplexChars (0=not enforced)
* @param requireEncryption
* @param requireEncryptionExternal
* @throws IllegalArgumentException for illegal arguments.
*/
public PolicySet(int minPasswordLength, int passwordMode, int maxPasswordFails,
int maxScreenLockTime, boolean requireRemoteWipe, int passwordExpirationDays,
int passwordHistory, int passwordComplexChars, boolean requireEncryption)
throws IllegalArgumentException {
int passwordHistory, int passwordComplexChars, boolean requireEncryption,
boolean requireEncryptionExternal) throws IllegalArgumentException {
// 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
if (passwordMode == PASSWORD_MODE_NONE) {
@ -171,6 +180,7 @@ public class PolicySet implements Parcelable {
mPasswordHistory = passwordHistory;
mPasswordComplexChars = passwordComplexChars;
mRequireEncryption = requireEncryption;
mRequireEncryptionExternal = requireEncryptionExternal;
}
/**
@ -201,6 +211,7 @@ public class PolicySet implements Parcelable {
mPasswordComplexChars =
(int) ((flags & PASSWORD_COMPLEX_CHARS_MASK) >> PASSWORD_COMPLEX_CHARS_SHIFT);
mRequireEncryption = 0 != (flags & REQUIRE_ENCRYPTION);
mRequireEncryptionExternal = 0 != (flags & REQUIRE_ENCRYPTION_EXTERNAL);
}
/**
@ -305,6 +316,7 @@ public class PolicySet implements Parcelable {
dest.writeInt(mPasswordHistory);
dest.writeInt(mPasswordComplexChars);
dest.writeInt(mRequireEncryption ? 1 : 0);
dest.writeInt(mRequireEncryptionExternal ? 1 : 0);
}
/**
@ -320,6 +332,7 @@ public class PolicySet implements Parcelable {
mPasswordHistory = in.readInt();
mPasswordComplexChars = in.readInt();
mRequireEncryption = in.readInt() == 1;
mRequireEncryptionExternal = in.readInt() == 1;
}
@Override
@ -339,6 +352,7 @@ public class PolicySet implements Parcelable {
flags |= (long)mPasswordExpirationDays << PASSWORD_EXPIRATION_SHIFT;
flags |= (long)mPasswordComplexChars << PASSWORD_COMPLEX_CHARS_SHIFT;
if (mRequireEncryption) flags |= REQUIRE_ENCRYPTION;
if (mRequireEncryptionExternal) flags |= REQUIRE_ENCRYPTION_EXTERNAL;
return flags;
}
@ -350,7 +364,8 @@ public class PolicySet implements Parcelable {
+ " pw-expiration=" + mPasswordExpirationDays
+ " pw-history=" + mPasswordHistory
+ " pw-complex-chars=" + mPasswordComplexChars
+ " require-encryption=" + mRequireEncryption + "}";
+ " require-encryption=" + mRequireEncryption
+ " require-encryptionExternal=" + mRequireEncryptionExternal + "}";
}
}

View File

@ -33,6 +33,7 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Environment;
import android.util.Log;
/**
@ -48,7 +49,7 @@ public class SecurityPolicy {
private PolicySet mAggregatePolicy;
/* package */ static final PolicySet NO_POLICY_SET =
new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, false, 0, 0, 0, false);
new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, false, 0, 0, 0, false, false);
/**
* This projection on Account is for scanning/reading
@ -105,6 +106,7 @@ public class SecurityPolicy {
* password expiration take the min (strongest mode)
* password complex chars take the max (strongest mode)
* encryption take the max (logical or)
* encryption (external) take the max (logical or)
*
* @return a policy representing the strongest aggregate. If no policy sets are defined,
* a lightweight "nothing required" policy will be returned. Never null.
@ -121,6 +123,7 @@ public class SecurityPolicy {
int passwordExpirationDays = Integer.MAX_VALUE;
int passwordComplexChars = Integer.MIN_VALUE;
boolean requireEncryption = false;
boolean requireEncryptionExternal = false;
Cursor c = mContext.getContentResolver().query(Account.CONTENT_URI,
ACCOUNT_SECURITY_PROJECTION, Account.SECURITY_NONZERO_SELECTION, null, null);
@ -150,6 +153,7 @@ public class SecurityPolicy {
}
requireRemoteWipe |= p.mRequireRemoteWipe;
requireEncryption |= p.mRequireEncryption;
requireEncryptionExternal |= p.mRequireEncryptionExternal;
policiesFound = true;
}
}
@ -168,7 +172,7 @@ public class SecurityPolicy {
return new PolicySet(minPasswordLength, passwordMode, maxPasswordFails,
maxScreenLockTime, requireRemoteWipe, passwordExpirationDays, passwordHistory,
passwordComplexChars, requireEncryption);
passwordComplexChars, requireEncryption, requireEncryptionExternal);
} else {
return NO_POLICY_SET;
}
@ -229,6 +233,13 @@ public class SecurityPolicy {
return false;
}
}
if (policies.mRequireEncryptionExternal) {
// At this time, we only support "external encryption" when it is provided by virtue
// of emulating the external storage inside an encrypted device.
if (!policies.mRequireEncryption) return false;
if (Environment.isExternalStorageRemovable()) return false;
if (!Environment.isExternalStorageEmulated()) return false;
}
return true;
}
@ -254,7 +265,19 @@ public class SecurityPolicy {
result = new PolicySet(policies.mMinPasswordLength, policies.mPasswordMode,
policies.mMaxPasswordFails, policies.mMaxScreenLockTime,
policies.mRequireRemoteWipe, policies.mPasswordExpirationDays,
policies.mPasswordHistory, policies.mPasswordComplexChars, false);
policies.mPasswordHistory, policies.mPasswordComplexChars, false, false);
}
}
// At this time, we only support "external encryption" when it is provided by virtue
// of emulating the external storage inside an encrypted device.
if (policies.mRequireEncryptionExternal) {
if (Environment.isExternalStorageRemovable()
|| !Environment.isExternalStorageEmulated()) {
// Make new PolicySet w/o encryption
result = new PolicySet(policies.mMinPasswordLength, policies.mPasswordMode,
policies.mMaxPasswordFails, policies.mMaxScreenLockTime,
policies.mRequireRemoteWipe, policies.mPasswordExpirationDays,
policies.mPasswordHistory, policies.mPasswordComplexChars, false, false);
}
}
return result;
@ -375,6 +398,11 @@ public class SecurityPolicy {
reasons |= INACTIVE_NEED_ENCRYPTION;
}
}
// TODO: If we ever support external storage encryption as a first-class feature,
// it will need to be checked here. For now, if there is a policy request for
// external storage encryption, it's sufficient that we've activated internal
// storage encryption.
// password failures are counted locally - no test required here
// no check required for remote wipe (it's supported, if we're the admin)
@ -415,6 +443,10 @@ public class SecurityPolicy {
dpm.setPasswordMinimumNonLetter(mAdminName, policies.mPasswordComplexChars);
// encryption required
dpm.setStorageEncryption(mAdminName, policies.mRequireEncryption);
// TODO: If we ever support external storage encryption as a first-class feature,
// it will need to be set here. For now, if there is a policy request for
// external storage encryption, it's sufficient that we've activated internal
// storage encryption.
}
}

View File

@ -49,7 +49,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
private Context mMockContext;
private static final PolicySet EMPTY_POLICY_SET =
new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, false, 0, 0, 0, false);
new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, false, 0, 0, 0, false, false);
public SecurityPolicyTests() {
super(EmailProvider.class, EmailContent.AUTHORITY);
@ -114,28 +114,29 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
// We know that EMPTY_POLICY_SET doesn't generate an Exception or we wouldn't be here
// Try some illegal parameters
try {
new PolicySet(100, PolicySet.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0, false);
new PolicySet(100, PolicySet.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0, false, false);
fail("Too-long password allowed");
} catch (IllegalArgumentException e) {
}
try {
new PolicySet(0, PolicySet.PASSWORD_MODE_STRONG + 1, 0, 0, false, 0, 0, 0, false);
new PolicySet(0, PolicySet.PASSWORD_MODE_STRONG + 1, 0, 0, false, 0, 0, 0, false,
false);
fail("Illegal password mode allowed");
} catch (IllegalArgumentException e) {
}
PolicySet ps = new PolicySet(0, PolicySet.PASSWORD_MODE_SIMPLE, 0,
PolicySet.SCREEN_LOCK_TIME_MAX + 1, false, 0, 0, 0, false);
PolicySet.SCREEN_LOCK_TIME_MAX + 1, false, 0, 0, 0, false, false);
assertEquals(PolicySet.SCREEN_LOCK_TIME_MAX, ps.getMaxScreenLockTimeForTest());
ps = new PolicySet(0, PolicySet.PASSWORD_MODE_SIMPLE,
PolicySet.PASSWORD_MAX_FAILS_MAX + 1, 0, false, 0, 0, 0, false);
PolicySet.PASSWORD_MAX_FAILS_MAX + 1, 0, false, 0, 0, 0, false, false);
assertEquals(PolicySet.PASSWORD_MAX_FAILS_MAX, ps.getMaxPasswordFailsForTest());
// All password related fields should be zero when password mode is NONE
// Illegal values for these fields should be ignored
ps = new PolicySet(999/*length*/, PolicySet.PASSWORD_MODE_NONE,
999/*fails*/, 9999/*screenlock*/, false, 999/*expir*/, 999/*history*/,
999/*complex*/, false);
999/*complex*/, false, false);
assertEquals(0, ps.mMinPasswordLength);
assertEquals(0, ps.mMaxScreenLockTime);
assertEquals(0, ps.mMaxPasswordFails);
@ -145,7 +146,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
// With a simple password, we should set complex chars to zero
ps = new PolicySet(4/*length*/, PolicySet.PASSWORD_MODE_SIMPLE,
0, 0, false, 0, 0, 3/*complex*/, false);
0, 0, false, 0, 0, 3/*complex*/, false, false);
assertEquals(4, ps.mMinPasswordLength);
assertEquals(0, ps.mPasswordComplexChars);
}
@ -172,7 +173,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
// first test with partially-populated policies
Account a3 = ProviderTestUtils.setupAccount("sec-3", false, mMockContext);
PolicySet p3ain = new PolicySet(10, PolicySet.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0,
false);
false, false);
p3ain.writeAccount(a3, null, true, mMockContext);
PolicySet p3aout = sp.computeAggregatePolicy();
assertNotNull(p3aout);
@ -180,7 +181,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
// Repeat that test with fully-populated policies
PolicySet p3bin = new PolicySet(10, PolicySet.PASSWORD_MODE_SIMPLE, 15, 16, false, 6, 2, 3,
false);
false, false);
p3bin.writeAccount(a3, null, true, mMockContext);
PolicySet p3bout = sp.computeAggregatePolicy();
assertNotNull(p3bout);
@ -193,8 +194,9 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
// expiration - will not change because 0 (unspecified)
// max complex chars - max logic - will change
// encryption required - OR logic - will *not* change here because false
// encryption external req'd - OR logic - will *not* change here because false
PolicySet p4in = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 0, 5, 7,
false);
false, false);
Account a4 = ProviderTestUtils.setupAccount("sec-4", false, mMockContext);
p4in.writeAccount(a4, null, true, mMockContext);
PolicySet p4out = sp.computeAggregatePolicy();
@ -208,6 +210,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
assertEquals(7, p4out.mPasswordComplexChars);
assertFalse(p4out.mRequireRemoteWipe);
assertFalse(p4out.mRequireEncryption);
assertFalse(p4out.mRequireEncryptionExternal);
// 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
@ -216,8 +219,9 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
// expiration time - min logic - will change because lower here
// history & complex chars - will not change because 0 (unspecified)
// encryption required - OR logic - will change here because true
// encryption external req'd - OR logic - will *not* change here because false
PolicySet p5in = new PolicySet(4, PolicySet.PASSWORD_MODE_SIMPLE, 5, 6, true, 1, 0, 0,
true);
true, false);
Account a5 = ProviderTestUtils.setupAccount("sec-5", false, mMockContext);
p5in.writeAccount(a5, null, true, mMockContext);
PolicySet p5out = sp.computeAggregatePolicy();
@ -230,7 +234,17 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
assertEquals(5, p5out.mPasswordHistory);
assertEquals(7, p5out.mPasswordComplexChars);
assertTrue(p5out.mRequireRemoteWipe);
assertTrue(p5out.mRequireEncryption);
assertFalse(p5out.mRequireEncryptionExternal);
// add another account that continues to mutate fields
// encryption external req'd - OR logic - will change here because true
PolicySet p6in = new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, false, 0, 0, 0,
false, true);
Account a6 = ProviderTestUtils.setupAccount("sec-6", false, mMockContext);
p6in.writeAccount(a6, null, true, mMockContext);
PolicySet p6out = sp.computeAggregatePolicy();
assertNotNull(p6out);
assertTrue(p6out.mRequireEncryptionExternal);
}
/**
@ -260,7 +274,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
public void testFieldIsolation() {
// Check PASSWORD_LENGTH
PolicySet p = new PolicySet(PolicySet.PASSWORD_LENGTH_MAX, PolicySet.PASSWORD_MODE_SIMPLE,
0, 0, false, 0, 0 ,0, false);
0, 0, false, 0, 0 ,0, false, false);
assertEquals(PolicySet.PASSWORD_MODE_SIMPLE, p.mPasswordMode);
assertEquals(PolicySet.PASSWORD_LENGTH_MAX, p.mMinPasswordLength);
assertEquals(0, p.mMaxPasswordFails);
@ -270,9 +284,10 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
assertEquals(0, p.mPasswordComplexChars);
assertFalse(p.mRequireRemoteWipe);
assertFalse(p.mRequireEncryption);
assertFalse(p.mRequireEncryptionExternal);
// Check PASSWORD_MODE
p = new PolicySet(0, PolicySet.PASSWORD_MODE_STRONG, 0, 0, false, 0, 0, 0, false);
p = new PolicySet(0, PolicySet.PASSWORD_MODE_STRONG, 0, 0, false, 0, 0, 0, false, false);
assertEquals(PolicySet.PASSWORD_MODE_STRONG, p.mPasswordMode);
assertEquals(0, p.mMinPasswordLength);
assertEquals(0, p.mMaxPasswordFails);
@ -282,10 +297,11 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
assertEquals(0, p.mPasswordComplexChars);
assertFalse(p.mRequireRemoteWipe);
assertFalse(p.mRequireEncryption);
assertFalse(p.mRequireEncryptionExternal);
// 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,
false, 0, 0, 0, false);
false, 0, 0, 0, false, false);
assertEquals(PolicySet.PASSWORD_MODE_SIMPLE, p.mPasswordMode);
assertEquals(0, p.mMinPasswordLength);
assertEquals(PolicySet.PASSWORD_MAX_FAILS_MAX, p.mMaxPasswordFails);
@ -295,10 +311,11 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
assertEquals(0, p.mPasswordComplexChars);
assertFalse(p.mRequireRemoteWipe);
assertFalse(p.mRequireEncryption);
assertFalse(p.mRequireEncryptionExternal);
// 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,
false, 0, 0, 0, false);
false, 0, 0, 0, false, false);
assertEquals(PolicySet.PASSWORD_MODE_SIMPLE, p.mPasswordMode);
assertEquals(0, p.mMinPasswordLength);
assertEquals(0, p.mMaxPasswordFails);
@ -308,9 +325,10 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
assertEquals(0, p.mPasswordComplexChars);
assertFalse(p.mRequireRemoteWipe);
assertFalse(p.mRequireEncryption);
assertFalse(p.mRequireEncryptionExternal);
// Check REQUIRE_REMOTE_WIPE
p = new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, true, 0, 0, 0, false);
p = new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, true, 0, 0, 0, false, false);
assertEquals(PolicySet.PASSWORD_MODE_NONE, p.mPasswordMode);
assertEquals(0, p.mMinPasswordLength);
assertEquals(0, p.mMaxPasswordFails);
@ -320,10 +338,11 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
assertEquals(0, p.mPasswordComplexChars);
assertTrue(p.mRequireRemoteWipe);
assertFalse(p.mRequireEncryption);
assertFalse(p.mRequireEncryptionExternal);
// 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,
PolicySet.PASSWORD_EXPIRATION_MAX, 0, 0, false);
PolicySet.PASSWORD_EXPIRATION_MAX, 0, 0, false, false);
assertEquals(PolicySet.PASSWORD_MODE_SIMPLE, p.mPasswordMode);
assertEquals(0, p.mMinPasswordLength);
assertEquals(0, p.mMaxPasswordFails);
@ -333,10 +352,11 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
assertEquals(0, p.mPasswordComplexChars);
assertFalse(p.mRequireRemoteWipe);
assertFalse(p.mRequireEncryption);
assertFalse(p.mRequireEncryptionExternal);
// 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,
PolicySet.PASSWORD_HISTORY_MAX, 0, false);
PolicySet.PASSWORD_HISTORY_MAX, 0, false, false);
assertEquals(PolicySet.PASSWORD_MODE_SIMPLE, p.mPasswordMode);
assertEquals(0, p.mMinPasswordLength);
assertEquals(0, p.mMaxPasswordFails);
@ -346,10 +366,11 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
assertEquals(0, p.mPasswordComplexChars);
assertFalse(p.mRequireRemoteWipe);
assertFalse(p.mRequireEncryption);
assertFalse(p.mRequireEncryptionExternal);
// 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,
PolicySet.PASSWORD_COMPLEX_CHARS_MAX, false);
PolicySet.PASSWORD_COMPLEX_CHARS_MAX, false, false);
assertEquals(PolicySet.PASSWORD_MODE_STRONG, p.mPasswordMode);
assertEquals(0, p.mMinPasswordLength);
assertEquals(0, p.mMaxPasswordFails);
@ -359,9 +380,10 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
assertEquals(PolicySet.PASSWORD_COMPLEX_CHARS_MAX, p.mPasswordComplexChars);
assertFalse(p.mRequireRemoteWipe);
assertFalse(p.mRequireEncryption);
assertFalse(p.mRequireEncryptionExternal);
// Check REQUIRE_ENCRYPTION
p = new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, false, 0, 0, 0, true);
p = new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, false, 0, 0, 0, true, false);
assertEquals(PolicySet.PASSWORD_MODE_NONE, p.mPasswordMode);
assertEquals(0, p.mMinPasswordLength);
assertEquals(0, p.mMaxPasswordFails);
@ -371,6 +393,20 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
assertEquals(0, p.mPasswordComplexChars);
assertFalse(p.mRequireRemoteWipe);
assertTrue(p.mRequireEncryption);
assertFalse(p.mRequireEncryptionExternal);
// Check REQUIRE_ENCRYPTION_EXTERNAL
p = new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, false, 0, 0, 0, false, 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);
assertFalse(p.mRequireEncryption);
assertTrue(p.mRequireEncryptionExternal);
}
/**
@ -378,7 +414,8 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
*/
@SmallTest
public void testAccountEncoding() {
PolicySet p1 = new PolicySet(1, PolicySet.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false);
PolicySet p1 =
new PolicySet(1, PolicySet.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false);
Account a = new Account();
final String SYNC_KEY = "test_sync_key";
p1.writeAccount(a, SYNC_KEY, false, null);
@ -392,9 +429,12 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
*/
@SmallTest
public void testEquals() {
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, false);
PolicySet p3 = new PolicySet(2, PolicySet.PASSWORD_MODE_SIMPLE, 5, 6, true, 7, 8, 9, false);
PolicySet p1 =
new PolicySet(1, PolicySet.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false);
PolicySet p2 =
new PolicySet(1, PolicySet.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false);
PolicySet p3 =
new PolicySet(2, PolicySet.PASSWORD_MODE_SIMPLE, 5, 6, true, 7, 8, 9, false, false);
assertTrue(p1.equals(p2));
assertFalse(p2.equals(p3));
}
@ -444,12 +484,12 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
public void testDisableAdmin() {
Account a1 = ProviderTestUtils.setupAccount("disable-1", false, mMockContext);
PolicySet p1 = new PolicySet(10, PolicySet.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0,
false);
false, false);
p1.writeAccount(a1, "sync-key-1", true, mMockContext);
Account a2 = ProviderTestUtils.setupAccount("disable-2", false, mMockContext);
PolicySet p2 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0,
false);
false, false);
p2.writeAccount(a2, "sync-key-2", true, mMockContext);
Account a3 = ProviderTestUtils.setupAccount("disable-3", false, mMockContext);
@ -494,42 +534,40 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
* Test the scanner that finds expiring accounts
*/
public void testFindExpiringAccount() {
SecurityPolicy sp = getSecurityPolicy();
Account a1 = ProviderTestUtils.setupAccount("expiring-1", true, mMockContext);
// With no expiring accounts, this should return null.
long nextExpiringAccountId = sp.findShortestExpiration(mMockContext);
long nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext);
assertEquals(-1, nextExpiringAccountId);
// Add a single expiring account
Account a2 = ProviderTestUtils.setupAccount("expiring-2", false, mMockContext);
PolicySet p2 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0,
false);
false, false);
p2.writeAccount(a2, "sync-key-2", true, mMockContext);
// The expiring account should be returned
nextExpiringAccountId = sp.findShortestExpiration(mMockContext);
nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext);
assertEquals(a2.mId, nextExpiringAccountId);
// Add an account with a longer expiration
Account a3 = ProviderTestUtils.setupAccount("expiring-3", false, mMockContext);
PolicySet p3 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 60, 0, 0,
false);
false, false);
p3.writeAccount(a3, "sync-key-3", true, mMockContext);
// The original expiring account (a2) should be returned
nextExpiringAccountId = sp.findShortestExpiration(mMockContext);
nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext);
assertEquals(a2.mId, nextExpiringAccountId);
// Add an account with a shorter expiration
Account a4 = ProviderTestUtils.setupAccount("expiring-4", false, mMockContext);
PolicySet p4 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 15, 0, 0,
false);
false, false);
p4.writeAccount(a4, "sync-key-4", true, mMockContext);
// The new expiring account (a4) should be returned
nextExpiringAccountId = sp.findShortestExpiration(mMockContext);
nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext);
assertEquals(a4.mId, nextExpiringAccountId);
}
@ -555,7 +593,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
Account a1 = ProviderTestUtils.setupAccount("expired-1", true, mMockContext);
Account a2 = ProviderTestUtils.setupAccount("expired-2", false, mMockContext);
PolicySet p2 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0,
false);
false, false);
p2.writeAccount(a2, "sync-key-2", true, mMockContext);
// Add a mailbox & messages to each account
@ -581,7 +619,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
// Add 3rd account that really expires
Account a3 = ProviderTestUtils.setupAccount("expired-3", false, mMockContext);
PolicySet p3 = new PolicySet(20, PolicySet.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0,
false);
false, false);
p3.writeAccount(a3, "sync-key-3", true, mMockContext);
// Add mailbox & messages to 3rd account
@ -618,8 +656,12 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
* TODO inject a mock DPM so we can directly control & test all cases, no matter what device
*/
public void testClearUnsupportedPolicies() {
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, true);
PolicySet p1 =
new PolicySet(1, PolicySet.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false);
PolicySet p2 =
new PolicySet(1, PolicySet.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, true, false);
PolicySet p3 =
new PolicySet(1, PolicySet.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, true);
SecurityPolicy sp = getSecurityPolicy();
DevicePolicyManager dpm = sp.getDPM();
@ -628,16 +670,22 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
PolicySet p1Result = sp.clearUnsupportedPolicies(p1);
PolicySet p2Result = sp.clearUnsupportedPolicies(p2);
PolicySet p3Result = sp.clearUnsupportedPolicies(p3);
// No changes expected when encryptionRequested was false
// No changes expected when encryptionRequested bits were false
assertEquals(p1, p1Result);
if (hasEncryption) {
// No changes expected
// NOTE: TODO: Modify to check for external encryption cleared on devices that
// won't support it (e.g. having only unencrypted, removable storage.)
assertEquals(p2, p2Result);
assertEquals(p3, p3Result);
} else {
PolicySet p2Expect =
new PolicySet(1, PolicySet.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false);
assertEquals(p2Expect, p2Result);
// If encryption is unsupported, encryption policy bits are cleared
PolicySet policyExpect =
new PolicySet(1, PolicySet.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false);
assertEquals(policyExpect, p2Result);
assertEquals(policyExpect, p3Result);
}
}
}