Loading core/java/android/app/admin/DevicePolicyManager.java +23 −13 Original line number Diff line number Diff line Loading @@ -1662,7 +1662,16 @@ public class DevicePolicyManager { * Force a new device unlock password (the password needed to access the * entire device, not for individual accounts) on the user. This takes * effect immediately. * The given password must be sufficient for the * * <p>Calling this from a managed profile that shares the password with the owner profile * will throw a security exception. * * <p><em>Note: This API has been limited as of {@link android.os.Build.VERSION_CODES#N} for * device admins that are not device owner and not profile owner. * The password can now only be changed if there is currently no password set. Device owner * and profile owner can still do this.</em> * * <p>The given password must be sufficient for the * current password quality and length constraints as returned by * {@link #getPasswordQuality(ComponentName)} and * {@link #getPasswordMinimumLength(ComponentName)}; if it does not meet Loading @@ -1672,19 +1681,20 @@ public class DevicePolicyManager { * the currently active quality will be increased to match. * * <p>Calling with a null or empty password will clear any existing PIN, * pattern or password if the current password constraints allow it. * pattern or password if the current password constraints allow it. <em>Note: This will not * work in {@link android.os.Build.VERSION_CODES#N} and later for device admins that are not * device owner and not profile owner. Once set, the password cannot be changed to null or * empty, except by device owner or profile owner.</em> * * <p>The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call * this method; if it has not, a security exception will be thrown. * * <p>Calling this from a managed profile will throw a security exception. * * @param password The new password for the user. Null or empty clears the password. * @param flags May be 0 or combination of {@link #RESET_PASSWORD_REQUIRE_ENTRY} and * {@link #RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT}. * @return Returns true if the password was applied, or false if it is * not acceptable for the current constraints. * not acceptable for the current constraints or if the user has not been decrypted yet. */ public boolean resetPassword(String password, int flags) { if (mService != null) { Loading Loading @@ -1792,7 +1802,7 @@ public class DevicePolicyManager { public void wipeData(int flags) { if (mService != null) { try { mService.wipeData(flags, myUserId()); mService.wipeData(flags); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } Loading Loading @@ -2668,15 +2678,15 @@ public class DevicePolicyManager { * does *not* check weather the device owner is actually running on the current user. */ public boolean isDeviceOwnerApp(String packageName) { if (mService != null) { try { return mService.isDeviceOwnerPackage(packageName); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } if (packageName == null) { return false; } final ComponentName deviceOwner = getDeviceOwnerComponent(); if (deviceOwner == null) { return false; } return packageName.equals(deviceOwner.getPackageName()); } /** * @hide Loading core/java/android/app/admin/IDevicePolicyManager.aidl +1 −2 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ interface IDevicePolicyManager { void lockNow(); void wipeData(int flags, int userHandle); void wipeData(int flags); ComponentName setGlobalProxy(in ComponentName admin, String proxySpec, String exclusionList); ComponentName getGlobalProxyAdmin(int userHandle); Loading Loading @@ -114,7 +114,6 @@ interface IDevicePolicyManager { void reportSuccessfulPasswordAttempt(int userHandle); boolean setDeviceOwner(in ComponentName who, String ownerName, int userId); boolean isDeviceOwnerPackage(String packageName); ComponentName getDeviceOwner(); String getDeviceOwnerName(); void clearDeviceOwner(String packageName); Loading services/core/java/com/android/server/pm/PackageManagerService.java +7 −1 Original line number Diff line number Diff line Loading @@ -12770,8 +12770,14 @@ public class PackageManagerService extends IPackageManager.Stub { ServiceManager.getService(Context.DEVICE_POLICY_SERVICE)); try { if (dpm != null) { final ComponentName deviceOwnerComponentName = dpm.getDeviceOwner(); final String deviceOwnerPackageName = deviceOwnerComponentName == null ? null : deviceOwnerComponentName.getPackageName(); // Does the package contains the device owner? if (dpm.isDeviceOwnerPackage(packageName)) { // TODO Do we have to do it even if userId != UserHandle.USER_ALL? Otherwise, // this check is probably not needed, since DO should be registered as a device // admin on some user too. (Original bug for this: b/17657954) if (packageName.equals(deviceOwnerPackageName)) { return true; } // Does it contain a device admin for any user? services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +108 −58 Original line number Diff line number Diff line Loading @@ -1612,25 +1612,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @VisibleForTesting boolean isActiveAdminWithPolicyForUserLocked(ActiveAdmin admin, int reqPolicy, int userId) { boolean ownsDevice = isDeviceOwner(admin.info.getComponent()); boolean ownsProfile = (getProfileOwner(userId) != null && getProfileOwner(userId).getPackageName() .equals(admin.info.getPackageName())); final boolean ownsDevice = isDeviceOwner(admin.info.getComponent(), userId); final boolean ownsProfile = isProfileOwner(admin.info.getComponent(), userId); if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) { if ((userId == UserHandle.USER_SYSTEM && ownsDevice) || (ownsDevice && ownsProfile)) { return true; } return ownsDevice; } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) { if ((userId == UserHandle.USER_SYSTEM && ownsDevice) || ownsProfile) { return true; } // DO always has the PO power. return ownsDevice || ownsProfile; } else { if (admin.info.usesPolicy(reqPolicy)) { return true; } return admin.info.usesPolicy(reqPolicy); } return false; } void sendAdminCommandLocked(ActiveAdmin admin, String action) { Loading Loading @@ -2441,8 +2433,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return; } if (admin.getUid() != mInjector.binderGetCallingUid()) { // Active device owners must remain active admins. if (isDeviceOwner(adminReceiver)) { // Active device/profile owners must remain active admins. if (isDeviceOwner(adminReceiver, userHandle) || isProfileOwner(adminReceiver, userHandle)) { return; } mContext.enforceCallingOrSelfPermission( Loading Loading @@ -3187,12 +3180,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override public boolean resetPassword(String passwordOrNull, int flags) { public boolean resetPassword(String passwordOrNull, int flags) throws RemoteException { if (!mHasFeature) { return false; } final int userHandle = UserHandle.getCallingUserId(); enforceNotManagedProfile(userHandle, "reset the password"); long ident = mInjector.binderClearCallingIdentity(); try { if (mUserManager.getCredentialOwnerProfile(userHandle) != userHandle) { throw new SecurityException("You can not change password for this profile because" + " it shares the password with the owner profile"); } } finally { mInjector.binderRestoreCallingIdentity(ident); } String password = passwordOrNull != null ? passwordOrNull : ""; Loading @@ -3200,8 +3202,35 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { synchronized (this) { // This api can only be called by an active device admin, // so try to retrieve it to check that the caller is one. getActiveAdminForCallerLocked(null, final ActiveAdmin admin = getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_RESET_PASSWORD); final ComponentName adminComponent = admin.info.getComponent(); // As of N, only profile owners and device owners can reset the password. if (!(isProfileOwner(adminComponent, userHandle) || isDeviceOwner(adminComponent, userHandle))) { final boolean preN = getTargetSdk(admin.info.getPackageName(), userHandle) < android.os.Build.VERSION_CODES.N; // As of N, password resetting to empty/null is not allowed anymore. // TODO Should we allow DO/PO to set an empty password? if (TextUtils.isEmpty(password)) { if (!preN) { throw new SecurityException("Cannot call with null password"); } else { Slog.e(LOG_TAG, "Cannot call with null password"); return false; } } // As of N, password cannot be changed by the admin if it is already set. if (isLockScreenSecureUnchecked(userHandle)) { if (!preN) { throw new SecurityException("Admin cannot change current password"); } else { Slog.e(LOG_TAG, "Admin cannot change current password"); return false; } } } quality = getPasswordQuality(null, userHandle); if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { int realQuality = LockPatternUtils.computePasswordQuality(password); Loading Loading @@ -3303,9 +3332,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // Don't do this with the lock held, because it is going to call // back in to the service. long ident = mInjector.binderClearCallingIdentity(); ident = mInjector.binderClearCallingIdentity(); try { LockPatternUtils utils = new LockPatternUtils(mContext); LockPatternUtils utils = mInjector.newLockPatternUtils(); if (!TextUtils.isEmpty(password)) { utils.saveLockPassword(password, null, quality, userHandle); } else { Loading @@ -3330,6 +3359,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return true; } private boolean isLockScreenSecureUnchecked(int userId) { long ident = mInjector.binderClearCallingIdentity(); try { return mInjector.newLockPatternUtils().isSecure(userId); } finally { mInjector.binderRestoreCallingIdentity(ident); } } private void setDoNotAskCredentialsOnBoot() { synchronized (this) { DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM); Loading Loading @@ -3685,10 +3723,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override public void wipeData(int flags, final int userHandle) { public void wipeData(int flags) { if (!mHasFeature) { return; } final int userHandle = mInjector.userHandleGetCallingUserId(); enforceCrossUserPermission(userHandle); synchronized (this) { // This API can only be called by an active device admin, Loading @@ -3701,8 +3740,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { long ident = mInjector.binderClearCallingIdentity(); try { if ((flags & WIPE_RESET_PROTECTION_DATA) != 0) { if (userHandle != UserHandle.USER_SYSTEM || !isDeviceOwner(admin.info.getComponent())) { if (!isDeviceOwner(admin.info.getComponent(), userHandle)) { throw new SecurityException( "Only device owner admins can set WIPE_RESET_PROTECTION_DATA"); } Loading Loading @@ -4325,7 +4363,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return; } Preconditions.checkNotNull(who, "ComponentName is null"); final int userHandle = UserHandle.getCallingUserId(); final int userHandle = mInjector.userHandleGetCallingUserId(); synchronized (this) { ActiveAdmin ap = getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA); Loading @@ -4337,7 +4375,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // Tell the user manager that the restrictions have changed. synchronized (mUserManagerInternal.getUserRestrictionsLock()) { synchronized (this) { if (isDeviceOwner(who)) { if (isDeviceOwner(who, userHandle)) { mUserManagerInternal.updateEffectiveUserRestrictionsForAllUsersLR(); } else { mUserManagerInternal.updateEffectiveUserRestrictionsLR(userHandle); Loading Loading @@ -4499,24 +4537,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } public boolean isDeviceOwner(ComponentName who) { if (!mHasFeature) { return false; } public boolean isDeviceOwner(ComponentName who, int userId) { synchronized (this) { return mOwners.hasDeviceOwner() && mOwners.getDeviceOwnerComponent().equals(who); return mOwners.hasDeviceOwner() && mOwners.getDeviceOwnerUserId() == userId && mOwners.getDeviceOwnerComponent().equals(who); } } @Override public boolean isDeviceOwnerPackage(String packageName) { if (!mHasFeature) { return false; } synchronized (this) { return mOwners.hasDeviceOwner() && mOwners.getDeviceOwnerComponent().getPackageName().equals(packageName); } public boolean isProfileOwner(ComponentName who, int userId) { final ComponentName profileOwner = getProfileOwner(userId); return who != null && who.equals(profileOwner); } @Override Loading Loading @@ -5637,9 +5668,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); final boolean isDeviceOwner = isDeviceOwner(who); if (!isDeviceOwner && userHandle != UserHandle.USER_SYSTEM && DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) { final boolean isDeviceOwner = isDeviceOwner(who, userHandle); if (!isDeviceOwner && DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) { throw new SecurityException( "Profile owners cannot set user restriction " + key); } Loading Loading @@ -6132,9 +6162,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Bundle adminExtras = new Bundle(); adminExtras.putString(DeviceAdminReceiver.EXTRA_LOCK_TASK_PACKAGE, pkg); for (ActiveAdmin admin : policy.mAdminList) { boolean ownsDevice = isDeviceOwner(admin.info.getComponent()); boolean ownsProfile = (getProfileOwner(userHandle) != null && getProfileOwner(userHandle).equals(admin.info.getPackageName())); final boolean ownsDevice = isDeviceOwner(admin.info.getComponent(), userHandle); final boolean ownsProfile = isProfileOwner(admin.info.getComponent(), userHandle); if (ownsDevice || ownsProfile) { if (isEnabled) { sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_LOCK_TASK_ENTERING, Loading Loading @@ -6186,13 +6215,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public void setSecureSetting(ComponentName who, String setting, String value) { Preconditions.checkNotNull(who, "ComponentName is null"); int callingUserId = UserHandle.getCallingUserId(); final ContentResolver contentResolver = mContext.getContentResolver(); int callingUserId = mInjector.userHandleGetCallingUserId(); synchronized (this) { getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); if (isDeviceOwner(who)) { if (isDeviceOwner(who, mInjector.userHandleGetCallingUserId())) { if (!SECURE_SETTINGS_DEVICEOWNER_WHITELIST.contains(setting)) { throw new SecurityException(String.format( "Permission denial: Device owners cannot update %1$s", setting)); Loading Loading @@ -6504,13 +6532,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * @param callerUid UID of the caller. * @return true if the caller is the device owner app */ private boolean isCallerDeviceOwner(int callerUid) { String[] pkgs = mContext.getPackageManager().getPackagesForUid(callerUid); @VisibleForTesting boolean isCallerDeviceOwner(int callerUid) { synchronized (this) { if (!mOwners.hasDeviceOwner()) { return false; } if (UserHandle.getUserId(callerUid) != mOwners.getDeviceOwnerUserId()) { return false; } final String deviceOwnerPackageName = mOwners.getDeviceOwnerComponent() .getPackageName(); final String[] pkgs = mContext.getPackageManager().getPackagesForUid(callerUid); for (String pkg : pkgs) { if (isDeviceOwnerPackage(pkg)) { if (deviceOwnerPackageName.equals(pkg)) { return true; } } } return false; } Loading Loading @@ -6590,10 +6631,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); long ident = mInjector.binderClearCallingIdentity(); try { final ApplicationInfo ai = mIPackageManager .getApplicationInfo(packageName, 0, user.getIdentifier()); final int targetSdkVersion = ai == null ? 0 : ai.targetSdkVersion; if (targetSdkVersion < android.os.Build.VERSION_CODES.M) { if (getTargetSdk(packageName, user.getIdentifier()) < android.os.Build.VERSION_CODES.M) { return false; } final PackageManager packageManager = mContext.getPackageManager(); Loading Loading @@ -6708,4 +6747,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } throw new IllegalArgumentException("Unknown provisioning action " + action); } /** * Returns the target sdk version number that the given packageName was built for * in the given user. */ private int getTargetSdk(String packageName, int userId) throws RemoteException { final ApplicationInfo ai = mIPackageManager .getApplicationInfo(packageName, 0, userId); final int targetSdkVersion = ai == null ? 0 : ai.targetSdkVersion; return targetSdkVersion; } } Loading
core/java/android/app/admin/DevicePolicyManager.java +23 −13 Original line number Diff line number Diff line Loading @@ -1662,7 +1662,16 @@ public class DevicePolicyManager { * Force a new device unlock password (the password needed to access the * entire device, not for individual accounts) on the user. This takes * effect immediately. * The given password must be sufficient for the * * <p>Calling this from a managed profile that shares the password with the owner profile * will throw a security exception. * * <p><em>Note: This API has been limited as of {@link android.os.Build.VERSION_CODES#N} for * device admins that are not device owner and not profile owner. * The password can now only be changed if there is currently no password set. Device owner * and profile owner can still do this.</em> * * <p>The given password must be sufficient for the * current password quality and length constraints as returned by * {@link #getPasswordQuality(ComponentName)} and * {@link #getPasswordMinimumLength(ComponentName)}; if it does not meet Loading @@ -1672,19 +1681,20 @@ public class DevicePolicyManager { * the currently active quality will be increased to match. * * <p>Calling with a null or empty password will clear any existing PIN, * pattern or password if the current password constraints allow it. * pattern or password if the current password constraints allow it. <em>Note: This will not * work in {@link android.os.Build.VERSION_CODES#N} and later for device admins that are not * device owner and not profile owner. Once set, the password cannot be changed to null or * empty, except by device owner or profile owner.</em> * * <p>The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call * this method; if it has not, a security exception will be thrown. * * <p>Calling this from a managed profile will throw a security exception. * * @param password The new password for the user. Null or empty clears the password. * @param flags May be 0 or combination of {@link #RESET_PASSWORD_REQUIRE_ENTRY} and * {@link #RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT}. * @return Returns true if the password was applied, or false if it is * not acceptable for the current constraints. * not acceptable for the current constraints or if the user has not been decrypted yet. */ public boolean resetPassword(String password, int flags) { if (mService != null) { Loading Loading @@ -1792,7 +1802,7 @@ public class DevicePolicyManager { public void wipeData(int flags) { if (mService != null) { try { mService.wipeData(flags, myUserId()); mService.wipeData(flags); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } Loading Loading @@ -2668,15 +2678,15 @@ public class DevicePolicyManager { * does *not* check weather the device owner is actually running on the current user. */ public boolean isDeviceOwnerApp(String packageName) { if (mService != null) { try { return mService.isDeviceOwnerPackage(packageName); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } if (packageName == null) { return false; } final ComponentName deviceOwner = getDeviceOwnerComponent(); if (deviceOwner == null) { return false; } return packageName.equals(deviceOwner.getPackageName()); } /** * @hide Loading
core/java/android/app/admin/IDevicePolicyManager.aidl +1 −2 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ interface IDevicePolicyManager { void lockNow(); void wipeData(int flags, int userHandle); void wipeData(int flags); ComponentName setGlobalProxy(in ComponentName admin, String proxySpec, String exclusionList); ComponentName getGlobalProxyAdmin(int userHandle); Loading Loading @@ -114,7 +114,6 @@ interface IDevicePolicyManager { void reportSuccessfulPasswordAttempt(int userHandle); boolean setDeviceOwner(in ComponentName who, String ownerName, int userId); boolean isDeviceOwnerPackage(String packageName); ComponentName getDeviceOwner(); String getDeviceOwnerName(); void clearDeviceOwner(String packageName); Loading
services/core/java/com/android/server/pm/PackageManagerService.java +7 −1 Original line number Diff line number Diff line Loading @@ -12770,8 +12770,14 @@ public class PackageManagerService extends IPackageManager.Stub { ServiceManager.getService(Context.DEVICE_POLICY_SERVICE)); try { if (dpm != null) { final ComponentName deviceOwnerComponentName = dpm.getDeviceOwner(); final String deviceOwnerPackageName = deviceOwnerComponentName == null ? null : deviceOwnerComponentName.getPackageName(); // Does the package contains the device owner? if (dpm.isDeviceOwnerPackage(packageName)) { // TODO Do we have to do it even if userId != UserHandle.USER_ALL? Otherwise, // this check is probably not needed, since DO should be registered as a device // admin on some user too. (Original bug for this: b/17657954) if (packageName.equals(deviceOwnerPackageName)) { return true; } // Does it contain a device admin for any user?
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +108 −58 Original line number Diff line number Diff line Loading @@ -1612,25 +1612,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @VisibleForTesting boolean isActiveAdminWithPolicyForUserLocked(ActiveAdmin admin, int reqPolicy, int userId) { boolean ownsDevice = isDeviceOwner(admin.info.getComponent()); boolean ownsProfile = (getProfileOwner(userId) != null && getProfileOwner(userId).getPackageName() .equals(admin.info.getPackageName())); final boolean ownsDevice = isDeviceOwner(admin.info.getComponent(), userId); final boolean ownsProfile = isProfileOwner(admin.info.getComponent(), userId); if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) { if ((userId == UserHandle.USER_SYSTEM && ownsDevice) || (ownsDevice && ownsProfile)) { return true; } return ownsDevice; } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) { if ((userId == UserHandle.USER_SYSTEM && ownsDevice) || ownsProfile) { return true; } // DO always has the PO power. return ownsDevice || ownsProfile; } else { if (admin.info.usesPolicy(reqPolicy)) { return true; } return admin.info.usesPolicy(reqPolicy); } return false; } void sendAdminCommandLocked(ActiveAdmin admin, String action) { Loading Loading @@ -2441,8 +2433,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return; } if (admin.getUid() != mInjector.binderGetCallingUid()) { // Active device owners must remain active admins. if (isDeviceOwner(adminReceiver)) { // Active device/profile owners must remain active admins. if (isDeviceOwner(adminReceiver, userHandle) || isProfileOwner(adminReceiver, userHandle)) { return; } mContext.enforceCallingOrSelfPermission( Loading Loading @@ -3187,12 +3180,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override public boolean resetPassword(String passwordOrNull, int flags) { public boolean resetPassword(String passwordOrNull, int flags) throws RemoteException { if (!mHasFeature) { return false; } final int userHandle = UserHandle.getCallingUserId(); enforceNotManagedProfile(userHandle, "reset the password"); long ident = mInjector.binderClearCallingIdentity(); try { if (mUserManager.getCredentialOwnerProfile(userHandle) != userHandle) { throw new SecurityException("You can not change password for this profile because" + " it shares the password with the owner profile"); } } finally { mInjector.binderRestoreCallingIdentity(ident); } String password = passwordOrNull != null ? passwordOrNull : ""; Loading @@ -3200,8 +3202,35 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { synchronized (this) { // This api can only be called by an active device admin, // so try to retrieve it to check that the caller is one. getActiveAdminForCallerLocked(null, final ActiveAdmin admin = getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_RESET_PASSWORD); final ComponentName adminComponent = admin.info.getComponent(); // As of N, only profile owners and device owners can reset the password. if (!(isProfileOwner(adminComponent, userHandle) || isDeviceOwner(adminComponent, userHandle))) { final boolean preN = getTargetSdk(admin.info.getPackageName(), userHandle) < android.os.Build.VERSION_CODES.N; // As of N, password resetting to empty/null is not allowed anymore. // TODO Should we allow DO/PO to set an empty password? if (TextUtils.isEmpty(password)) { if (!preN) { throw new SecurityException("Cannot call with null password"); } else { Slog.e(LOG_TAG, "Cannot call with null password"); return false; } } // As of N, password cannot be changed by the admin if it is already set. if (isLockScreenSecureUnchecked(userHandle)) { if (!preN) { throw new SecurityException("Admin cannot change current password"); } else { Slog.e(LOG_TAG, "Admin cannot change current password"); return false; } } } quality = getPasswordQuality(null, userHandle); if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { int realQuality = LockPatternUtils.computePasswordQuality(password); Loading Loading @@ -3303,9 +3332,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // Don't do this with the lock held, because it is going to call // back in to the service. long ident = mInjector.binderClearCallingIdentity(); ident = mInjector.binderClearCallingIdentity(); try { LockPatternUtils utils = new LockPatternUtils(mContext); LockPatternUtils utils = mInjector.newLockPatternUtils(); if (!TextUtils.isEmpty(password)) { utils.saveLockPassword(password, null, quality, userHandle); } else { Loading @@ -3330,6 +3359,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return true; } private boolean isLockScreenSecureUnchecked(int userId) { long ident = mInjector.binderClearCallingIdentity(); try { return mInjector.newLockPatternUtils().isSecure(userId); } finally { mInjector.binderRestoreCallingIdentity(ident); } } private void setDoNotAskCredentialsOnBoot() { synchronized (this) { DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM); Loading Loading @@ -3685,10 +3723,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override public void wipeData(int flags, final int userHandle) { public void wipeData(int flags) { if (!mHasFeature) { return; } final int userHandle = mInjector.userHandleGetCallingUserId(); enforceCrossUserPermission(userHandle); synchronized (this) { // This API can only be called by an active device admin, Loading @@ -3701,8 +3740,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { long ident = mInjector.binderClearCallingIdentity(); try { if ((flags & WIPE_RESET_PROTECTION_DATA) != 0) { if (userHandle != UserHandle.USER_SYSTEM || !isDeviceOwner(admin.info.getComponent())) { if (!isDeviceOwner(admin.info.getComponent(), userHandle)) { throw new SecurityException( "Only device owner admins can set WIPE_RESET_PROTECTION_DATA"); } Loading Loading @@ -4325,7 +4363,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return; } Preconditions.checkNotNull(who, "ComponentName is null"); final int userHandle = UserHandle.getCallingUserId(); final int userHandle = mInjector.userHandleGetCallingUserId(); synchronized (this) { ActiveAdmin ap = getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA); Loading @@ -4337,7 +4375,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // Tell the user manager that the restrictions have changed. synchronized (mUserManagerInternal.getUserRestrictionsLock()) { synchronized (this) { if (isDeviceOwner(who)) { if (isDeviceOwner(who, userHandle)) { mUserManagerInternal.updateEffectiveUserRestrictionsForAllUsersLR(); } else { mUserManagerInternal.updateEffectiveUserRestrictionsLR(userHandle); Loading Loading @@ -4499,24 +4537,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } public boolean isDeviceOwner(ComponentName who) { if (!mHasFeature) { return false; } public boolean isDeviceOwner(ComponentName who, int userId) { synchronized (this) { return mOwners.hasDeviceOwner() && mOwners.getDeviceOwnerComponent().equals(who); return mOwners.hasDeviceOwner() && mOwners.getDeviceOwnerUserId() == userId && mOwners.getDeviceOwnerComponent().equals(who); } } @Override public boolean isDeviceOwnerPackage(String packageName) { if (!mHasFeature) { return false; } synchronized (this) { return mOwners.hasDeviceOwner() && mOwners.getDeviceOwnerComponent().getPackageName().equals(packageName); } public boolean isProfileOwner(ComponentName who, int userId) { final ComponentName profileOwner = getProfileOwner(userId); return who != null && who.equals(profileOwner); } @Override Loading Loading @@ -5637,9 +5668,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); final boolean isDeviceOwner = isDeviceOwner(who); if (!isDeviceOwner && userHandle != UserHandle.USER_SYSTEM && DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) { final boolean isDeviceOwner = isDeviceOwner(who, userHandle); if (!isDeviceOwner && DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) { throw new SecurityException( "Profile owners cannot set user restriction " + key); } Loading Loading @@ -6132,9 +6162,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Bundle adminExtras = new Bundle(); adminExtras.putString(DeviceAdminReceiver.EXTRA_LOCK_TASK_PACKAGE, pkg); for (ActiveAdmin admin : policy.mAdminList) { boolean ownsDevice = isDeviceOwner(admin.info.getComponent()); boolean ownsProfile = (getProfileOwner(userHandle) != null && getProfileOwner(userHandle).equals(admin.info.getPackageName())); final boolean ownsDevice = isDeviceOwner(admin.info.getComponent(), userHandle); final boolean ownsProfile = isProfileOwner(admin.info.getComponent(), userHandle); if (ownsDevice || ownsProfile) { if (isEnabled) { sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_LOCK_TASK_ENTERING, Loading Loading @@ -6186,13 +6215,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public void setSecureSetting(ComponentName who, String setting, String value) { Preconditions.checkNotNull(who, "ComponentName is null"); int callingUserId = UserHandle.getCallingUserId(); final ContentResolver contentResolver = mContext.getContentResolver(); int callingUserId = mInjector.userHandleGetCallingUserId(); synchronized (this) { getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); if (isDeviceOwner(who)) { if (isDeviceOwner(who, mInjector.userHandleGetCallingUserId())) { if (!SECURE_SETTINGS_DEVICEOWNER_WHITELIST.contains(setting)) { throw new SecurityException(String.format( "Permission denial: Device owners cannot update %1$s", setting)); Loading Loading @@ -6504,13 +6532,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * @param callerUid UID of the caller. * @return true if the caller is the device owner app */ private boolean isCallerDeviceOwner(int callerUid) { String[] pkgs = mContext.getPackageManager().getPackagesForUid(callerUid); @VisibleForTesting boolean isCallerDeviceOwner(int callerUid) { synchronized (this) { if (!mOwners.hasDeviceOwner()) { return false; } if (UserHandle.getUserId(callerUid) != mOwners.getDeviceOwnerUserId()) { return false; } final String deviceOwnerPackageName = mOwners.getDeviceOwnerComponent() .getPackageName(); final String[] pkgs = mContext.getPackageManager().getPackagesForUid(callerUid); for (String pkg : pkgs) { if (isDeviceOwnerPackage(pkg)) { if (deviceOwnerPackageName.equals(pkg)) { return true; } } } return false; } Loading Loading @@ -6590,10 +6631,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); long ident = mInjector.binderClearCallingIdentity(); try { final ApplicationInfo ai = mIPackageManager .getApplicationInfo(packageName, 0, user.getIdentifier()); final int targetSdkVersion = ai == null ? 0 : ai.targetSdkVersion; if (targetSdkVersion < android.os.Build.VERSION_CODES.M) { if (getTargetSdk(packageName, user.getIdentifier()) < android.os.Build.VERSION_CODES.M) { return false; } final PackageManager packageManager = mContext.getPackageManager(); Loading Loading @@ -6708,4 +6747,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } throw new IllegalArgumentException("Unknown provisioning action " + action); } /** * Returns the target sdk version number that the given packageName was built for * in the given user. */ private int getTargetSdk(String packageName, int userId) throws RemoteException { final ApplicationInfo ai = mIPackageManager .getApplicationInfo(packageName, 0, userId); final int targetSdkVersion = ai == null ? 0 : ai.targetSdkVersion; return targetSdkVersion; } }