Add permission access to DPM certificate mng APIs
Bug: 234609037
Test: atest KeyManagementTest
Change-Id: I13ade76670022be991dd05a2b2fe467d74f978cf
diff --git a/core/api/current.txt b/core/api/current.txt
index 9d15aa3..81322e5 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -7744,7 +7744,7 @@
method @Nullable public android.os.UserHandle createAndManageUser(@NonNull android.content.ComponentName, @NonNull String, @NonNull android.content.ComponentName, @Nullable android.os.PersistableBundle, int);
method public void enableSystemApp(@NonNull android.content.ComponentName, String);
method public int enableSystemApp(@NonNull android.content.ComponentName, android.content.Intent);
- method public android.security.AttestedKeyPair generateKeyPair(@Nullable android.content.ComponentName, @NonNull String, @NonNull android.security.keystore.KeyGenParameterSpec, int);
+ method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES, conditional=true) public android.security.AttestedKeyPair generateKeyPair(@Nullable android.content.ComponentName, @NonNull String, @NonNull android.security.keystore.KeyGenParameterSpec, int);
method @Nullable public String[] getAccountTypesWithManagementDisabled();
method @Nullable public java.util.List<android.content.ComponentName> getActiveAdmins();
method @NonNull public java.util.Set<java.lang.String> getAffiliationIds(@NonNull android.content.ComponentName);
@@ -7839,13 +7839,13 @@
method public boolean grantKeyPairToWifiAuth(@NonNull String);
method public boolean hasCaCertInstalled(@Nullable android.content.ComponentName, byte[]);
method public boolean hasGrantedPolicy(@NonNull android.content.ComponentName, int);
- method public boolean hasKeyPair(@NonNull String);
+ method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES, conditional=true) public boolean hasKeyPair(@NonNull String);
method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI, conditional=true) public boolean hasLockdownAdminConfiguredNetworks(@Nullable android.content.ComponentName);
method public boolean installCaCert(@Nullable android.content.ComponentName, byte[]);
method public boolean installExistingPackage(@NonNull android.content.ComponentName, String);
- method public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate, @NonNull String);
- method public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate[], @NonNull String, boolean);
- method public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate[], @NonNull String, int);
+ method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES, conditional=true) public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate, @NonNull String);
+ method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES, conditional=true) public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate[], @NonNull String, boolean);
+ method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES, conditional=true) public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate[], @NonNull String, int);
method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, conditional=true) public void installSystemUpdate(@Nullable android.content.ComponentName, @NonNull android.net.Uri, @NonNull java.util.concurrent.Executor, @NonNull android.app.admin.DevicePolicyManager.InstallSystemUpdateCallback);
method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional=true) public boolean isActivePasswordSufficient();
method public boolean isActivePasswordSufficientForDeviceRequirement();
@@ -7887,7 +7887,7 @@
method public void reboot(@NonNull android.content.ComponentName);
method public void removeActiveAdmin(@NonNull android.content.ComponentName);
method public boolean removeCrossProfileWidgetProvider(@NonNull android.content.ComponentName, String);
- method public boolean removeKeyPair(@Nullable android.content.ComponentName, @NonNull String);
+ method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES, conditional=true) public boolean removeKeyPair(@Nullable android.content.ComponentName, @NonNull String);
method public boolean removeOverrideApn(@NonNull android.content.ComponentName, int);
method public boolean removeUser(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
method public boolean requestBugreport(@NonNull android.content.ComponentName);
@@ -7928,7 +7928,7 @@
method @WorkerThread public int setGlobalPrivateDnsModeSpecifiedHost(@NonNull android.content.ComponentName, @NonNull String);
method public void setGlobalSetting(@NonNull android.content.ComponentName, String, String);
method public void setKeepUninstalledPackages(@Nullable android.content.ComponentName, @NonNull java.util.List<java.lang.String>);
- method public boolean setKeyPairCertificate(@Nullable android.content.ComponentName, @NonNull String, @NonNull java.util.List<java.security.cert.Certificate>, boolean);
+ method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES, conditional=true) public boolean setKeyPairCertificate(@Nullable android.content.ComponentName, @NonNull String, @NonNull java.util.List<java.security.cert.Certificate>, boolean);
method public boolean setKeyguardDisabled(@NonNull android.content.ComponentName, boolean);
method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_KEYGUARD, conditional=true) public void setKeyguardDisabledFeatures(@Nullable android.content.ComponentName, int);
method public void setLocationEnabled(@NonNull android.content.ComponentName, boolean);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 94a3bbb..7c3fb9d 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -18,8 +18,9 @@
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
-import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA;
import static android.Manifest.permission.MANAGE_DEVICE_ADMINS;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_FACTORY_RESET;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_INPUT_METHODS;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_KEYGUARD;
@@ -28,7 +29,6 @@
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MTE;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_PACKAGE_STATE;
-import static android.Manifest.permission.MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SCREEN_CAPTURE;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES;
@@ -7295,6 +7295,8 @@
* <li>Profile owner</li>
* <li>Delegated certificate installer</li>
* <li>Credential management app</li>
+ * <li>An app that holds the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission</li>
* </ul>
* All apps within the profile will be able to access the certificate and use the private key,
* given direct user approval.
@@ -7317,17 +7319,19 @@
* revoked.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
- * {@code null} if calling from a delegated certificate installer.
+ * {@code null} if the caller is not a device admin.
* @param privKey The private key to install.
* @param cert The certificate to install.
* @param alias The private key alias under which to install the certificate. If a certificate
* with that alias already exists, it will be overwritten.
* @return {@code true} if the keys were installed, {@code false} otherwise.
* @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
- * owner.
+ * owner, or {@code admin} is null and the calling application does not have the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
* @see #setDelegatedScopes
* @see #DELEGATION_CERT_INSTALL
*/
+ @RequiresPermission(value = MANAGE_DEVICE_POLICY_CERTIFICATES, conditional = true)
public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey,
@NonNull Certificate cert, @NonNull String alias) {
return installKeyPair(admin, privKey, new Certificate[] {cert}, alias, false);
@@ -7341,6 +7345,8 @@
* <li>Profile owner</li>
* <li>Delegated certificate installer</li>
* <li>Credential management app</li>
+ * <li>An app that holds the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission</li>
* </ul>
* All apps within the profile will be able to access the certificate chain and use the private
* key, given direct user approval.
@@ -7361,7 +7367,7 @@
* revoked.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
- * {@code null} if calling from a delegated certificate installer.
+ * {@code null} if the caller is not a device admin.
* @param privKey The private key to install.
* @param certs The certificate chain to install. The chain should start with the leaf
* certificate and include the chain of trust in order. This will be returned by
@@ -7373,11 +7379,13 @@
* approval.
* @return {@code true} if the keys were installed, {@code false} otherwise.
* @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
- * owner.
+ * owner, or {@code admin} is null and the calling application does not have the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
* @see android.security.KeyChain#getCertificateChain
* @see #setDelegatedScopes
* @see #DELEGATION_CERT_INSTALL
*/
+ @RequiresPermission(value = MANAGE_DEVICE_POLICY_CERTIFICATES, conditional = true)
public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey,
@NonNull Certificate[] certs, @NonNull String alias, boolean requestAccess) {
int flags = INSTALLKEY_SET_USER_SELECTABLE;
@@ -7395,6 +7403,8 @@
* <li>Profile owner</li>
* <li>Delegated certificate installer</li>
* <li>Credential management app</li>
+ * <li>An app that holds the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission</li>
* </ul>
* All apps within the profile will be able to access the certificate chain and use the
* private key, given direct user approval (if the user is allowed to select the private key).
@@ -7421,7 +7431,7 @@
* revoked.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
- * {@code null} if calling from a delegated certificate installer.
+ * {@code null} if the caller is not a device admin.
* @param privKey The private key to install.
* @param certs The certificate chain to install. The chain should start with the leaf
* certificate and include the chain of trust in order. This will be returned by
@@ -7432,13 +7442,15 @@
* and set the key to be user-selectable. See {@link #INSTALLKEY_SET_USER_SELECTABLE} and
* {@link #INSTALLKEY_REQUEST_CREDENTIALS_ACCESS}.
* @return {@code true} if the keys were installed, {@code false} otherwise.
- * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
- * owner, or {@code admin} is null but the calling application is not a delegated
- * certificate installer or credential management app.
+ * @throws SecurityException if {@code admin} is not {@code null} and not a device or
+ * profile owner, or {@code admin} is null but the calling application is not a
+ * delegated certificate installer, credential management app and does not have the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
* @see android.security.KeyChain#getCertificateChain
* @see #setDelegatedScopes
* @see #DELEGATION_CERT_INSTALL
*/
+ @RequiresPermission(value = MANAGE_DEVICE_POLICY_CERTIFICATES, conditional = true)
public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey,
@NonNull Certificate[] certs, @NonNull String alias, int flags) {
throwIfParentInstance("installKeyPair");
@@ -7474,6 +7486,8 @@
* <li>Profile owner</li>
* <li>Delegated certificate installer</li>
* <li>Credential management app</li>
+ * <li>An app that holds the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission</li>
* </ul>
*
* <p>From Android {@link android.os.Build.VERSION_CODES#S}, the credential management app
@@ -7481,15 +7495,17 @@
* {@code null}. Note, there can only be a credential management app on an unmanaged device.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
- * {@code null} if calling from a delegated certificate installer.
+ * {@code null} if the caller is not a device admin.
* @param alias The private key alias under which the certificate is installed.
* @return {@code true} if the private key alias no longer exists, {@code false} otherwise.
- * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
- * owner, or {@code admin} is null but the calling application is not a delegated
- * certificate installer or credential management app.
+ * @throws SecurityException if {@code admin} is not {@code null} and not a device owner or
+ * profile owner, or {@code admin} is null but the calling application is not a
+ * delegated certificate installer, credential management app and does not have the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
* @see #setDelegatedScopes
* @see #DELEGATION_CERT_INSTALL
*/
+ @RequiresPermission(value = MANAGE_DEVICE_POLICY_CERTIFICATES, conditional = true)
public boolean removeKeyPair(@Nullable ComponentName admin, @NonNull String alias) {
throwIfParentInstance("removeKeyPair");
try {
@@ -7508,6 +7524,8 @@
* <li>Profile owner</li>
* <li>Delegated certificate installer</li>
* <li>Credential management app</li>
+ * <li>An app that holds the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission</li>
* </ul>
*
* If called by the credential management app, the alias must exist in the credential
@@ -7516,10 +7534,12 @@
* @param alias The alias under which the key pair is installed.
* @return {@code true} if a key pair with this alias exists, {@code false} otherwise.
* @throws SecurityException if the caller is not a device or profile owner, a delegated
- * certificate installer or the credential management app.
+ * certificate installer, the credential management app and does not have the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
* @see #setDelegatedScopes
* @see #DELEGATION_CERT_INSTALL
*/
+ @RequiresPermission(value = MANAGE_DEVICE_POLICY_CERTIFICATES, conditional = true)
public boolean hasKeyPair(@NonNull String alias) {
throwIfParentInstance("hasKeyPair");
try {
@@ -7536,6 +7556,8 @@
* <li>Profile owner</li>
* <li>Delegated certificate installer</li>
* <li>Credential management app</li>
+ * <li>An app that holds the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission</li>
* </ul>
* If the device supports key generation via secure hardware, this method is useful for
* creating a key in KeyChain that never left the secure hardware. Access to the key is
@@ -7566,19 +7588,23 @@
* supports these features, refer to {@link #isDeviceIdAttestationSupported()} and
* {@link #isUniqueDeviceAttestationSupported()}.
*
- * <p>Device owner, profile owner, their delegated certificate installer and the credential
- * management app can use {@link #ID_TYPE_BASE_INFO} to request inclusion of the general device
- * information including manufacturer, model, brand, device and product in the attestation
- * record.
- * Only device owner, profile owner on an organization-owned device or affiliated user, and
- * their delegated certificate installers can use {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI}
- * and {@link #ID_TYPE_MEID} to request unique device identifiers to be attested (the serial
- * number, IMEI and MEID correspondingly), if supported by the device
- * (see {@link #isDeviceIdAttestationSupported()}).
- * Additionally, device owner, profile owner on an organization-owned device and their delegated
- * certificate installers can also request the attestation record to be signed using an
- * individual attestation certificate by specifying the {@link #ID_TYPE_INDIVIDUAL_ATTESTATION}
- * flag (if supported by the device, see {@link #isUniqueDeviceAttestationSupported()}).
+ * <p>Device owner, profile owner, their delegated certificate installer, the credential
+ * management app or an app that holds the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission can use
+ * {@link #ID_TYPE_BASE_INFO} to request inclusion of the general device information including
+ * manufacturer, model, brand, device and product in the attestation record.
+ * Only device owner, profile owner on an organization-owned device or affiliated user, their
+ * delegated certificate installers or an app that holds the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission can use
+ * {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} and {@link #ID_TYPE_MEID} to request unique
+ * device identifiers to be attested (the serial number, IMEI and MEID correspondingly),
+ * if supported by the device (see {@link #isDeviceIdAttestationSupported()}).
+ * Additionally, device owner, profile owner on an organization-owned device, their delegated
+ * certificate installers and an app that holds the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission can also
+ * request the attestation record to be signed using an individual attestation certificate by
+ * specifying the {@link #ID_TYPE_INDIVIDUAL_ATTESTATION} flag (if supported by the device,
+ * see {@link #isUniqueDeviceAttestationSupported()}).
* <p>
* If any of {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} and {@link #ID_TYPE_MEID}
* is set, it is implicitly assumed that {@link #ID_TYPE_BASE_INFO} is also set.
@@ -7587,7 +7613,7 @@
* key generation is done in StrongBox.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
- * {@code null} if calling from a delegated certificate installer.
+ * {@code null} if the caller is not a device admin.
* @param algorithm The key generation algorithm, see {@link java.security.KeyPairGenerator}.
* @param keySpec Specification of the key to generate, see
* {@link java.security.KeyPairGenerator}.
@@ -7603,12 +7629,14 @@
* If any flag is specified, then an attestation challenge must be included in the
* {@code keySpec}.
* @return A non-null {@code AttestedKeyPair} if the key generation succeeded, null otherwise.
- * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
- * owner, or {@code admin} is null but the calling application is not a delegated
- * certificate installer or credential management app. If Device ID attestation is
- * requested (using {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} or
- * {@link #ID_TYPE_MEID}), the caller must be the Device Owner or the Certificate
- * Installer delegate.
+ * @throws SecurityException if {@code admin} is not {@code null} and not a device owner or
+ * profile owner, or {@code admin} is null but the calling application is not a
+ * delegated certificate installer, credential management app and does not have the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
+ * If Device ID attestation is requested (using {@link #ID_TYPE_SERIAL},
+ * {@link #ID_TYPE_IMEI} or {@link #ID_TYPE_MEID}), the caller must be the Device Owner,
+ * the Certificate Installer delegate or have the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
* @throws IllegalArgumentException in the following cases:
* <p>
* <ul>
@@ -7624,6 +7652,7 @@
* specified in {@code keySpec} but the device does not have one.
* @see KeyGenParameterSpec.Builder#setAttestationChallenge(byte[])
*/
+ @RequiresPermission(value = MANAGE_DEVICE_POLICY_CERTIFICATES, conditional = true)
public AttestedKeyPair generateKeyPair(@Nullable ComponentName admin,
@NonNull String algorithm, @NonNull KeyGenParameterSpec keySpec,
@AttestationIdType int idAttestationFlags) {
@@ -7890,6 +7919,8 @@
* <li>Profile owner</li>
* <li>Delegated certificate installer</li>
* <li>Credential management app</li>
+ * <li>An app that holds the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission</li>
* </ul>
*
* <p>From Android {@link android.os.Build.VERSION_CODES#S}, the credential management app
@@ -7897,7 +7928,7 @@
* {@code null}. Note, there can only be a credential management app on an unmanaged device.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
- * {@code null} if calling from a delegated certificate installer.
+ * {@code null} if the caller is not a device admin.
* @param alias The private key alias under which to install the certificate. The {@code alias}
* should denote an existing private key. If a certificate with that alias already
* exists, it will be overwritten.
@@ -7910,10 +7941,12 @@
* {@link android.app.admin.DeviceAdminReceiver#onChoosePrivateKeyAlias}.
* @return {@code true} if the provided {@code alias} exists and the certificates has been
* successfully associated with it, {@code false} otherwise.
- * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
- * owner, or {@code admin} is null but the calling application is not a delegated
- * certificate installer or credential management app.
+ * @throws SecurityException if {@code admin} is not {@code null} and not a device owner or
+ * profile owner, or {@code admin} is null but the calling application is not a
+ * delegated certificate installer, credential management app and does not have the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
*/
+ @RequiresPermission(value = MANAGE_DEVICE_POLICY_CERTIFICATES, conditional = true)
public boolean setKeyPairCertificate(@Nullable ComponentName admin,
@NonNull String alias, @NonNull List<Certificate> certs, boolean isUserSelectable) {
throwIfParentInstance("setKeyPairCertificate");
@@ -7934,7 +7967,6 @@
return false;
}
-
/**
* @return the alias of a given CA certificate in the certificate store, or {@code null} if it
* doesn't exist.
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b386598..500a86b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -23,6 +23,7 @@
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_FACTORY_RESET;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_INPUT_METHODS;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_KEYGUARD;
@@ -5994,9 +5995,15 @@
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
final boolean isCallerDelegate = isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
final boolean isCredentialManagementApp = isCredentialManagementApp(caller);
- Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
- || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+ if (isPermissionCheckFlagEnabled()) {
+ Preconditions.checkCallAuthorization(
+ hasPermission(MANAGE_DEVICE_POLICY_CERTIFICATES, caller.getUserId())
+ || isCredentialManagementApp);
+ } else {
+ Preconditions.checkCallAuthorization((caller.hasAdminComponent()
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
+ || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+ }
if (isCredentialManagementApp) {
Preconditions.checkCallAuthorization(!isUserSelectable, "The credential "
+ "management app is not allowed to install a user selectable key pair");
@@ -6059,9 +6066,15 @@
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
final boolean isCallerDelegate = isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
final boolean isCredentialManagementApp = isCredentialManagementApp(caller);
- Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
- || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+ if (isPermissionCheckFlagEnabled()) {
+ Preconditions.checkCallAuthorization(
+ hasPermission(MANAGE_DEVICE_POLICY_CERTIFICATES, caller.getUserId())
+ || isCredentialManagementApp);
+ } else {
+ Preconditions.checkCallAuthorization((caller.hasAdminComponent()
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
+ || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+ }
if (isCredentialManagementApp) {
Preconditions.checkCallAuthorization(
isAliasInCredentialManagementAppPolicy(caller, alias),
@@ -6124,8 +6137,12 @@
}
private boolean canInstallCertificates(CallerIdentity caller) {
- return isProfileOwner(caller) || isDefaultDeviceOwner(caller)
- || isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
+ if (isPermissionCheckFlagEnabled()) {
+ return hasPermission(MANAGE_DEVICE_POLICY_CERTIFICATES, caller.getUserId());
+ } else {
+ return isProfileOwner(caller) || isDefaultDeviceOwner(caller)
+ || isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
+ }
}
private boolean canChooseCertificates(CallerIdentity caller) {
@@ -6318,9 +6335,15 @@
caller.getPackageName(), caller.getUid()));
enforceIndividualAttestationSupportedIfRequested(attestationUtilsFlags);
} else {
- Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
- || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+ if (isPermissionCheckFlagEnabled()) {
+ Preconditions.checkCallAuthorization(
+ hasPermission(MANAGE_DEVICE_POLICY_CERTIFICATES, caller.getUserId())
+ || isCredentialManagementApp);
+ } else {
+ Preconditions.checkCallAuthorization((caller.hasAdminComponent() && (isProfileOwner(
+ caller) || isDefaultDeviceOwner(caller))) || (caller.hasPackage() && (
+ isCallerDelegate || isCredentialManagementApp)));
+ }
if (isCredentialManagementApp) {
Preconditions.checkCallAuthorization(
isAliasInCredentialManagementAppPolicy(caller, alias),
@@ -6453,9 +6476,15 @@
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
final boolean isCallerDelegate = isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
final boolean isCredentialManagementApp = isCredentialManagementApp(caller);
- Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
- || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+ if (isPermissionCheckFlagEnabled()) {
+ Preconditions.checkCallAuthorization(
+ hasPermission(MANAGE_DEVICE_POLICY_CERTIFICATES, caller.getUserId())
+ || isCredentialManagementApp);
+ } else {
+ Preconditions.checkCallAuthorization((caller.hasAdminComponent()
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
+ || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+ }
if (isCredentialManagementApp) {
Preconditions.checkCallAuthorization(
isAliasInCredentialManagementAppPolicy(caller, alias),
@@ -10170,6 +10199,8 @@
* (2.1.1) The caller is the profile owner.
* (2.1.2) The caller is from another app in the same user as the profile owner, AND
* the caller is the delegated cert installer.
+ * (3) The caller holds the
+ * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
*
* For the device owner case, simply check that the caller is the device owner or the
* delegated certificate installer.
@@ -10182,19 +10213,23 @@
*/
@VisibleForTesting
boolean hasDeviceIdAccessUnchecked(String packageName, int uid) {
- ComponentName deviceOwner = getDeviceOwnerComponent(true);
- if (deviceOwner != null && (deviceOwner.getPackageName().equals(packageName)
- || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL))) {
- return true;
- }
final int userId = UserHandle.getUserId(uid);
- ComponentName profileOwner = getProfileOwnerAsUser(userId);
- final boolean isCallerProfileOwnerOrDelegate = profileOwner != null
- && (profileOwner.getPackageName().equals(packageName)
- || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL));
- if (isCallerProfileOwnerOrDelegate && (isProfileOwnerOfOrganizationOwnedDevice(userId)
- || isUserAffiliatedWithDevice(userId))) {
- return true;
+ if (isPermissionCheckFlagEnabled()) {
+ return hasPermission(MANAGE_DEVICE_POLICY_CERTIFICATES, userId);
+ } else {
+ ComponentName deviceOwner = getDeviceOwnerComponent(true);
+ if (deviceOwner != null && (deviceOwner.getPackageName().equals(packageName)
+ || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL))) {
+ return true;
+ }
+ ComponentName profileOwner = getProfileOwnerAsUser(userId);
+ final boolean isCallerProfileOwnerOrDelegate = profileOwner != null
+ && (profileOwner.getPackageName().equals(packageName)
+ || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL));
+ if (isCallerProfileOwnerOrDelegate && (isProfileOwnerOfOrganizationOwnedDevice(userId)
+ || isUserAffiliatedWithDevice(userId))) {
+ return true;
+ }
}
return false;
}
@@ -21079,7 +21114,8 @@
MANAGE_DEVICE_POLICY_PACKAGE_STATE,
MANAGE_DEVICE_POLICY_LOCK,
MANAGE_DEVICE_POLICY_FACTORY_RESET,
- MANAGE_DEVICE_POLICY_KEYGUARD);
+ MANAGE_DEVICE_POLICY_KEYGUARD,
+ MANAGE_DEVICE_POLICY_CERTIFICATES);
private static final List<String> FINANCED_DEVICE_OWNER_PERMISSIONS = List.of(
MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL,
MANAGE_DEVICE_POLICY_ACROSS_USERS,
@@ -21096,18 +21132,19 @@
SET_TIME_ZONE,
MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY,
MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS,
- MANAGE_DEVICE_POLICY_WIFI,
- MANAGE_DEVICE_POLICY_WIPE_DATA,
- MANAGE_DEVICE_POLICY_SCREEN_CAPTURE,
- MANAGE_DEVICE_POLICY_SYSTEM_UPDATES,
- MANAGE_DEVICE_POLICY_SECURITY_LOGGING,
- MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING,
- MANAGE_DEVICE_POLICY_MTE,
- MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
+ MANAGE_DEVICE_POLICY_WIFI,
+ MANAGE_DEVICE_POLICY_WIPE_DATA,
+ MANAGE_DEVICE_POLICY_SCREEN_CAPTURE,
+ MANAGE_DEVICE_POLICY_SYSTEM_UPDATES,
+ MANAGE_DEVICE_POLICY_SECURITY_LOGGING,
+ MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING,
+ MANAGE_DEVICE_POLICY_MTE,
+ MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
MANAGE_DEVICE_POLICY_PACKAGE_STATE,
- MANAGE_DEVICE_POLICY_LOCK,
- MANAGE_DEVICE_POLICY_FACTORY_RESET,
- MANAGE_DEVICE_POLICY_KEYGUARD);
+ MANAGE_DEVICE_POLICY_LOCK,
+ MANAGE_DEVICE_POLICY_FACTORY_RESET,
+ MANAGE_DEVICE_POLICY_KEYGUARD,
+ MANAGE_DEVICE_POLICY_CERTIFICATES);
private static final List<String> PROFILE_OWNER_ON_USER_0_PERMISSIONS = List.of(
SET_TIME,
SET_TIME_ZONE,