Merge "API to approve CA certificates" into nyc-dev

am: f1fe782

* commit 'f1fe782e912d3feed9cded8fb80b179c4ee5d09c':
  API to approve CA certificates

Change-Id: Ia84876f692a79d159cbfadd5888d73557e111e37
This commit is contained in:
Robin Lee
2016-03-31 18:31:32 +00:00
committed by android-build-merger
3 changed files with 127 additions and 23 deletions

View File

@@ -2654,6 +2654,43 @@ public class DevicePolicyManager {
return ENCRYPTION_STATUS_UNSUPPORTED;
}
/**
* Mark a CA certificate as approved by the device user. This means that they have been notified
* of the installation, were made aware of the risks, viewed the certificate and still wanted to
* keep the certificate on the device.
*
* Calling with {@param approval} as {@code true} will cancel any ongoing warnings related to
* this certificate.
*
* @hide
*/
public boolean approveCaCert(String alias, int userHandle, boolean approval) {
if (mService != null) {
try {
return mService.approveCaCert(alias, userHandle, approval);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return false;
}
/**
* Check whether a CA certificate has been approved by the device user.
*
* @hide
*/
public boolean isCaCertApproved(String alias, int userHandle) {
if (mService != null) {
try {
return mService.isCaCertApproved(alias, userHandle);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return false;
}
/**
* Installs the given certificate as a user CA.
*

View File

@@ -144,6 +144,8 @@ interface IDevicePolicyManager {
boolean installCaCert(in ComponentName admin, in byte[] certBuffer);
void uninstallCaCerts(in ComponentName admin, in String[] aliases);
void enforceCanManageCaCerts(in ComponentName admin);
boolean approveCaCert(in String alias, int userHandle, boolean approval);
boolean isCaCertApproved(in String alias, int userHandle);
boolean installKeyPair(in ComponentName who, in byte[] privKeyBuffer, in byte[] certBuffer,
in byte[] certChainBuffer, String alias, boolean requestAccess);

View File

@@ -136,6 +136,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
import com.android.internal.util.ParcelableString;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.internal.widget.LockPatternUtils;
@@ -184,12 +185,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private static final String DEVICE_POLICIES_XML = "device_policies.xml";
private static final String TAG_ACCEPTED_CA_CERTIFICATES = "accepted-ca-certificate";
private static final String TAG_LOCK_TASK_COMPONENTS = "lock-task-component";
private static final String TAG_STATUS_BAR = "statusbar";
private static final String ATTR_DISABLED = "disabled";
private static final String ATTR_NAME = "name";
private static final String DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML =
"do-not-ask-credentials-on-boot";
@@ -420,6 +425,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final ArrayList<ActiveAdmin> mAdminList = new ArrayList<>();
final ArrayList<ComponentName> mRemovingAdmins = new ArrayList<>();
final ArraySet<String> mAcceptedCaCertificates = new ArraySet<>();
// This is the list of component allowed to start lock task mode.
List<String> mLockTaskPackages = new ArrayList<>();
@@ -483,7 +490,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
if (Intent.ACTION_BOOT_COMPLETED.equals(action)
|| KeyChain.ACTION_STORAGE_CHANGED.equals(action)) {
new MonitoringCertNotificationTask().execute(intent);
int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_ALL);
new MonitoringCertNotificationTask().execute(userId);
}
if (Intent.ACTION_USER_ADDED.equals(action)) {
disableSecurityLoggingIfNotCompliant();
@@ -2221,6 +2229,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
out.endTag(null, "active-password");
}
for (int i = 0; i < policy.mAcceptedCaCertificates.size(); i++) {
out.startTag(null, TAG_ACCEPTED_CA_CERTIFICATES);
out.attribute(null, ATTR_NAME, policy.mAcceptedCaCertificates.valueAt(i));
out.endTag(null, TAG_ACCEPTED_CA_CERTIFICATES);
}
for (int i=0; i<policy.mLockTaskPackages.size(); i++) {
String component = policy.mLockTaskPackages.get(i);
out.startTag(null, TAG_LOCK_TASK_COMPONENTS);
@@ -2387,6 +2401,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
parser.getAttributeValue(null, "symbols"));
policy.mActivePasswordNonLetter = Integer.parseInt(
parser.getAttributeValue(null, "nonletter"));
} else if (TAG_ACCEPTED_CA_CERTIFICATES.equals(tag)) {
policy.mAcceptedCaCertificates.add(parser.getAttributeValue(null, ATTR_NAME));
} else if (TAG_LOCK_TASK_COMPONENTS.equals(tag)) {
policy.mLockTaskPackages.add(parser.getAttributeValue(null, "name"));
} else if (TAG_STATUS_BAR.equals(tag)) {
@@ -2638,17 +2654,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
private class MonitoringCertNotificationTask extends AsyncTask<Intent, Void, Void> {
private class MonitoringCertNotificationTask extends AsyncTask<Integer, Void, Void> {
@Override
protected Void doInBackground(Intent... params) {
int userHandle = params[0].getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_ALL);
protected Void doInBackground(Integer... params) {
int userHandle = params[0];
if (userHandle == UserHandle.USER_ALL) {
for (UserInfo userInfo : mUserManager.getUsers()) {
manageNotification(userInfo.getUserHandle());
}
} else {
manageNotification(new UserHandle(userHandle));
manageNotification(UserHandle.of(userHandle));
}
return null;
}
@@ -2658,25 +2674,27 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return;
}
// Call out to KeyChain to check for user-added CAs
boolean hasCert = false;
// Call out to KeyChain to check for CAs which are waiting for approval.
final List<String> pendingCertificates;
try {
KeyChainConnection kcs = KeyChain.bindAsUser(mContext, userHandle);
try {
if (!kcs.getService().getUserCaAliases().getList().isEmpty()) {
hasCert = true;
}
} catch (RemoteException e) {
Log.e(LOG_TAG, "Could not connect to KeyChain service", e);
} finally {
kcs.close();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (RuntimeException | AssertionError e) {
Log.e(LOG_TAG, "Could not connect to KeyChain service", e);
pendingCertificates = getInstalledCaCertificates(userHandle);
} catch (RemoteException | RuntimeException e) {
Log.e(LOG_TAG, "Could not retrieve certificates from KeyChain service", e);
return;
}
if (!hasCert) {
synchronized (DevicePolicyManagerService.this) {
final DevicePolicyData policy = getUserData(userHandle.getIdentifier());
// Remove deleted certificates. Flush xml if necessary.
if (policy.mAcceptedCaCertificates.retainAll(pendingCertificates)) {
saveSettingsLocked(userHandle.getIdentifier());
}
// Trim to approved certificates.
pendingCertificates.removeAll(policy.mAcceptedCaCertificates);
}
if (pendingCertificates.isEmpty()) {
mInjector.getNotificationManager().cancelAsUser(
null, MONITORING_CERT_NOTIFICATION_ID, userHandle);
return;
@@ -2707,7 +2725,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final Context userContext;
try {
userContext = mContext.createPackageContextAsUser("android", 0, userHandle);
final String packageName = mContext.getPackageName();
userContext = mContext.createPackageContextAsUser(packageName, 0, userHandle);
} catch (PackageManager.NameNotFoundException e) {
Log.e(LOG_TAG, "Create context as " + userHandle + " failed", e);
return;
@@ -2726,6 +2745,29 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mInjector.getNotificationManager().notifyAsUser(
null, MONITORING_CERT_NOTIFICATION_ID, noti, userHandle);
}
private List<String> getInstalledCaCertificates(UserHandle userHandle)
throws RemoteException, RuntimeException {
KeyChainConnection conn = null;
try {
conn = KeyChain.bindAsUser(mContext, userHandle);
List<ParcelableString> aliases = conn.getService().getUserCaAliases().getList();
List<String> result = new ArrayList<>(aliases.size());
for (int i = 0; i < aliases.size(); i++) {
result.add(aliases.get(i).string);
}
return result;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return null;
} catch (AssertionError e) {
throw new RuntimeException(e);
} finally {
if (conn != null) {
conn.close();
}
}
}
}
/**
@@ -4075,6 +4117,29 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
@Override
public boolean approveCaCert(String alias, int userId, boolean approval) {
enforceManageUsers();
synchronized (this) {
Set<String> certs = getUserData(userId).mAcceptedCaCertificates;
boolean changed = (approval ? certs.add(alias) : certs.remove(alias));
if (!changed) {
return false;
}
saveSettingsLocked(userId);
}
new MonitoringCertNotificationTask().execute(userId);
return true;
}
@Override
public boolean isCaCertApproved(String alias, int userId) {
enforceManageUsers();
synchronized (this) {
return getUserData(userId).mAcceptedCaCertificates.contains(alias);
}
}
@Override
public boolean installCaCert(ComponentName admin, byte[] certBuffer) throws RemoteException {
enforceCanManageCaCerts(admin);