Relax device admin policies when accounts deleted
If an account is deleted, immediately recompute the aggregate security policy, and apply it immediately. When applying policies, handle "no policy" case by releasing device admin status entirely.
This commit is contained in:
parent
34716bb6f9
commit
50d1610c43
|
@ -63,6 +63,9 @@ public class AccountBackupRestore {
|
|||
if (restored) {
|
||||
// after restoring accounts, register services appropriately
|
||||
Log.w(Email.LOG_TAG, "Register services after restoring accounts");
|
||||
// update security profile
|
||||
SecurityPolicy.getInstance(context).updatePolicies(-1);
|
||||
// enable/disable other email services as necessary
|
||||
Email.setServicesEnabled(context);
|
||||
ExchangeUtils.startExchangeService(context);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Utility functions to support reading and writing security policies
|
||||
|
@ -178,6 +179,16 @@ public class SecurityPolicy {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return updated aggregate policy, from cached value if possible
|
||||
*/
|
||||
public synchronized PolicySet getAggregatePolicy() {
|
||||
if (mAggregatePolicy == null) {
|
||||
mAggregatePolicy = computeAggregatePolicy();
|
||||
}
|
||||
return mAggregatePolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dpm. This mainly allows us to make some utility calls without it, for testing.
|
||||
*/
|
||||
|
@ -217,12 +228,23 @@ public class SecurityPolicy {
|
|||
|
||||
/**
|
||||
* API: Report that policies may have been updated due to rewriting values in an Account.
|
||||
* @param accountId the account that has been updated
|
||||
* @param accountId the account that has been updated, -1 if unknown/deleted
|
||||
*/
|
||||
public synchronized void updatePolicies(long accountId) {
|
||||
mAggregatePolicy = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* API: Report that policies may have been updated *and* the caller vouches that the
|
||||
* change is a reduction in policies. This forces an immediate change to device state.
|
||||
* Typically used when deleting accounts, although we may use it for server-side policy
|
||||
* rollbacks.
|
||||
*/
|
||||
public void reducePolicies() {
|
||||
updatePolicies(-1);
|
||||
setActivePolicies();
|
||||
}
|
||||
|
||||
/**
|
||||
* API: Query used to determine if a given policy is "active" (the device is operating at
|
||||
* the required security level).
|
||||
|
@ -237,21 +259,16 @@ public class SecurityPolicy {
|
|||
* @return true if the policies are active, false if not active
|
||||
*/
|
||||
public boolean isActive(PolicySet policies) {
|
||||
// select aggregate set if needed
|
||||
if (policies == null) {
|
||||
policies = getAggregatePolicy();
|
||||
}
|
||||
// quick check for the "empty set" of no policies
|
||||
if (policies == NO_POLICY_SET) {
|
||||
return true;
|
||||
}
|
||||
DevicePolicyManager dpm = getDPM();
|
||||
if (dpm.isAdminActive(mAdminName)) {
|
||||
// select aggregate set if needed
|
||||
if (policies == null) {
|
||||
synchronized (this) {
|
||||
if (mAggregatePolicy == null) {
|
||||
mAggregatePolicy = computeAggregatePolicy();
|
||||
}
|
||||
policies = mAggregatePolicy;
|
||||
}
|
||||
}
|
||||
// quick check for the "empty set" of no policies
|
||||
if (policies == NO_POLICY_SET) {
|
||||
return true;
|
||||
}
|
||||
// check each policy explicitly
|
||||
if (policies.mMinPasswordLength > 0) {
|
||||
if (dpm.getPasswordMinimumLength(mAdminName) < policies.mMinPasswordLength) {
|
||||
|
@ -283,19 +300,18 @@ public class SecurityPolicy {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the requested security level based on the aggregate set of requests
|
||||
* Set the requested security level based on the aggregate set of requests.
|
||||
* If the set is empty, we release our device administration. If the set is non-empty,
|
||||
* we only proceed if we are already active as an admin.
|
||||
*/
|
||||
public void setActivePolicies() {
|
||||
DevicePolicyManager dpm = getDPM();
|
||||
if (dpm.isAdminActive(mAdminName)) {
|
||||
// compute aggregate set if needed
|
||||
PolicySet policies;
|
||||
synchronized (this) {
|
||||
if (mAggregatePolicy == null) {
|
||||
mAggregatePolicy = computeAggregatePolicy();
|
||||
}
|
||||
policies = mAggregatePolicy;
|
||||
}
|
||||
// compute aggregate set of policies
|
||||
PolicySet policies = getAggregatePolicy();
|
||||
// if empty set, detach from policy manager
|
||||
if (policies == NO_POLICY_SET) {
|
||||
dpm.removeActiveAdmin(mAdminName);
|
||||
} else if (dpm.isAdminActive(mAdminName)) {
|
||||
// set each policy in the policy manager
|
||||
// password mode & length
|
||||
dpm.setPasswordQuality(mAdminName, policies.getDPManagerPasswordQuality());
|
||||
|
@ -416,12 +432,15 @@ public class SecurityPolicy {
|
|||
}
|
||||
|
||||
/**
|
||||
* API: Remote wipe (from server). This is final, there is no confirmation.
|
||||
* API: Remote wipe (from server). This is final, there is no confirmation. It will only
|
||||
* return to the caller if there is an unexpected failure.
|
||||
*/
|
||||
public void remoteWipe(long accountId) {
|
||||
public void remoteWipe() {
|
||||
DevicePolicyManager dpm = getDPM();
|
||||
if (dpm.isAdminActive(mAdminName)) {
|
||||
dpm.wipeData(0);
|
||||
} else {
|
||||
Log.d(Email.LOG_TAG, "Could not remote wipe because not device admin.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import com.android.email.AccountBackupRestore;
|
|||
import com.android.email.Controller;
|
||||
import com.android.email.Email;
|
||||
import com.android.email.R;
|
||||
import com.android.email.SecurityPolicy;
|
||||
import com.android.email.Utility;
|
||||
import com.android.email.activity.setup.AccountSettings;
|
||||
import com.android.email.activity.setup.AccountSetupBasics;
|
||||
|
@ -426,6 +427,8 @@ public class AccountFolderList extends ListActivity implements OnItemClickListen
|
|||
AccountFolderList.this.getContentResolver().delete(uri, null, null);
|
||||
// Update the backup (side copy) of the accounts
|
||||
AccountBackupRestore.backupAccounts(AccountFolderList.this);
|
||||
// Release or relax device administration, if relevant
|
||||
SecurityPolicy.getInstance(AccountFolderList.this).reducePolicies();
|
||||
} catch (Exception e) {
|
||||
// Ignore
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package com.android.exchange;
|
|||
|
||||
import com.android.email.AccountBackupRestore;
|
||||
import com.android.email.Email;
|
||||
import com.android.email.SecurityPolicy;
|
||||
import com.android.email.mail.MessagingException;
|
||||
import com.android.email.mail.store.TrustManagerFactory;
|
||||
import com.android.email.provider.EmailContent;
|
||||
|
@ -1283,9 +1284,10 @@ public class SyncManager extends Service implements Runnable {
|
|||
accountsDeleted = true;
|
||||
}
|
||||
}
|
||||
// If we changed the list of accounts, refresh the backup
|
||||
// If we changed the list of accounts, refresh the backup & security settings
|
||||
if (accountsDeleted) {
|
||||
AccountBackupRestore.backupAccounts(getContext());
|
||||
SecurityPolicy.getInstance(context).reducePolicies();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue