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:
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user