From 18d21312ca524267db8d5ca70288ee269081aa63 Mon Sep 17 00:00:00 2001 From: Eran Messeri Date: Thu, 14 Nov 2019 22:44:40 +0000 Subject: [PATCH] Rename PO Device IDs access -> Org Owned device Repurpose the "Profile Owner was granted access to device identifiers" to "Profile Owner of an Organization-owned device". The old method now throws an exception, as it should not be called by anything other than ManagedProvisioning (which is changed in this topic). The new method now provides the functionality the old method provided, and there's a new permission associated with it. No functionality has been added or removed in this CL beyond that. Bug: 138709470 Test: atest FrameworksServicesTests:DevicePolicyManagerTest Test: atest com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testDeviceIdAttestationForProfileOwner Change-Id: I9914e8220213898d0c6b3499af8897e3a6f23819 --- api/system-current.txt | 4 +- .../dpm/src/com/android/commands/dpm/Dpm.java | 14 ++-- .../app/admin/DevicePolicyManager.java | 30 +++++--- .../app/admin/IDevicePolicyManager.aidl | 2 +- core/res/AndroidManifest.xml | 7 ++ .../DevicePolicyManagerService.java | 39 +++++++---- .../android/server/devicepolicy/Owners.java | 68 +++++++++++-------- .../devicepolicy/DevicePolicyManagerTest.java | 23 ++++--- 8 files changed, 113 insertions(+), 74 deletions(-) diff --git a/api/system-current.txt b/api/system-current.txt index adfda2fe527af..251be512baf5d 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -75,7 +75,7 @@ package android { field public static final String GET_PROCESS_STATE_AND_OOM_SCORE = "android.permission.GET_PROCESS_STATE_AND_OOM_SCORE"; field public static final String GET_RUNTIME_PERMISSIONS = "android.permission.GET_RUNTIME_PERMISSIONS"; field public static final String GET_TOP_ACTIVITY_INFO = "android.permission.GET_TOP_ACTIVITY_INFO"; - field public static final String GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS = "android.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS"; + field @Deprecated public static final String GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS = "android.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS"; field public static final String GRANT_RUNTIME_PERMISSIONS = "android.permission.GRANT_RUNTIME_PERMISSIONS"; field public static final String GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS = "android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS"; field public static final String HANDLE_CAR_MODE_CHANGES = "android.permission.HANDLE_CAR_MODE_CHANGES"; @@ -745,7 +745,7 @@ package android.app.admin { method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public boolean packageHasActiveAdmins(String); method @Deprecated @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public boolean setActiveProfileOwner(@NonNull android.content.ComponentName, String) throws java.lang.IllegalArgumentException; method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setDeviceProvisioningConfigApplied(); - method @RequiresPermission(value=android.Manifest.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS, conditional=true) public void setProfileOwnerCanAccessDeviceIds(@NonNull android.content.ComponentName); + method @Deprecated @RequiresPermission(value=android.Manifest.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS, conditional=true) public void setProfileOwnerCanAccessDeviceIds(@NonNull android.content.ComponentName); field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_ALLOWED"; field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED"; field public static final String ACTION_PROVISION_FINALIZATION = "android.app.action.PROVISION_FINALIZATION"; diff --git a/cmds/dpm/src/com/android/commands/dpm/Dpm.java b/cmds/dpm/src/com/android/commands/dpm/Dpm.java index 6c6797a328c98..d0c2a24d5314f 100644 --- a/cmds/dpm/src/com/android/commands/dpm/Dpm.java +++ b/cmds/dpm/src/com/android/commands/dpm/Dpm.java @@ -48,8 +48,8 @@ public final class Dpm extends BaseCommand { private static final String COMMAND_CLEAR_FREEZE_PERIOD_RECORD = "clear-freeze-period-record"; private static final String COMMAND_FORCE_NETWORK_LOGS = "force-network-logs"; private static final String COMMAND_FORCE_SECURITY_LOGS = "force-security-logs"; - private static final String COMMAND_GRANT_PO_DEVICE_ID_ACCESS = - "grant-profile-owner-device-ids-access"; + private static final String COMMAND_MARK_PO_ON_ORG_OWNED_DEVICE = + "mark-profile-owner-on-organization-owned-device"; private IDevicePolicyManager mDevicePolicyManager; private int mUserId = UserHandle.USER_SYSTEM; @@ -93,7 +93,7 @@ public final class Dpm extends BaseCommand { "dpm " + COMMAND_FORCE_SECURITY_LOGS + ": makes all security logs available to " + "the DPC and triggers DeviceAdminReceiver.onSecurityLogsAvailable() if needed." + "\n" - + "usage: dpm " + COMMAND_GRANT_PO_DEVICE_ID_ACCESS + ": " + + "usage: dpm " + COMMAND_MARK_PO_ON_ORG_OWNED_DEVICE + ": " + "[ --user | current ] \n"); } @@ -129,8 +129,8 @@ public final class Dpm extends BaseCommand { case COMMAND_FORCE_SECURITY_LOGS: runForceSecurityLogs(); break; - case COMMAND_GRANT_PO_DEVICE_ID_ACCESS: - runGrantProfileOwnerDeviceIdsAccess(); + case COMMAND_MARK_PO_ON_ORG_OWNED_DEVICE: + runMarkProfileOwnerOnOrganizationOwnedDevice(); break; default: throw new IllegalArgumentException ("unknown command '" + command + "'"); @@ -251,9 +251,9 @@ public final class Dpm extends BaseCommand { } - private void runGrantProfileOwnerDeviceIdsAccess() throws RemoteException { + private void runMarkProfileOwnerOnOrganizationOwnedDevice() throws RemoteException { parseArgs(/*canHaveName=*/ false); - mDevicePolicyManager.grantDeviceIdsAccessToProfileOwner(mComponent, mUserId); + mDevicePolicyManager.markProfileOwnerOnOrganizationOwnedDevice(mComponent, mUserId); System.out.println("Success"); } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 9a5444cfcd576..73980a50e5676 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -10832,28 +10832,38 @@ public class DevicePolicyManager { } /** - * Grants the profile owner of the given user access to device identifiers (such as - * serial number, IMEI and MEID). + * Deprecated. Use {@code markProfileOwnerOnOrganizationOwnedDevice} instead. + * Throws UnsupportedOperationException when called. * - *

