Loading core/java/android/app/admin/DevicePolicyManager.java +37 −0 Original line number Diff line number Diff line Loading @@ -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. * Loading core/java/android/app/admin/IDevicePolicyManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -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); Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +87 −22 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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"; Loading Loading @@ -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<>(); Loading Loading @@ -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(); Loading Loading @@ -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); Loading Loading @@ -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)) { Loading Loading @@ -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; } Loading @@ -2658,25 +2674,27 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return; } // Call out to KeyChain to check for user-added CAs boolean hasCert = false; try { KeyChainConnection kcs = KeyChain.bindAsUser(mContext, userHandle); // Call out to KeyChain to check for CAs which are waiting for approval. final List<String> pendingCertificates; try { if (!kcs.getService().getUserCaAliases().getList().isEmpty()) { hasCert = true; pendingCertificates = getInstalledCaCertificates(userHandle); } catch (RemoteException | RuntimeException e) { Log.e(LOG_TAG, "Could not retrieve certificates from KeyChain service", e); return; } } catch (RemoteException e) { Log.e(LOG_TAG, "Could not connect to KeyChain service", e); } finally { kcs.close(); synchronized (DevicePolicyManagerService.this) { final DevicePolicyData policy = getUserData(userHandle.getIdentifier()); // Remove deleted certificates. Flush xml if necessary. if (policy.mAcceptedCaCertificates.retainAll(pendingCertificates)) { saveSettingsLocked(userHandle.getIdentifier()); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (RuntimeException | AssertionError e) { Log.e(LOG_TAG, "Could not connect to KeyChain service", e); // Trim to approved certificates. pendingCertificates.removeAll(policy.mAcceptedCaCertificates); } if (!hasCert) { if (pendingCertificates.isEmpty()) { mInjector.getNotificationManager().cancelAsUser( null, MONITORING_CERT_NOTIFICATION_ID, userHandle); return; Loading Loading @@ -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; Loading @@ -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(); } } } } /** Loading Loading @@ -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); Loading Loading
core/java/android/app/admin/DevicePolicyManager.java +37 −0 Original line number Diff line number Diff line Loading @@ -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. * Loading
core/java/android/app/admin/IDevicePolicyManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +87 −22 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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"; Loading Loading @@ -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<>(); Loading Loading @@ -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(); Loading Loading @@ -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); Loading Loading @@ -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)) { Loading Loading @@ -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; } Loading @@ -2658,25 +2674,27 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return; } // Call out to KeyChain to check for user-added CAs boolean hasCert = false; try { KeyChainConnection kcs = KeyChain.bindAsUser(mContext, userHandle); // Call out to KeyChain to check for CAs which are waiting for approval. final List<String> pendingCertificates; try { if (!kcs.getService().getUserCaAliases().getList().isEmpty()) { hasCert = true; pendingCertificates = getInstalledCaCertificates(userHandle); } catch (RemoteException | RuntimeException e) { Log.e(LOG_TAG, "Could not retrieve certificates from KeyChain service", e); return; } } catch (RemoteException e) { Log.e(LOG_TAG, "Could not connect to KeyChain service", e); } finally { kcs.close(); synchronized (DevicePolicyManagerService.this) { final DevicePolicyData policy = getUserData(userHandle.getIdentifier()); // Remove deleted certificates. Flush xml if necessary. if (policy.mAcceptedCaCertificates.retainAll(pendingCertificates)) { saveSettingsLocked(userHandle.getIdentifier()); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (RuntimeException | AssertionError e) { Log.e(LOG_TAG, "Could not connect to KeyChain service", e); // Trim to approved certificates. pendingCertificates.removeAll(policy.mAcceptedCaCertificates); } if (!hasCert) { if (pendingCertificates.isEmpty()) { mInjector.getNotificationManager().cancelAsUser( null, MONITORING_CERT_NOTIFICATION_ID, userHandle); return; Loading Loading @@ -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; Loading @@ -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(); } } } } /** Loading Loading @@ -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); Loading