Revert "Enable SD card encryption policy when emulated"

This is a manual cherry-pick of c379ebe372
This reverts commit 7fd14be804

The introduction of proper SD cards breaks the invariant that "external"
storage can be encrypted. Unfortunately, this means that accounts with
that policy bit set will have to be removed for now.

Accounts with the security policy set will be forced to go through
security provisioning on the next sync, using the regular mechanisms of
showing a notification with "Security update required", and then having
it fail. :(

Bug: 4466311
Change-Id: I68119b14f8d198779c2073296e228bc6772136ee
This commit is contained in:
Ben Komalo 2011-07-01 12:34:03 -07:00
parent 0268581de2
commit e76962b1b9
2 changed files with 31 additions and 64 deletions

View File

@ -35,7 +35,6 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Environment;
import android.util.Log;
/**
@ -99,7 +98,6 @@ 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.
@ -117,6 +115,10 @@ public class SecurityPolicy {
aggregate.mMaxScreenLockTime = Integer.MAX_VALUE;
aggregate.mRequireRemoteWipe = false;
aggregate.mRequireEncryption = false;
// This can never be supported at this time. It exists only for historic reasons where
// this was able to be supported prior to the introduction of proper removable storage
// support for external storage.
aggregate.mRequireEncryptionExternal = false;
Cursor c = mContext.getContentResolver().query(Policy.CONTENT_URI,
@ -153,7 +155,6 @@ public class SecurityPolicy {
}
aggregate.mRequireRemoteWipe |= policy.mRequireRemoteWipe;
aggregate.mRequireEncryption |= policy.mRequireEncryption;
aggregate.mRequireEncryptionExternal |= policy.mRequireEncryptionExternal;
aggregate.mDontAllowCamera |= policy.mDontAllowCamera;
policiesFound = true;
}
@ -240,13 +241,6 @@ public class SecurityPolicy {
return false;
}
}
if (policy.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 (!policy.mRequireEncryption) return false;
if (Environment.isExternalStorageRemovable()) return false;
if (!Environment.isExternalStorageEmulated()) return false;
}
// If we ever support devices that can't disable cameras for any reason, we should
// indicate as such in the mDontAllowCamera policy
@ -274,14 +268,6 @@ public class SecurityPolicy {
policy.mRequireEncryption = 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 (policy.mRequireEncryptionExternal) {
if (Environment.isExternalStorageRemovable()
|| !Environment.isExternalStorageEmulated()) {
policy.mRequireEncryptionExternal = false;
}
}
// If we ever support devices that can't disable cameras for any reason, we should
// clear the mDontAllowCamera policy
@ -425,11 +411,6 @@ 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)
@ -485,10 +466,6 @@ public class SecurityPolicy {
// encryption required
dpm.setStorageEncryption(mAdminName, aggregatePolicy.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

@ -105,7 +105,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
private Policy setupPolicy(int minPasswordLength, int passwordMode, int maxPasswordFails,
int maxScreenLockTime, boolean requireRemoteWipe, int passwordExpirationDays,
int passwordHistory, int passwordComplexChars, boolean requireEncryption,
boolean requireEncryptionExternal, boolean dontAllowCamera)
boolean dontAllowCamera)
throws IllegalArgumentException {
Policy policy = new Policy();
policy.mPasswordMinLength = minPasswordLength;
@ -117,7 +117,6 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
policy.mPasswordHistory = passwordHistory;
policy.mPasswordComplexChars = passwordComplexChars;
policy.mRequireEncryption = requireEncryption;
policy.mRequireEncryptionExternal = requireEncryptionExternal;
policy.mDontAllowCamera = dontAllowCamera;
return policy;
}
@ -140,7 +139,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
// first test with partially-populated policies
Account a3 = ProviderTestUtils.setupAccount("sec-3", true, mMockContext);
Policy p3ain = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0,
false, false, false);
false, false);
Policy.setAccountPolicy(mMockContext, a3, p3ain, null);
Policy p3aout = mSecurityPolicy.computeAggregatePolicy();
assertNotNull(p3aout);
@ -148,7 +147,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
// Repeat that test with fully-populated policies
Policy p3bin = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 15, 16, false, 6, 2, 3,
false, false, false);
false, false);
Policy.setAccountPolicy(mMockContext, a3, p3bin, null);
Policy p3bout = mSecurityPolicy.computeAggregatePolicy();
assertNotNull(p3bout);
@ -161,10 +160,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
// don't allow camera - OR logic - will change here because it's true
Policy p4in = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 0, 5, 7,
false, false, true);
false, true);
Account a4 = ProviderTestUtils.setupAccount("sec-4", true, mMockContext);
Policy.setAccountPolicy(mMockContext, a4, p4in, null);
Policy p4out = mSecurityPolicy.computeAggregatePolicy();
@ -188,10 +186,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
// don't allow camera - OR logic - will *not* change here because it's already true
Policy p5in = setupPolicy(4, Policy.PASSWORD_MODE_SIMPLE, 5, 6, true, 1, 0, 0,
true, false, false);
true, false);
Account a5 = ProviderTestUtils.setupAccount("sec-5", true, mMockContext);
Policy.setAccountPolicy(mMockContext, a5, p5in, null);
Policy p5out = mSecurityPolicy.computeAggregatePolicy();
@ -210,7 +207,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
// add another account that continues to mutate fields
// encryption external req'd - OR logic - will change here because true
Policy p6in = setupPolicy(0, Policy.PASSWORD_MODE_NONE, 0, 0, false, 0, 0, 0,
false, true, false);
false, false);
Account a6 = ProviderTestUtils.setupAccount("sec-6", true, mMockContext);
Policy.setAccountPolicy(mMockContext, a6, p6in, null);
Policy p6out = mSecurityPolicy.computeAggregatePolicy();
@ -246,13 +243,13 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
Account account = ProviderTestUtils.setupAccount("testaccount", true, mMockContext);
long accountId = account.mId;
Policy initial = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0,
false, false, false);
false, false);
Policy.setAccountPolicy(mMockContext, accountId, initial, null);
long oldKey = assertAccountPolicyConsistent(account.mId, 0);
Policy updated = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0,
false, false, false);
false, false);
Policy.setAccountPolicy(mMockContext, accountId, updated, null);
oldKey = assertAccountPolicyConsistent(account.mId, oldKey);
@ -270,13 +267,13 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
@SmallTest
public void testEquals() {
Policy p1 =
setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false, false);
setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false);
Policy p2 =
setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false, false);
setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false);
Policy p3 =
setupPolicy(2, Policy.PASSWORD_MODE_SIMPLE, 5, 6, true, 7, 8, 9, false, false, false);
setupPolicy(2, Policy.PASSWORD_MODE_SIMPLE, 5, 6, true, 7, 8, 9, false, false);
Policy p4 =
setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false, true);
setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, true);
assertTrue(p1.equals(p2));
assertFalse(p2.equals(p3));
assertFalse(p1.equals(p4));
@ -327,12 +324,12 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
public void testDisableAdmin() {
Account a1 = ProviderTestUtils.setupAccount("disable-1", true, mMockContext);
Policy p1 = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0,
false, false, false);
false, false);
Policy.setAccountPolicy(mMockContext, a1, p1, "security-sync-key-1");
Account a2 = ProviderTestUtils.setupAccount("disable-2", true, mMockContext);
Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0,
false, false, false);
false, false);
Policy.setAccountPolicy(mMockContext, a2, p2, "security-sync-key-2");
Account a3 = ProviderTestUtils.setupAccount("disable-3", true, mMockContext);
@ -388,7 +385,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
Account a2 =
ProviderTestUtils.setupAccount("expiring-2", true, mMockContext);
Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0,
false, false, true);
false, true);
Policy.setAccountPolicy(mMockContext, a2, p2, null);
// The expiring account should be returned
@ -398,7 +395,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
// Add an account with a longer expiration
Account a3 = ProviderTestUtils.setupAccount("expiring-3", true, mMockContext);
Policy p3 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 60, 0, 0,
false, false, true);
false, true);
Policy.setAccountPolicy(mMockContext, a3, p3, null);
// The original expiring account (a2) should be returned
@ -408,7 +405,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
// Add an account with a shorter expiration
Account a4 = ProviderTestUtils.setupAccount("expiring-4", true, mMockContext);
Policy p4 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 15, 0, 0,
false, false, true);
false, true);
Policy.setAccountPolicy(mMockContext, a4, p4, null);
// The new expiring account (a4) should be returned
@ -438,7 +435,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
Account a1 = ProviderTestUtils.setupAccount("expired-1", true, mMockContext);
Account a2 = ProviderTestUtils.setupAccount("expired-2", true, mMockContext);
Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0,
false, false, true);
false, true);
Policy.setAccountPolicy(mMockContext, a2, p2, null);
// Add a mailbox & messages to each account
@ -464,7 +461,7 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
// Add 3rd account that really expires
Account a3 = ProviderTestUtils.setupAccount("expired-3", true, mMockContext);
Policy p3 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0,
false, false, true);
false, true);
Policy.setAccountPolicy(mMockContext, a3, p3, null);
// Add mailbox & messages to 3rd account
@ -502,11 +499,9 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
*/
public void testClearUnsupportedPolicies() {
Policy p1 =
setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false, false);
setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false);
Policy p2 =
setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, true, false, false);
Policy p3 =
setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, true, false);
setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, true, false);
mSecurityPolicy = SecurityPolicy.getInstance(mMockContext);
DevicePolicyManager dpm = mSecurityPolicy.getDPM();
@ -515,23 +510,18 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
Policy p1Result = mSecurityPolicy.clearUnsupportedPolicies(p1);
Policy p2Result = mSecurityPolicy.clearUnsupportedPolicies(p2);
Policy p3Result = mSecurityPolicy.clearUnsupportedPolicies(p3);
// No changes expected when encryptionRequested bits were false
// No changes expected when encryptionRequested was 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 {
// If encryption is unsupported, encryption policy bits are cleared
Policy policyExpect =
setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false,
false, false);
false);
assertEquals(policyExpect, p2Result);
assertEquals(policyExpect, p3Result);
}
}
@ -541,25 +531,25 @@ public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
public void testGetDPManagerPasswordQuality() {
// Policy.PASSWORD_MODE_NONE -> DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED
Policy p1 = setupPolicy(0, Policy.PASSWORD_MODE_NONE,
0, 0, false, 0, 0, 0, false, false, false);
0, 0, false, 0, 0, 0, false, false);
assertEquals(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
p1.getDPManagerPasswordQuality());
// PASSWORD_MODE_SIMPLE -> PASSWORD_QUALITY_NUMERIC
Policy p2 = setupPolicy(4, Policy.PASSWORD_MODE_SIMPLE,
0, 0, false, 0, 0, 0, false, false, false);
0, 0, false, 0, 0, 0, false, false);
assertEquals(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
p2.getDPManagerPasswordQuality());
// PASSWORD_MODE_STRONG -> PASSWORD_QUALITY_ALPHANUMERIC
Policy p3 = setupPolicy(4, Policy.PASSWORD_MODE_STRONG,
0, 0, false, 0, 0, 0, false, false, false);
0, 0, false, 0, 0, 0, false, false);
assertEquals(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC,
p3.getDPManagerPasswordQuality());
// PASSWORD_MODE_STRONG + complex chars -> PASSWORD_QUALITY_COMPLEX
Policy p4 = setupPolicy(4, Policy.PASSWORD_MODE_STRONG,
0, 0, false, 0, 0 , 2, false, false, false);
0, 0, false, 0, 0 , 2, false, false);
assertEquals(DevicePolicyManager.PASSWORD_QUALITY_COMPLEX,
p4.getDPManagerPasswordQuality());
}