This lets the profile owner request inclusion of device identifiers when calling - * {@link generateKeyPair}. - * - *

This grant is necessary to guarantee that profile owners can access device identifiers. - * - *

Privileged system API - meant to be called by the system, particularly the managed - * provisioning app, when a work profile is set up. + * @deprecated Use {@link #markProfileOwnerOnOrganizationOwnedDevice} instead. * * @hide */ + @Deprecated @SystemApi @RequiresPermission(value = android.Manifest.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS, conditional = true) public void setProfileOwnerCanAccessDeviceIds(@NonNull ComponentName who) { + throw new UnsupportedOperationException( + "This method is deprecated. use markProfileOwnerOnOrganizationOwnedDevice instead" + + "."); + } + + /** + * Marks the profile owner of the given user as managing an organization-owned device. + * That will give it access to device identifiers (such as serial number, IMEI and MEID) + * as well as other privileges. + * + * @hide + */ + @RequiresPermission(value = android.Manifest.permission.MARK_DEVICE_ORGANIZATION_OWNED, + conditional = true) + public void markProfileOwnerOnOrganizationOwnedDevice(@NonNull ComponentName who) { if (mService == null) { return; } try { - mService.grantDeviceIdsAccessToProfileOwner(who, myUserId()); + mService.markProfileOwnerOnOrganizationOwnedDevice(who, myUserId()); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 591d1510e6f4f..df4b55483be5b 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -426,7 +426,7 @@ interface IDevicePolicyManager { int getGlobalPrivateDnsMode(in ComponentName admin); String getGlobalPrivateDnsHost(in ComponentName admin); - void grantDeviceIdsAccessToProfileOwner(in ComponentName who, int userId); + void markProfileOwnerOnOrganizationOwnedDevice(in ComponentName who, int userId); void installUpdateFromFile(in ComponentName admin, in ParcelFileDescriptor updateFileDescriptor, in StartInstallingUpdateCallback listener); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 220fdd2e889d2..5e93b32a66a3b 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -4595,10 +4595,17 @@ + + + component name // might have written bad device owner files. b/17652534 @@ -587,7 +593,7 @@ class Owners { profileOwnerInfo = new OwnerInfo(profileOwnerName, profileOwnerPackageName, /* userRestrictionsMigrated =*/ false, /* remoteBugreportUri =*/ null, /* remoteBugreportHash =*/ - null, /* canAccessDeviceIds =*/ false); + null, /* isOrganizationOwnedDevice =*/ false); } mProfileOwners.put(userId, profileOwnerInfo); } else if (TAG_SYSTEM_UPDATE_POLICY.equals(tag)) { @@ -947,28 +953,30 @@ class Owners { public boolean userRestrictionsMigrated; public String remoteBugreportUri; public String remoteBugreportHash; - public boolean canAccessDeviceIds; + public boolean isOrganizationOwnedDevice; public OwnerInfo(String name, String packageName, boolean userRestrictionsMigrated, - String remoteBugreportUri, String remoteBugreportHash, boolean canAccessDeviceIds) { + String remoteBugreportUri, String remoteBugreportHash, + boolean isOrganizationOwnedDevice) { this.name = name; this.packageName = packageName; this.admin = new ComponentName(packageName, ""); this.userRestrictionsMigrated = userRestrictionsMigrated; this.remoteBugreportUri = remoteBugreportUri; this.remoteBugreportHash = remoteBugreportHash; - this.canAccessDeviceIds = canAccessDeviceIds; + this.isOrganizationOwnedDevice = isOrganizationOwnedDevice; } public OwnerInfo(String name, ComponentName admin, boolean userRestrictionsMigrated, - String remoteBugreportUri, String remoteBugreportHash, boolean canAccessDeviceIds) { + String remoteBugreportUri, String remoteBugreportHash, + boolean isOrganizationOwnedDevice) { this.name = name; this.admin = admin; this.packageName = admin.getPackageName(); this.userRestrictionsMigrated = userRestrictionsMigrated; this.remoteBugreportUri = remoteBugreportUri; this.remoteBugreportHash = remoteBugreportHash; - this.canAccessDeviceIds = canAccessDeviceIds; + this.isOrganizationOwnedDevice = isOrganizationOwnedDevice; } public void writeToXml(XmlSerializer out, String tag) throws IOException { @@ -988,9 +996,9 @@ class Owners { if (remoteBugreportHash != null) { out.attribute(null, ATTR_REMOTE_BUGREPORT_HASH, remoteBugreportHash); } - if (canAccessDeviceIds) { - out.attribute(null, ATTR_CAN_ACCESS_DEVICE_IDS, - String.valueOf(canAccessDeviceIds)); + if (isOrganizationOwnedDevice) { + out.attribute(null, ATTR_PROFILE_OWNER_OF_ORG_OWNED_DEVICE, + String.valueOf(isOrganizationOwnedDevice)); } out.endTag(null, tag); } @@ -1012,13 +1020,17 @@ class Owners { parser.getAttributeValue(null, ATTR_CAN_ACCESS_DEVICE_IDS); final boolean canAccessDeviceIds = ("true".equals(canAccessDeviceIdsStr)); + final String isOrgOwnedDeviceStr = + parser.getAttributeValue(null, ATTR_PROFILE_OWNER_OF_ORG_OWNED_DEVICE); + final boolean isOrgOwnedDevice = + ("true".equals(isOrgOwnedDeviceStr)) | canAccessDeviceIds; // Has component name? If so, return [name, component] if (componentName != null) { final ComponentName admin = ComponentName.unflattenFromString(componentName); if (admin != null) { return new OwnerInfo(name, admin, userRestrictionsMigrated, - remoteBugreportUri, remoteBugreportHash, canAccessDeviceIds); + remoteBugreportUri, remoteBugreportHash, isOrgOwnedDevice); } else { // This shouldn't happen but switch from package name -> component name // might have written bad device owner files. b/17652534 @@ -1029,14 +1041,14 @@ class Owners { // Else, build with [name, package] return new OwnerInfo(name, packageName, userRestrictionsMigrated, remoteBugreportUri, - remoteBugreportHash, canAccessDeviceIds); + remoteBugreportHash, isOrgOwnedDevice); } public void dump(IndentingPrintWriter pw) { pw.println("admin=" + admin); pw.println("name=" + name); pw.println("package=" + packageName); - pw.println("canAccessDeviceIds=" + canAccessDeviceIds); + pw.println("isOrganizationOwnedDevice=" + isOrganizationOwnedDevice); } } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index eef77ee1fed02..ed55aebdea028 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -5143,7 +5143,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { configureContextForAccess(mContext, false); assertExpectException(SecurityException.class, /* messageRegex= */ null, - () -> dpm.setProfileOwnerCanAccessDeviceIds(admin2)); + () -> dpm.markProfileOwnerOnOrganizationOwnedDevice(admin2)); } public void testGrantDeviceIdsAccess_notByAuthorizedCaller() throws Exception { @@ -5151,20 +5151,20 @@ public class DevicePolicyManagerTest extends DpmTestBase { configureContextForAccess(mContext, false); assertExpectException(SecurityException.class, /* messageRegex= */ null, - () -> dpm.setProfileOwnerCanAccessDeviceIds(admin1)); + () -> dpm.markProfileOwnerOnOrganizationOwnedDevice(admin1)); } public void testGrantDeviceIdsAccess_byAuthorizedSystemCaller() throws Exception { setupProfileOwner(); // This method will throw if the system context could not call - // setProfileOwnerCanAccessDeviceIds successfully. - configureProfileOwnerForDeviceIdAccess(admin1, DpmMockContext.CALLER_USER_HANDLE); + // markProfileOwnerOfOrganizationOwnedDevice successfully. + configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE); } private void configureContextForAccess(DpmMockContext context, boolean granted) { when(context.spiedContext.checkCallingPermission( - android.Manifest.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS)) + permission.MARK_DEVICE_ORGANIZATION_OWNED)) .thenReturn(granted ? PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED); @@ -5183,7 +5183,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { DpmMockContext.CALLER_MANAGED_PROVISIONING_UID); try { runAsCaller(mServiceContext, dpms, dpm -> { - dpm.setProfileOwnerCanAccessDeviceIds(admin1); + dpm.markProfileOwnerOnOrganizationOwnedDevice(admin1); }); } finally { mServiceContext.binder.restoreCallingIdentity(ident); @@ -5221,7 +5221,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { admin1.getPackageName(), DpmMockContext.CALLER_SYSTEM_USER_UID)); setupProfileOwner(); - configureProfileOwnerForDeviceIdAccess(admin1, DpmMockContext.CALLER_USER_HANDLE); + configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE); // The profile owner is allowed to request Device ID attestation. mServiceContext.binder.callingUid = DpmMockContext.CALLER_UID; @@ -5258,7 +5258,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { dpm -> dpm.setDelegatedScopes(admin1, DpmMockContext.DELEGATE_PACKAGE_NAME, Arrays.asList(DELEGATION_CERT_INSTALL))); - configureProfileOwnerForDeviceIdAccess(admin1, DpmMockContext.CALLER_USER_HANDLE); + configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE); // Make sure that the profile owner can still request Device ID attestation. mServiceContext.binder.callingUid = DpmMockContext.CALLER_UID; @@ -5435,15 +5435,16 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertTrue(dpm.isPackageAllowedToAccessCalendar(testPackage)); } - private void configureProfileOwnerForDeviceIdAccess(ComponentName who, int userId) { + private void configureProfileOwnerOfOrgOwnedDevice(ComponentName who, int userId) { when(getServices().userManager.getProfileParent(eq(UserHandle.of(userId)))) .thenReturn(UserHandle.SYSTEM); - final long ident = mServiceContext.binder.clearCallingIdentity(); mServiceContext.binder.callingUid = UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE, DpmMockContext.SYSTEM_UID); + + configureContextForAccess(mServiceContext, true); runAsCaller(mServiceContext, dpms, dpm -> { - dpm.setProfileOwnerCanAccessDeviceIds(who); + dpm.markProfileOwnerOnOrganizationOwnedDevice(who); }); mServiceContext.binder.restoreCallingIdentity(ident); }