diff options
5 files changed, 74 insertions, 51 deletions
diff --git a/api/current.txt b/api/current.txt index 589225a..019de19 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5249,7 +5249,10 @@ package android.app.admin { method public int getPasswordQuality(android.content.ComponentName); method public boolean getStorageEncryption(android.content.ComponentName); method public int getStorageEncryptionStatus(); + method public boolean hasAnyCaCertsInstalled(); + method public boolean hasCaCertInstalled(byte[]); method public boolean hasGrantedPolicy(android.content.ComponentName, int); + method public boolean installCaCert(android.content.ComponentName, byte[]); method public boolean isActivePasswordSufficient(); method public boolean isAdminActive(android.content.ComponentName); method public boolean isApplicationBlocked(android.content.ComponentName, java.lang.String); @@ -5287,6 +5290,7 @@ package android.app.admin { method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName); method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String); method public int setStorageEncryption(android.content.ComponentName, boolean); + method public void uninstallCaCert(android.content.ComponentName, byte[]); method public void wipeData(int); field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN"; field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.ACTION_PROVISION_MANAGED_PROFILE"; diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index af653a3..df6be8b 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1507,12 +1507,11 @@ public class DevicePolicyManager { * * @return false if the certBuffer cannot be parsed or installation is * interrupted, otherwise true - * @hide */ - public boolean installCaCert(byte[] certBuffer) { + public boolean installCaCert(ComponentName who, byte[] certBuffer) { if (mService != null) { try { - return mService.installCaCert(certBuffer); + return mService.installCaCert(who, certBuffer); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1522,13 +1521,14 @@ public class DevicePolicyManager { /** * Uninstalls the given certificate from the list of User CAs, if present. - * - * @hide */ - public void uninstallCaCert(byte[] certBuffer) { + public void uninstallCaCert(ComponentName who, byte[] certBuffer) { if (mService != null) { try { - mService.uninstallCaCert(certBuffer); + final String alias = getCaCertAlias(certBuffer); + mService.uninstallCaCert(who, alias); + } catch (CertificateException e) { + Log.w(TAG, "Unable to parse certificate", e); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1537,10 +1537,8 @@ public class DevicePolicyManager { /** * Returns whether there are any user-installed CA certificates. - * - * @hide */ - public static boolean hasAnyCaCertsInstalled() { + public boolean hasAnyCaCertsInstalled() { TrustedCertificateStore certStore = new TrustedCertificateStore(); Set<String> aliases = certStore.userAliases(); return aliases != null && !aliases.isEmpty(); @@ -1548,18 +1546,10 @@ public class DevicePolicyManager { /** * Returns whether this certificate has been installed as a User CA. - * - * @hide */ public boolean hasCaCertInstalled(byte[] certBuffer) { - TrustedCertificateStore certStore = new TrustedCertificateStore(); - String alias; - byte[] pemCert; try { - CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - X509Certificate cert = (X509Certificate) certFactory.generateCertificate( - new ByteArrayInputStream(certBuffer)); - return certStore.getCertificateAlias(cert) != null; + return getCaCertAlias(certBuffer) != null; } catch (CertificateException ce) { Log.w(TAG, "Could not parse certificate", ce); } @@ -1567,6 +1557,17 @@ public class DevicePolicyManager { } /** + * Returns the alias of a given CA certificate in the certificate store, or null if it + * doesn't exist. + */ + private static String getCaCertAlias(byte[] certBuffer) throws CertificateException { + final CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + final X509Certificate cert = (X509Certificate) certFactory.generateCertificate( + new ByteArrayInputStream(certBuffer)); + return new TrustedCertificateStore().getCertificateAlias(cert); + } + + /** * Called by an application that is administering the device to disable all cameras * on the device. After setting this, no applications will be able to access any cameras * on the device. diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index e7b77d8..5333ea6 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -115,8 +115,8 @@ interface IDevicePolicyManager { String getProfileOwnerName(int userHandle); void setProfileEnabled(in ComponentName who); - boolean installCaCert(in byte[] certBuffer); - void uninstallCaCert(in byte[] certBuffer); + boolean installCaCert(in ComponentName admin, in byte[] certBuffer); + void uninstallCaCert(in ComponentName admin, in String alias); void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity); void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName); diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java index 9d6d76e..0da2b99 100644 --- a/keystore/java/android/security/KeyChain.java +++ b/keystore/java/android/security/KeyChain.java @@ -23,7 +23,9 @@ import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.os.Looper; +import android.os.Process; import android.os.RemoteException; +import android.os.UserHandle; import java.io.ByteArrayInputStream; import java.io.Closeable; import java.security.InvalidKeyException; @@ -437,6 +439,14 @@ public final class KeyChain { * Caller should call unbindService on the result when finished. */ public static KeyChainConnection bind(Context context) throws InterruptedException { + return bindAsUser(context, Process.myUserHandle()); + } + + /** + * @hide + */ + public static KeyChainConnection bindAsUser(Context context, UserHandle user) + throws InterruptedException { if (context == null) { throw new NullPointerException("context == null"); } @@ -459,9 +469,10 @@ public final class KeyChain { Intent intent = new Intent(IKeyChainService.class.getName()); ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0); intent.setComponent(comp); - boolean isBound = context.bindService(intent, - keyChainServiceConnection, - Context.BIND_AUTO_CREATE); + boolean isBound = context.bindServiceAsUser(intent, + keyChainServiceConnection, + Context.BIND_AUTO_CREATE, + user); if (!isBound) { throw new AssertionError("could not bind to KeyChainService"); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 4897b1d..2801f4f 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -1322,7 +1322,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private void manageMonitoringCertificateNotification(Intent intent) { final NotificationManager notificationManager = getNotificationManager(); - final boolean hasCert = DevicePolicyManager.hasAnyCaCertsInstalled(); + final boolean hasCert = !(new TrustedCertificateStore().userAliases().isEmpty()); if (! hasCert) { if (intent.getAction().equals(KeyChain.ACTION_STORAGE_CHANGED)) { for (UserInfo user : mUserManager.getUsers()) { @@ -2382,13 +2382,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return !"".equals(state); } - public boolean installCaCert(byte[] certBuffer) throws RemoteException { - mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null); - KeyChainConnection keyChainConnection = null; + public boolean installCaCert(ComponentName who, byte[] certBuffer) throws RemoteException { + if (who == null) { + mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null); + } else { + synchronized (this) { + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + } + } + byte[] pemCert; try { X509Certificate cert = parseCert(certBuffer); - pemCert = Credentials.convertToPem(cert); + pemCert = Credentials.convertToPem(cert); } catch (CertificateException ce) { Log.e(LOG_TAG, "Problem converting cert", ce); return false; @@ -2396,20 +2402,24 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Log.e(LOG_TAG, "Problem reading cert", ioe); return false; } + + final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId()); + final long id = Binder.clearCallingIdentity(); try { - keyChainConnection = KeyChain.bind(mContext); + final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle); try { keyChainConnection.getService().installCaCertificate(pemCert); return true; + } catch (RemoteException e) { + Log.e(LOG_TAG, "installCaCertsToKeyChain(): ", e); } finally { - if (keyChainConnection != null) { - keyChainConnection.close(); - keyChainConnection = null; - } + keyChainConnection.close(); } } catch (InterruptedException e1) { Log.w(LOG_TAG, "installCaCertsToKeyChain(): ", e1); Thread.currentThread().interrupt(); + } finally { + Binder.restoreCallingIdentity(id); } return false; } @@ -2421,34 +2431,31 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { certBuffer)); } - public void uninstallCaCert(final byte[] certBuffer) { - mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null); - TrustedCertificateStore certStore = new TrustedCertificateStore(); - String alias = null; - try { - X509Certificate cert = parseCert(certBuffer); - alias = certStore.getCertificateAlias(cert); - } catch (CertificateException ce) { - Log.e(LOG_TAG, "Problem creating X509Certificate", ce); - return; - } catch (IOException ioe) { - Log.e(LOG_TAG, "Problem reading certificate", ioe); - return; + public void uninstallCaCert(ComponentName who, String alias) { + if (who == null) { + mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null); + } else { + synchronized (this) { + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + } } + + final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId()); + final long id = Binder.clearCallingIdentity(); try { - KeyChainConnection keyChainConnection = KeyChain.bind(mContext); - IKeyChainService service = keyChainConnection.getService(); + final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle); try { - service.deleteCaCertificate(alias); + keyChainConnection.getService().deleteCaCertificate(alias); } catch (RemoteException e) { Log.e(LOG_TAG, "from CaCertUninstaller: ", e); } finally { keyChainConnection.close(); - keyChainConnection = null; } } catch (InterruptedException ie) { Log.w(LOG_TAG, "CaCertUninstaller: ", ie); Thread.currentThread().interrupt(); + } finally { + Binder.restoreCallingIdentity(id); } } |