2010-01-27 01:24:15 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2010 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package com.android.email;
|
|
|
|
|
2011-06-22 01:16:26 +00:00
|
|
|
import android.app.admin.DevicePolicyManager;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.ContextWrapper;
|
|
|
|
import android.test.ProviderTestCase2;
|
|
|
|
import android.test.suitebuilder.annotation.MediumTest;
|
|
|
|
import android.test.suitebuilder.annotation.SmallTest;
|
2013-12-17 02:18:51 +00:00
|
|
|
import android.test.suitebuilder.annotation.Suppress;
|
2011-06-22 01:16:26 +00:00
|
|
|
|
2010-12-01 20:58:36 +00:00
|
|
|
import com.android.email.provider.ContentCache;
|
2011-02-09 02:54:56 +00:00
|
|
|
import com.android.email.provider.EmailProvider;
|
|
|
|
import com.android.email.provider.ProviderTestUtils;
|
2011-06-13 22:32:27 +00:00
|
|
|
import com.android.emailcommon.provider.Account;
|
2011-02-10 18:26:56 +00:00
|
|
|
import com.android.emailcommon.provider.EmailContent;
|
|
|
|
import com.android.emailcommon.provider.EmailContent.Message;
|
2011-05-14 00:26:27 +00:00
|
|
|
import com.android.emailcommon.provider.Mailbox;
|
2011-04-28 00:12:06 +00:00
|
|
|
import com.android.emailcommon.provider.Policy;
|
|
|
|
import com.android.emailcommon.service.LegacyPolicySet;
|
2010-01-27 01:24:15 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This is a series of unit tests for backup/restore of the SecurityPolicy class.
|
2010-08-02 20:47:23 +00:00
|
|
|
*
|
2010-06-09 23:18:57 +00:00
|
|
|
* You can run this entire test case with:
|
|
|
|
* runtest -c com.android.email.SecurityPolicyTests email
|
2010-01-27 01:24:15 +00:00
|
|
|
*/
|
2010-06-09 23:18:57 +00:00
|
|
|
|
2013-12-17 02:18:51 +00:00
|
|
|
// TODO: after b/12085240 gets fixed, we need to see if this test can be enabled
|
|
|
|
@Suppress
|
2010-01-27 01:24:15 +00:00
|
|
|
@MediumTest
|
|
|
|
public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
|
|
|
|
private Context mMockContext;
|
2011-04-28 00:12:06 +00:00
|
|
|
private SecurityPolicy mSecurityPolicy;
|
2010-02-02 00:48:16 +00:00
|
|
|
|
2010-01-27 01:24:15 +00:00
|
|
|
public SecurityPolicyTests() {
|
2011-02-11 23:05:17 +00:00
|
|
|
super(EmailProvider.class, EmailContent.AUTHORITY);
|
2010-01-27 01:24:15 +00:00
|
|
|
}
|
|
|
|
|
2011-04-28 00:12:06 +00:00
|
|
|
private static final Policy EMPTY_POLICY = new Policy();
|
|
|
|
|
2010-01-27 01:24:15 +00:00
|
|
|
@Override
|
|
|
|
protected void setUp() throws Exception {
|
|
|
|
super.setUp();
|
2011-04-28 00:12:06 +00:00
|
|
|
mMockContext = new MockContext2(getMockContext(), mContext);
|
2010-12-01 20:58:36 +00:00
|
|
|
// Invalidate all caches, since we reset the database for each test
|
Improve EmailContent caching...
* Guarantee that up to 16 Account (with HostAuths), and Policy rows
are always cached. Also, 6 commonly used Mailboxes per Account
(Inbox, Outbox, Drafts, Sent, Trash, and Search)
* Precache these rows when EmailProvider starts up
* Ensure that newly added, precachable rows are cached when created
* Clean up some inefficient/wrong caching code
* Fix a commonly called method in NotificationManager in which we
load a single Mailbox row using selection vs withAppendedId
* Confirm that we don't read from the database in typical use and
heavy message loading
* Add a special URI for finding mailbox by type (using the cache)
* Add special-case code for EmailContent.count(Account.CONTENT_URI)
which is used in a number of places (including on the UI thread)
and whose value is easily determined
* Add a special URI to get the default account id
* Confirm that all unit tests work
The goal here is to be able to load all Account, HostAuth, Policy,
and Mailbox objects (by id) without worrying about disk access.
There will still be a single disk read for uncommon Mailbox reads,
but this should be considered acceptable.
Change-Id: Ibc9aa7acc73185e360b0b6f3053b90a985e97210
TODO: Unit tests
2011-06-19 01:03:11 +00:00
|
|
|
ContentCache.invalidateAllCaches();
|
2010-01-27 01:24:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delete any dummy accounts we set up for this test
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
protected void tearDown() throws Exception {
|
|
|
|
super.tearDown();
|
|
|
|
}
|
|
|
|
|
2010-02-02 00:48:16 +00:00
|
|
|
/**
|
2010-06-04 22:26:11 +00:00
|
|
|
* Private context wrapper used to add back getPackageName() for these tests.
|
|
|
|
*
|
2011-01-19 19:40:48 +00:00
|
|
|
* This class also implements {@link Context} method(s) that are called during tests.
|
2010-02-02 00:48:16 +00:00
|
|
|
*/
|
|
|
|
private static class MockContext2 extends ContextWrapper {
|
|
|
|
|
|
|
|
private final Context mRealContext;
|
|
|
|
|
|
|
|
public MockContext2(Context mockContext, Context realContext) {
|
|
|
|
super(mockContext);
|
|
|
|
mRealContext = realContext;
|
|
|
|
}
|
|
|
|
|
2010-06-04 22:26:11 +00:00
|
|
|
@Override
|
|
|
|
public Context getApplicationContext() {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2010-02-02 00:48:16 +00:00
|
|
|
@Override
|
|
|
|
public String getPackageName() {
|
|
|
|
return mRealContext.getPackageName();
|
|
|
|
}
|
2011-01-19 19:40:48 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public Object getSystemService(String name) {
|
|
|
|
return mRealContext.getSystemService(name);
|
|
|
|
}
|
2010-02-02 00:48:16 +00:00
|
|
|
}
|
|
|
|
|
2010-01-27 01:24:15 +00:00
|
|
|
/**
|
2011-04-28 00:12:06 +00:00
|
|
|
* Create a Policy using the arguments formerly used to create a PolicySet; this minimizes the
|
|
|
|
* changes needed for re-using the PolicySet unit test logic
|
2010-01-27 01:24:15 +00:00
|
|
|
*/
|
2011-04-28 00:12:06 +00:00
|
|
|
private Policy setupPolicy(int minPasswordLength, int passwordMode, int maxPasswordFails,
|
|
|
|
int maxScreenLockTime, boolean requireRemoteWipe, int passwordExpirationDays,
|
|
|
|
int passwordHistory, int passwordComplexChars, boolean requireEncryption,
|
2011-07-01 19:34:03 +00:00
|
|
|
boolean dontAllowCamera)
|
2011-05-06 21:57:47 +00:00
|
|
|
throws IllegalArgumentException {
|
2011-04-28 00:12:06 +00:00
|
|
|
Policy policy = new Policy();
|
|
|
|
policy.mPasswordMinLength = minPasswordLength;
|
|
|
|
policy.mPasswordMode = passwordMode;
|
|
|
|
policy.mPasswordMaxFails = maxPasswordFails;
|
|
|
|
policy.mMaxScreenLockTime = maxScreenLockTime;
|
|
|
|
policy.mRequireRemoteWipe = requireRemoteWipe;
|
|
|
|
policy.mPasswordExpirationDays = passwordExpirationDays;
|
|
|
|
policy.mPasswordHistory = passwordHistory;
|
|
|
|
policy.mPasswordComplexChars = passwordComplexChars;
|
|
|
|
policy.mRequireEncryption = requireEncryption;
|
2011-05-06 21:57:47 +00:00
|
|
|
policy.mDontAllowCamera = dontAllowCamera;
|
2011-04-28 00:12:06 +00:00
|
|
|
return policy;
|
2010-06-14 19:24:02 +00:00
|
|
|
}
|
|
|
|
|
2010-01-27 01:24:15 +00:00
|
|
|
/**
|
|
|
|
* Test business logic of aggregating accounts with policies
|
|
|
|
*/
|
|
|
|
public void testAggregator() {
|
2011-04-28 00:12:06 +00:00
|
|
|
mSecurityPolicy = SecurityPolicy.getInstance(mMockContext);
|
2010-01-27 01:24:15 +00:00
|
|
|
|
2010-02-02 00:48:16 +00:00
|
|
|
// with no accounts, should return empty set
|
2011-04-28 00:12:06 +00:00
|
|
|
assertEquals(EMPTY_POLICY, mSecurityPolicy.computeAggregatePolicy());
|
2010-01-27 01:24:15 +00:00
|
|
|
|
2010-02-02 00:48:16 +00:00
|
|
|
// with accounts having no security, empty set
|
2011-04-28 00:12:06 +00:00
|
|
|
ProviderTestUtils.setupAccount("no-sec-1", true, mMockContext);
|
|
|
|
ProviderTestUtils.setupAccount("no-sec-2", true, mMockContext);
|
|
|
|
assertEquals(EMPTY_POLICY, mSecurityPolicy.computeAggregatePolicy());
|
2010-01-27 01:24:15 +00:00
|
|
|
|
|
|
|
// with a single account in security mode, should return same security as in account
|
2010-02-05 19:10:39 +00:00
|
|
|
// first test with partially-populated policies
|
2011-04-28 00:12:06 +00:00
|
|
|
Account a3 = ProviderTestUtils.setupAccount("sec-3", true, mMockContext);
|
|
|
|
Policy p3ain = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0,
|
2011-07-01 19:34:03 +00:00
|
|
|
false, false);
|
2013-11-27 04:41:53 +00:00
|
|
|
SecurityPolicy.setAccountPolicy(mMockContext, a3, p3ain, null);
|
2011-04-28 00:12:06 +00:00
|
|
|
Policy p3aout = mSecurityPolicy.computeAggregatePolicy();
|
2010-02-05 19:10:39 +00:00
|
|
|
assertNotNull(p3aout);
|
|
|
|
assertEquals(p3ain, p3aout);
|
|
|
|
|
|
|
|
// Repeat that test with fully-populated policies
|
2011-04-28 00:12:06 +00:00
|
|
|
Policy p3bin = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 15, 16, false, 6, 2, 3,
|
2011-07-01 19:34:03 +00:00
|
|
|
false, false);
|
2013-11-27 04:41:53 +00:00
|
|
|
SecurityPolicy.setAccountPolicy(mMockContext, a3, p3bin, null);
|
2011-04-28 00:12:06 +00:00
|
|
|
Policy p3bout = mSecurityPolicy.computeAggregatePolicy();
|
2010-02-05 19:10:39 +00:00
|
|
|
assertNotNull(p3bout);
|
|
|
|
assertEquals(p3bin, p3bout);
|
2010-01-27 01:24:15 +00:00
|
|
|
|
|
|
|
// add another account which mixes it up (some fields will change, others will not)
|
|
|
|
// pw length and pw mode - max logic - will change because larger #s here
|
|
|
|
// fail count and lock timer - min logic - will *not* change because larger #s here
|
|
|
|
// wipe required - OR logic - will *not* change here because false
|
2010-12-01 20:58:36 +00:00
|
|
|
// expiration - will not change because 0 (unspecified)
|
|
|
|
// max complex chars - max logic - will change
|
2011-01-13 21:12:55 +00:00
|
|
|
// encryption required - OR logic - will *not* change here because false
|
2011-05-06 21:57:47 +00:00
|
|
|
// don't allow camera - OR logic - will change here because it's true
|
2011-04-28 00:12:06 +00:00
|
|
|
Policy p4in = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 0, 5, 7,
|
2011-07-01 19:34:03 +00:00
|
|
|
false, true);
|
2011-04-28 00:12:06 +00:00
|
|
|
Account a4 = ProviderTestUtils.setupAccount("sec-4", true, mMockContext);
|
2013-11-27 04:41:53 +00:00
|
|
|
SecurityPolicy.setAccountPolicy(mMockContext, a4, p4in, null);
|
2011-04-28 00:12:06 +00:00
|
|
|
Policy p4out = mSecurityPolicy.computeAggregatePolicy();
|
2010-01-27 01:24:15 +00:00
|
|
|
assertNotNull(p4out);
|
2011-04-28 00:12:06 +00:00
|
|
|
assertEquals(20, p4out.mPasswordMinLength);
|
|
|
|
assertEquals(Policy.PASSWORD_MODE_STRONG, p4out.mPasswordMode);
|
|
|
|
assertEquals(15, p4out.mPasswordMaxFails);
|
2010-01-27 01:24:15 +00:00
|
|
|
assertEquals(16, p4out.mMaxScreenLockTime);
|
2010-12-01 20:58:36 +00:00
|
|
|
assertEquals(6, p4out.mPasswordExpirationDays);
|
2010-06-09 23:18:57 +00:00
|
|
|
assertEquals(5, p4out.mPasswordHistory);
|
|
|
|
assertEquals(7, p4out.mPasswordComplexChars);
|
2010-01-27 01:24:15 +00:00
|
|
|
assertFalse(p4out.mRequireRemoteWipe);
|
2011-01-13 21:12:55 +00:00
|
|
|
assertFalse(p4out.mRequireEncryption);
|
2011-03-03 00:41:05 +00:00
|
|
|
assertFalse(p4out.mRequireEncryptionExternal);
|
2011-05-06 21:57:47 +00:00
|
|
|
assertTrue(p4out.mDontAllowCamera);
|
2010-01-27 01:24:15 +00:00
|
|
|
|
|
|
|
// 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
|
|
|
|
// fail count and lock timer - min logic - will change because smaller #s here
|
|
|
|
// wipe required - OR logic - will change here because true
|
2010-12-01 20:58:36 +00:00
|
|
|
// expiration time - min logic - will change because lower here
|
|
|
|
// history & complex chars - will not change because 0 (unspecified)
|
2011-01-13 21:12:55 +00:00
|
|
|
// encryption required - OR logic - will change here because true
|
2011-05-06 21:57:47 +00:00
|
|
|
// don't allow camera - OR logic - will *not* change here because it's already true
|
2011-04-28 00:12:06 +00:00
|
|
|
Policy p5in = setupPolicy(4, Policy.PASSWORD_MODE_SIMPLE, 5, 6, true, 1, 0, 0,
|
2011-07-01 19:34:03 +00:00
|
|
|
true, false);
|
2011-04-28 00:12:06 +00:00
|
|
|
Account a5 = ProviderTestUtils.setupAccount("sec-5", true, mMockContext);
|
2013-11-27 04:41:53 +00:00
|
|
|
SecurityPolicy.setAccountPolicy(mMockContext, a5, p5in, null);
|
2011-04-28 00:12:06 +00:00
|
|
|
Policy p5out = mSecurityPolicy.computeAggregatePolicy();
|
2010-01-27 01:24:15 +00:00
|
|
|
assertNotNull(p5out);
|
2011-04-28 00:12:06 +00:00
|
|
|
assertEquals(20, p5out.mPasswordMinLength);
|
|
|
|
assertEquals(Policy.PASSWORD_MODE_STRONG, p5out.mPasswordMode);
|
|
|
|
assertEquals(5, p5out.mPasswordMaxFails);
|
2010-01-27 01:24:15 +00:00
|
|
|
assertEquals(6, p5out.mMaxScreenLockTime);
|
2010-12-01 20:58:36 +00:00
|
|
|
assertEquals(1, p5out.mPasswordExpirationDays);
|
2011-01-13 21:12:55 +00:00
|
|
|
assertEquals(5, p5out.mPasswordHistory);
|
|
|
|
assertEquals(7, p5out.mPasswordComplexChars);
|
2010-01-27 01:24:15 +00:00
|
|
|
assertTrue(p5out.mRequireRemoteWipe);
|
2011-03-03 00:41:05 +00:00
|
|
|
assertFalse(p5out.mRequireEncryptionExternal);
|
2011-05-06 21:57:47 +00:00
|
|
|
assertTrue(p5out.mDontAllowCamera);
|
2010-01-27 01:24:15 +00:00
|
|
|
}
|
|
|
|
|
2011-06-22 01:16:26 +00:00
|
|
|
private long assertAccountPolicyConsistent(long accountId, long oldKey) {
|
|
|
|
Account account = Account.restoreAccountWithId(mMockContext, accountId);
|
|
|
|
long policyKey = account.mPolicyKey;
|
|
|
|
|
|
|
|
assertTrue(policyKey > 0);
|
|
|
|
|
|
|
|
// Found a policy. Ensure it matches.
|
|
|
|
Policy policy = Policy.restorePolicyWithId(mMockContext, policyKey);
|
|
|
|
assertNotNull(policy);
|
|
|
|
assertEquals(account.mPolicyKey, policy.mId);
|
|
|
|
assertEquals(
|
|
|
|
accountId,
|
|
|
|
Policy.getAccountIdWithPolicyKey(mMockContext, policy.mId));
|
|
|
|
|
|
|
|
// Assert the old one isn't there.
|
|
|
|
if (oldKey > 0) {
|
|
|
|
assertNull("old policy not cleaned up",
|
|
|
|
Policy.restorePolicyWithId(mMockContext, oldKey));
|
|
|
|
}
|
|
|
|
|
|
|
|
return policyKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
@SmallTest
|
|
|
|
public void testSettingAccountPolicy() {
|
|
|
|
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,
|
2011-07-01 19:34:03 +00:00
|
|
|
false, false);
|
2013-11-27 04:41:53 +00:00
|
|
|
SecurityPolicy.setAccountPolicy(mMockContext, account, initial, null);
|
2011-06-22 01:16:26 +00:00
|
|
|
|
|
|
|
long oldKey = assertAccountPolicyConsistent(account.mId, 0);
|
|
|
|
|
|
|
|
Policy updated = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0,
|
2011-07-01 19:34:03 +00:00
|
|
|
false, false);
|
2013-11-27 04:41:53 +00:00
|
|
|
SecurityPolicy.setAccountPolicy(mMockContext, account, updated, null);
|
2011-06-22 01:16:26 +00:00
|
|
|
oldKey = assertAccountPolicyConsistent(account.mId, oldKey);
|
|
|
|
|
|
|
|
// Remove the policy
|
2013-11-27 04:41:53 +00:00
|
|
|
SecurityPolicy.clearAccountPolicy(
|
2011-06-22 01:16:26 +00:00
|
|
|
mMockContext, Account.restoreAccountWithId(mMockContext, accountId));
|
|
|
|
assertNull("old policy not cleaned up",
|
|
|
|
Policy.restorePolicyWithId(mMockContext, oldKey));
|
|
|
|
}
|
|
|
|
|
2010-01-27 01:24:15 +00:00
|
|
|
/**
|
2010-06-09 23:18:57 +00:00
|
|
|
* Test equality. Note, the tests for inequality are poor, as each field should
|
2010-01-27 01:24:15 +00:00
|
|
|
* be tested individually.
|
|
|
|
*/
|
|
|
|
@SmallTest
|
2010-06-09 23:18:57 +00:00
|
|
|
public void testEquals() {
|
2011-04-28 00:12:06 +00:00
|
|
|
Policy p1 =
|
2011-07-01 19:34:03 +00:00
|
|
|
setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false);
|
2011-04-28 00:12:06 +00:00
|
|
|
Policy p2 =
|
2011-07-01 19:34:03 +00:00
|
|
|
setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false);
|
2011-04-28 00:12:06 +00:00
|
|
|
Policy p3 =
|
2011-07-01 19:34:03 +00:00
|
|
|
setupPolicy(2, Policy.PASSWORD_MODE_SIMPLE, 5, 6, true, 7, 8, 9, false, false);
|
2011-05-06 21:57:47 +00:00
|
|
|
Policy p4 =
|
2011-07-01 19:34:03 +00:00
|
|
|
setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, true);
|
2010-01-27 01:24:15 +00:00
|
|
|
assertTrue(p1.equals(p2));
|
|
|
|
assertFalse(p2.equals(p3));
|
2011-05-06 21:57:47 +00:00
|
|
|
assertFalse(p1.equals(p4));
|
2010-01-27 01:24:15 +00:00
|
|
|
}
|
|
|
|
|
2010-02-09 01:42:42 +00:00
|
|
|
/**
|
|
|
|
* Test the API to set/clear policy hold flags in an account
|
|
|
|
*/
|
|
|
|
public void testSetClearHoldFlag() {
|
|
|
|
Account a2 = ProviderTestUtils.setupAccount("holdflag-2", false, mMockContext);
|
2013-11-27 04:41:53 +00:00
|
|
|
a2.mFlags = Account.FLAGS_SYNC_DISABLED | Account.FLAGS_SECURITY_HOLD;
|
2010-02-09 01:42:42 +00:00
|
|
|
a2.save(mMockContext);
|
|
|
|
|
|
|
|
// confirm set until cleared
|
|
|
|
Account a2a = Account.restoreAccountWithId(mMockContext, a2.mId);
|
2013-11-27 04:41:53 +00:00
|
|
|
assertEquals(Account.FLAGS_SYNC_DISABLED | Account.FLAGS_SECURITY_HOLD, a2a.mFlags);
|
|
|
|
|
|
|
|
// set account hold flag off
|
2011-04-28 00:12:06 +00:00
|
|
|
SecurityPolicy.setAccountHoldFlag(mMockContext, a2, false);
|
2013-11-27 04:41:53 +00:00
|
|
|
assertEquals(Account.FLAGS_SYNC_DISABLED, a2.mFlags);
|
|
|
|
|
|
|
|
// confirm account hold flag set
|
2010-02-09 01:42:42 +00:00
|
|
|
Account a2b = Account.restoreAccountWithId(mMockContext, a2.mId);
|
2013-11-27 04:41:53 +00:00
|
|
|
assertEquals(Account.FLAGS_SYNC_DISABLED, a2b.mFlags);
|
2010-02-09 01:42:42 +00:00
|
|
|
}
|
|
|
|
|
2010-02-16 22:33:08 +00:00
|
|
|
/**
|
|
|
|
* Test the response to disabling DeviceAdmin status
|
|
|
|
*/
|
|
|
|
public void testDisableAdmin() {
|
2011-04-28 00:12:06 +00:00
|
|
|
Account a1 = ProviderTestUtils.setupAccount("disable-1", true, mMockContext);
|
|
|
|
Policy p1 = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0,
|
2011-07-01 19:34:03 +00:00
|
|
|
false, false);
|
2013-11-27 04:41:53 +00:00
|
|
|
SecurityPolicy.setAccountPolicy(mMockContext, a1, p1, "security-sync-key-1");
|
2010-02-16 22:33:08 +00:00
|
|
|
|
2011-04-28 00:12:06 +00:00
|
|
|
Account a2 = ProviderTestUtils.setupAccount("disable-2", true, mMockContext);
|
|
|
|
Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0,
|
2011-07-01 19:34:03 +00:00
|
|
|
false, false);
|
2013-11-27 04:41:53 +00:00
|
|
|
SecurityPolicy.setAccountPolicy(mMockContext, a2, p2, "security-sync-key-2");
|
2010-02-16 22:33:08 +00:00
|
|
|
|
2011-04-28 00:12:06 +00:00
|
|
|
Account a3 = ProviderTestUtils.setupAccount("disable-3", true, mMockContext);
|
2013-11-27 04:41:53 +00:00
|
|
|
SecurityPolicy.clearAccountPolicy(mMockContext, a3);
|
2010-02-16 22:33:08 +00:00
|
|
|
|
2011-04-28 00:12:06 +00:00
|
|
|
mSecurityPolicy = SecurityPolicy.getInstance(mMockContext);
|
2010-02-16 22:33:08 +00:00
|
|
|
|
2011-04-28 00:12:06 +00:00
|
|
|
// Confirm that "enabling" device admin does not change security status (policy & sync key)
|
|
|
|
Policy before = mSecurityPolicy.getAggregatePolicy();
|
|
|
|
mSecurityPolicy.onAdminEnabled(true); // "enabled" should not change anything
|
|
|
|
Policy after1 = mSecurityPolicy.getAggregatePolicy();
|
2010-02-16 22:33:08 +00:00
|
|
|
assertEquals(before, after1);
|
|
|
|
Account a1a = Account.restoreAccountWithId(mMockContext, a1.mId);
|
|
|
|
assertNotNull(a1a.mSecuritySyncKey);
|
2011-04-28 00:12:06 +00:00
|
|
|
assertTrue(a1a.mPolicyKey > 0);
|
2010-02-16 22:33:08 +00:00
|
|
|
Account a2a = Account.restoreAccountWithId(mMockContext, a2.mId);
|
|
|
|
assertNotNull(a2a.mSecuritySyncKey);
|
2011-04-28 00:12:06 +00:00
|
|
|
assertTrue(a2a.mPolicyKey > 0);
|
2010-02-16 22:33:08 +00:00
|
|
|
Account a3a = Account.restoreAccountWithId(mMockContext, a3.mId);
|
|
|
|
assertNull(a3a.mSecuritySyncKey);
|
2011-04-28 00:12:06 +00:00
|
|
|
assertTrue(a3a.mPolicyKey == 0);
|
2010-02-16 22:33:08 +00:00
|
|
|
|
2011-07-19 00:33:38 +00:00
|
|
|
mSecurityPolicy.deleteSecuredAccounts(mMockContext);
|
|
|
|
Policy after2 = mSecurityPolicy.getAggregatePolicy();
|
|
|
|
assertEquals(EMPTY_POLICY, after2);
|
|
|
|
Account a1b = Account.restoreAccountWithId(mMockContext, a1.mId);
|
|
|
|
assertNull(a1b);
|
|
|
|
Account a2b = Account.restoreAccountWithId(mMockContext, a2.mId);
|
|
|
|
assertNull(a2b);
|
|
|
|
Account a3b = Account.restoreAccountWithId(mMockContext, a3.mId);
|
|
|
|
assertNull(a3b.mSecuritySyncKey);
|
2010-12-01 20:58:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test the scanner that finds expiring accounts
|
|
|
|
*/
|
|
|
|
public void testFindExpiringAccount() {
|
2011-04-28 00:12:06 +00:00
|
|
|
ProviderTestUtils.setupAccount("expiring-1", true, mMockContext);
|
2010-12-01 20:58:36 +00:00
|
|
|
|
|
|
|
// With no expiring accounts, this should return null.
|
2011-03-03 00:41:05 +00:00
|
|
|
long nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext);
|
2010-12-01 20:58:36 +00:00
|
|
|
assertEquals(-1, nextExpiringAccountId);
|
|
|
|
|
|
|
|
// Add a single expiring account
|
2011-04-28 00:12:06 +00:00
|
|
|
Account a2 =
|
|
|
|
ProviderTestUtils.setupAccount("expiring-2", true, mMockContext);
|
|
|
|
Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0,
|
2011-07-01 19:34:03 +00:00
|
|
|
false, true);
|
2013-11-27 04:41:53 +00:00
|
|
|
SecurityPolicy.setAccountPolicy(mMockContext, a2, p2, null);
|
2010-12-01 20:58:36 +00:00
|
|
|
|
|
|
|
// The expiring account should be returned
|
2011-03-03 00:41:05 +00:00
|
|
|
nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext);
|
2010-12-01 20:58:36 +00:00
|
|
|
assertEquals(a2.mId, nextExpiringAccountId);
|
|
|
|
|
|
|
|
// Add an account with a longer expiration
|
2011-04-28 00:12:06 +00:00
|
|
|
Account a3 = ProviderTestUtils.setupAccount("expiring-3", true, mMockContext);
|
|
|
|
Policy p3 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 60, 0, 0,
|
2011-07-01 19:34:03 +00:00
|
|
|
false, true);
|
2013-11-27 04:41:53 +00:00
|
|
|
SecurityPolicy.setAccountPolicy(mMockContext, a3, p3, null);
|
2010-12-01 20:58:36 +00:00
|
|
|
|
|
|
|
// The original expiring account (a2) should be returned
|
2011-03-03 00:41:05 +00:00
|
|
|
nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext);
|
2010-12-01 20:58:36 +00:00
|
|
|
assertEquals(a2.mId, nextExpiringAccountId);
|
|
|
|
|
|
|
|
// Add an account with a shorter expiration
|
2011-04-28 00:12:06 +00:00
|
|
|
Account a4 = ProviderTestUtils.setupAccount("expiring-4", true, mMockContext);
|
|
|
|
Policy p4 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 15, 0, 0,
|
2011-07-01 19:34:03 +00:00
|
|
|
false, true);
|
2013-11-27 04:41:53 +00:00
|
|
|
SecurityPolicy.setAccountPolicy(mMockContext, a4, p4, null);
|
2010-12-01 20:58:36 +00:00
|
|
|
|
|
|
|
// The new expiring account (a4) should be returned
|
2011-03-03 00:41:05 +00:00
|
|
|
nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext);
|
2010-12-01 20:58:36 +00:00
|
|
|
assertEquals(a4.mId, nextExpiringAccountId);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test the scanner that wipes expiring accounts
|
|
|
|
*/
|
|
|
|
public void testWipeExpiringAccounts() {
|
2011-04-28 00:12:06 +00:00
|
|
|
mSecurityPolicy = SecurityPolicy.getInstance(mMockContext);
|
2010-12-01 20:58:36 +00:00
|
|
|
|
|
|
|
// Two accounts - a1 is normal, a2 has security (but no expiration)
|
|
|
|
Account a1 = ProviderTestUtils.setupAccount("expired-1", true, mMockContext);
|
2011-04-28 00:12:06 +00:00
|
|
|
Account a2 = ProviderTestUtils.setupAccount("expired-2", true, mMockContext);
|
|
|
|
Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0,
|
2011-07-01 19:34:03 +00:00
|
|
|
false, true);
|
2013-11-27 04:41:53 +00:00
|
|
|
SecurityPolicy.setAccountPolicy(mMockContext, a2, p2, null);
|
2010-12-01 20:58:36 +00:00
|
|
|
|
|
|
|
// Add a mailbox & messages to each account
|
|
|
|
long account1Id = a1.mId;
|
|
|
|
long account2Id = a2.mId;
|
|
|
|
Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext);
|
|
|
|
long box1Id = box1.mId;
|
|
|
|
ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, true, mMockContext);
|
|
|
|
ProviderTestUtils.setupMessage("message2", account1Id, box1Id, false, true, mMockContext);
|
|
|
|
Mailbox box2 = ProviderTestUtils.setupMailbox("box2", account2Id, true, mMockContext);
|
|
|
|
long box2Id = box2.mId;
|
|
|
|
ProviderTestUtils.setupMessage("message3", account2Id, box2Id, false, true, mMockContext);
|
|
|
|
ProviderTestUtils.setupMessage("message4", account2Id, box2Id, false, true, mMockContext);
|
|
|
|
|
|
|
|
// Run the expiration code - should do nothing
|
2013-11-27 04:41:53 +00:00
|
|
|
boolean wiped = SecurityPolicy.wipeExpiredAccounts(mMockContext);
|
2010-12-01 20:58:36 +00:00
|
|
|
assertFalse(wiped);
|
|
|
|
// check mailboxes & messages not wiped
|
|
|
|
assertEquals(2, EmailContent.count(mMockContext, Account.CONTENT_URI));
|
|
|
|
assertEquals(2, EmailContent.count(mMockContext, Mailbox.CONTENT_URI));
|
|
|
|
assertEquals(4, EmailContent.count(mMockContext, Message.CONTENT_URI));
|
|
|
|
|
|
|
|
// Add 3rd account that really expires
|
2011-04-28 00:12:06 +00:00
|
|
|
Account a3 = ProviderTestUtils.setupAccount("expired-3", true, mMockContext);
|
|
|
|
Policy p3 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0,
|
2011-07-01 19:34:03 +00:00
|
|
|
false, true);
|
2013-11-27 04:41:53 +00:00
|
|
|
SecurityPolicy.setAccountPolicy(mMockContext, a3, p3, null);
|
2010-12-01 20:58:36 +00:00
|
|
|
|
|
|
|
// Add mailbox & messages to 3rd account
|
|
|
|
long account3Id = a3.mId;
|
|
|
|
Mailbox box3 = ProviderTestUtils.setupMailbox("box3", account3Id, true, mMockContext);
|
|
|
|
long box3Id = box3.mId;
|
|
|
|
ProviderTestUtils.setupMessage("message5", account3Id, box3Id, false, true, mMockContext);
|
|
|
|
ProviderTestUtils.setupMessage("message6", account3Id, box3Id, false, true, mMockContext);
|
|
|
|
|
|
|
|
// check new counts
|
|
|
|
assertEquals(3, EmailContent.count(mMockContext, Account.CONTENT_URI));
|
|
|
|
assertEquals(3, EmailContent.count(mMockContext, Mailbox.CONTENT_URI));
|
|
|
|
assertEquals(6, EmailContent.count(mMockContext, Message.CONTENT_URI));
|
|
|
|
|
|
|
|
// Run the expiration code - wipe acct #3
|
2013-11-27 04:41:53 +00:00
|
|
|
wiped = SecurityPolicy.wipeExpiredAccounts(mMockContext);
|
2010-12-01 20:58:36 +00:00
|
|
|
assertTrue(wiped);
|
|
|
|
// check new counts - account survives but data is wiped
|
|
|
|
assertEquals(3, EmailContent.count(mMockContext, Account.CONTENT_URI));
|
|
|
|
assertEquals(2, EmailContent.count(mMockContext, Mailbox.CONTENT_URI));
|
|
|
|
assertEquals(4, EmailContent.count(mMockContext, Message.CONTENT_URI));
|
|
|
|
|
|
|
|
// Check security hold states - only #3 should be in hold
|
|
|
|
Account account = Account.restoreAccountWithId(mMockContext, account1Id);
|
|
|
|
assertEquals(0, account.mFlags & Account.FLAGS_SECURITY_HOLD);
|
|
|
|
account = Account.restoreAccountWithId(mMockContext, account2Id);
|
|
|
|
assertEquals(0, account.mFlags & Account.FLAGS_SECURITY_HOLD);
|
|
|
|
account = Account.restoreAccountWithId(mMockContext, account3Id);
|
|
|
|
assertEquals(Account.FLAGS_SECURITY_HOLD, account.mFlags & Account.FLAGS_SECURITY_HOLD);
|
|
|
|
}
|
2011-01-19 19:40:48 +00:00
|
|
|
|
2011-03-16 16:48:08 +00:00
|
|
|
/**
|
|
|
|
* Test the code that converts from exchange-style quality to DPM/Lockscreen style quality.
|
|
|
|
*/
|
|
|
|
public void testGetDPManagerPasswordQuality() {
|
2011-04-28 00:12:06 +00:00
|
|
|
// Policy.PASSWORD_MODE_NONE -> DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED
|
|
|
|
Policy p1 = setupPolicy(0, Policy.PASSWORD_MODE_NONE,
|
2011-07-01 19:34:03 +00:00
|
|
|
0, 0, false, 0, 0, 0, false, false);
|
2011-03-16 16:48:08 +00:00
|
|
|
assertEquals(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
|
|
|
|
p1.getDPManagerPasswordQuality());
|
|
|
|
|
|
|
|
// PASSWORD_MODE_SIMPLE -> PASSWORD_QUALITY_NUMERIC
|
2011-04-28 00:12:06 +00:00
|
|
|
Policy p2 = setupPolicy(4, Policy.PASSWORD_MODE_SIMPLE,
|
2011-07-01 19:34:03 +00:00
|
|
|
0, 0, false, 0, 0, 0, false, false);
|
2011-03-16 16:48:08 +00:00
|
|
|
assertEquals(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
|
|
|
|
p2.getDPManagerPasswordQuality());
|
|
|
|
|
|
|
|
// PASSWORD_MODE_STRONG -> PASSWORD_QUALITY_ALPHANUMERIC
|
2011-04-28 00:12:06 +00:00
|
|
|
Policy p3 = setupPolicy(4, Policy.PASSWORD_MODE_STRONG,
|
2011-07-01 19:34:03 +00:00
|
|
|
0, 0, false, 0, 0, 0, false, false);
|
2011-03-16 16:48:08 +00:00
|
|
|
assertEquals(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC,
|
|
|
|
p3.getDPManagerPasswordQuality());
|
|
|
|
|
|
|
|
// PASSWORD_MODE_STRONG + complex chars -> PASSWORD_QUALITY_COMPLEX
|
2011-04-28 00:12:06 +00:00
|
|
|
Policy p4 = setupPolicy(4, Policy.PASSWORD_MODE_STRONG,
|
2011-07-01 19:34:03 +00:00
|
|
|
0, 0, false, 0, 0 , 2, false, false);
|
2011-03-16 16:48:08 +00:00
|
|
|
assertEquals(DevicePolicyManager.PASSWORD_QUALITY_COMPLEX,
|
|
|
|
p4.getDPManagerPasswordQuality());
|
|
|
|
}
|
2011-04-28 00:12:06 +00:00
|
|
|
|
|
|
|
private boolean policySetEqualsPolicy(PolicySet ps, Policy policy) {
|
|
|
|
if ((ps.mPasswordMode >> LegacyPolicySet.PASSWORD_MODE_SHIFT) != policy.mPasswordMode) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (ps.mMinPasswordLength != policy.mPasswordMinLength) return false;
|
|
|
|
if (ps.mPasswordComplexChars != policy.mPasswordComplexChars) return false;
|
|
|
|
if (ps.mPasswordHistory != policy.mPasswordHistory) return false;
|
|
|
|
if (ps.mPasswordExpirationDays != policy.mPasswordExpirationDays) return false;
|
|
|
|
if (ps.mMaxPasswordFails != policy.mPasswordMaxFails) return false;
|
|
|
|
if (ps.mMaxScreenLockTime != policy.mMaxScreenLockTime) return false;
|
|
|
|
if (ps.mRequireRemoteWipe != policy.mRequireRemoteWipe) return false;
|
|
|
|
if (ps.mRequireEncryption != policy.mRequireEncryption) return false;
|
|
|
|
if (ps.mRequireEncryptionExternal != policy.mRequireEncryptionExternal) return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void testPolicyFlagsToPolicy() {
|
|
|
|
// Policy flags; the three sets included here correspond to policies for three test
|
|
|
|
// accounts that, between them, use all of the possible policies
|
|
|
|
long flags = 67096612L;
|
|
|
|
PolicySet ps = new PolicySet(flags);
|
|
|
|
Policy policy = LegacyPolicySet.flagsToPolicy(flags);
|
|
|
|
assertTrue(policySetEqualsPolicy(ps, policy));
|
|
|
|
flags = 52776591691846L;
|
|
|
|
ps = new PolicySet(flags);
|
|
|
|
policy = LegacyPolicySet.flagsToPolicy(flags);
|
|
|
|
assertTrue(policySetEqualsPolicy(ps, policy));
|
|
|
|
flags = 1689605957029924L;
|
|
|
|
ps = new PolicySet(flags);
|
|
|
|
policy = LegacyPolicySet.flagsToPolicy(flags);
|
|
|
|
assertTrue(policySetEqualsPolicy(ps, policy));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The old PolicySet class fields and constructor; we use this to test conversion to the
|
|
|
|
* new Policy table scheme
|
|
|
|
*/
|
|
|
|
private static class PolicySet {
|
|
|
|
private final int mMinPasswordLength;
|
|
|
|
private final int mPasswordMode;
|
|
|
|
private final int mMaxPasswordFails;
|
|
|
|
private final int mMaxScreenLockTime;
|
|
|
|
private final boolean mRequireRemoteWipe;
|
|
|
|
private final int mPasswordExpirationDays;
|
|
|
|
private final int mPasswordHistory;
|
|
|
|
private final int mPasswordComplexChars;
|
|
|
|
private final boolean mRequireEncryption;
|
|
|
|
private final boolean mRequireEncryptionExternal;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create from values encoded in an account flags int
|
|
|
|
*/
|
|
|
|
private PolicySet(long flags) {
|
|
|
|
mMinPasswordLength = (int) ((flags & LegacyPolicySet.PASSWORD_LENGTH_MASK)
|
|
|
|
>> LegacyPolicySet.PASSWORD_LENGTH_SHIFT);
|
|
|
|
mPasswordMode =
|
|
|
|
(int) (flags & LegacyPolicySet.PASSWORD_MODE_MASK);
|
|
|
|
mMaxPasswordFails = (int) ((flags & LegacyPolicySet.PASSWORD_MAX_FAILS_MASK)
|
|
|
|
>> LegacyPolicySet.PASSWORD_MAX_FAILS_SHIFT);
|
|
|
|
mMaxScreenLockTime = (int) ((flags & LegacyPolicySet.SCREEN_LOCK_TIME_MASK)
|
|
|
|
>> LegacyPolicySet.SCREEN_LOCK_TIME_SHIFT);
|
|
|
|
mRequireRemoteWipe = 0 != (flags & LegacyPolicySet.REQUIRE_REMOTE_WIPE);
|
|
|
|
mPasswordExpirationDays = (int) ((flags & LegacyPolicySet.PASSWORD_EXPIRATION_MASK)
|
|
|
|
>> LegacyPolicySet.PASSWORD_EXPIRATION_SHIFT);
|
|
|
|
mPasswordHistory = (int) ((flags & LegacyPolicySet.PASSWORD_HISTORY_MASK)
|
|
|
|
>> LegacyPolicySet.PASSWORD_HISTORY_SHIFT);
|
|
|
|
mPasswordComplexChars = (int) ((flags & LegacyPolicySet.PASSWORD_COMPLEX_CHARS_MASK)
|
|
|
|
>> LegacyPolicySet.PASSWORD_COMPLEX_CHARS_SHIFT);
|
|
|
|
mRequireEncryption = 0 != (flags & LegacyPolicySet.REQUIRE_ENCRYPTION);
|
|
|
|
mRequireEncryptionExternal = 0 != (flags & LegacyPolicySet.REQUIRE_ENCRYPTION_EXTERNAL);
|
|
|
|
}
|
|
|
|
}
|
2010-01-27 01:24:15 +00:00
|
|
|
}
|