diff options
| -rw-r--r-- | core/java/android/app/admin/DevicePolicyManager.java | 4 | ||||
| -rw-r--r-- | core/java/android/os/UserManager.java | 4 | ||||
| -rw-r--r-- | services/core/java/com/android/server/accounts/AccountManagerService.java | 60 |
3 files changed, 46 insertions, 22 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 5df6ba80a10a..eda098252aa0 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -4142,6 +4142,10 @@ public class DevicePolicyManager { * <p>When account management is disabled for an account type, adding or removing an account * of that type will not be possible. * + * <p>From {@link android.os.Build.VERSION_CODES#N} the profile or device owner can still use + * {@link android.accounts.AccountManager} APIs to add or remove accounts when account + * management for a specific type is disabled. + * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param accountType For which account management is disabled or enabled. * @param disabled The boolean indicating that account management will be disabled (true) or diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 16696af950bc..037916a94e5f 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -57,6 +57,10 @@ public class UserManager { * Authenticator. * The default value is <code>false</code>. * + * <p>From {@link android.os.Build.VERSION_CODES#N} a profile or device owner app can still + * use {@link android.accounts.AccountManager} APIs to add or remove accounts when account + * management is disallowed. + * * <p/>Key for user restrictions. * <p/>Type: Boolean * @see DevicePolicyManager#addUserRestriction(ComponentName, String) diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index ca5212ab2a5a..aa9944278134 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -37,7 +37,9 @@ import android.app.AppOpsManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; +import android.app.admin.DeviceAdminInfo; import android.app.admin.DevicePolicyManager; +import android.app.admin.DevicePolicyManagerInternal; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentValues; @@ -82,6 +84,7 @@ import com.android.internal.R; import com.android.internal.util.ArrayUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.server.FgThread; +import com.android.server.LocalServices; import com.google.android.collect.Lists; import com.google.android.collect.Sets; @@ -830,7 +833,8 @@ public class AccountManagerService throw new SecurityException(msg); } - if (!canUserModifyAccounts(userId) || !canUserModifyAccountsForType(userId, account.type)) { + if (!canUserModifyAccounts(userId, callingUid) || + !canUserModifyAccountsForType(userId, account.type, callingUid)) { return false; } @@ -1259,7 +1263,7 @@ public class AccountManagerService account.type); throw new SecurityException(msg); } - if (!canUserModifyAccounts(userId)) { + if (!canUserModifyAccounts(userId, callingUid)) { try { response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED, "User cannot modify accounts"); @@ -1267,7 +1271,7 @@ public class AccountManagerService } return; } - if (!canUserModifyAccountsForType(userId, account.type)) { + if (!canUserModifyAccountsForType(userId, account.type, callingUid)) { try { response.onError(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE, "User cannot modify accounts of this type (policy)."); @@ -1321,9 +1325,6 @@ public class AccountManagerService throw new SecurityException(msg); } UserAccounts accounts = getUserAccountsForCaller(); - if (!canUserModifyAccounts(userId) || !canUserModifyAccountsForType(userId, account.type)) { - return false; - } logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_REMOVE, TABLE_ACCOUNTS); long identityToken = clearCallingIdentity(); try { @@ -2146,8 +2147,9 @@ public class AccountManagerService if (accountType == null) throw new IllegalArgumentException("accountType is null"); // Is user disallowed from modifying accounts? - int userId = Binder.getCallingUserHandle().getIdentifier(); - if (!canUserModifyAccounts(userId)) { + final int uid = Binder.getCallingUid(); + final int userId = UserHandle.getUserId(uid); + if (!canUserModifyAccounts(userId, uid)) { try { response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED, "User is not allowed to add an account!"); @@ -2156,7 +2158,7 @@ public class AccountManagerService showCantAddAccount(AccountManager.ERROR_CODE_USER_RESTRICTED, userId); return; } - if (!canUserModifyAccountsForType(userId, accountType)) { + if (!canUserModifyAccountsForType(userId, accountType, uid)) { try { response.onError(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE, "User cannot modify accounts of this type (policy)."); @@ -2168,7 +2170,6 @@ public class AccountManagerService } final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); final Bundle options = (optionsIn == null) ? new Bundle() : optionsIn; options.putInt(AccountManager.KEY_CALLER_UID, uid); options.putInt(AccountManager.KEY_CALLER_PID, pid); @@ -2230,7 +2231,7 @@ public class AccountManagerService } // Is user disallowed from modifying accounts? - if (!canUserModifyAccounts(userId)) { + if (!canUserModifyAccounts(userId, callingUid)) { try { response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED, "User is not allowed to add an account!"); @@ -2239,7 +2240,7 @@ public class AccountManagerService showCantAddAccount(AccountManager.ERROR_CODE_USER_RESTRICTED, userId); return; } - if (!canUserModifyAccountsForType(userId, accountType)) { + if (!canUserModifyAccountsForType(userId, accountType, callingUid)) { try { response.onError(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE, "User cannot modify accounts of this type (policy)."); @@ -2310,8 +2311,9 @@ public class AccountManagerService throw new IllegalArgumentException("accountType is null"); } - int userId = Binder.getCallingUserHandle().getIdentifier(); - if (!canUserModifyAccounts(userId)) { + final int uid = Binder.getCallingUid(); + final int userId = UserHandle.getUserId(uid); + if (!canUserModifyAccounts(userId, uid)) { try { response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED, "User is not allowed to add an account!"); @@ -2320,7 +2322,7 @@ public class AccountManagerService showCantAddAccount(AccountManager.ERROR_CODE_USER_RESTRICTED, userId); return; } - if (!canUserModifyAccountsForType(userId, accountType)) { + if (!canUserModifyAccountsForType(userId, accountType, uid)) { try { response.onError(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE, "User cannot modify accounts of this type (policy)."); @@ -2332,7 +2334,6 @@ public class AccountManagerService } final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); final Bundle options = (optionsIn == null) ? new Bundle() : optionsIn; options.putInt(AccountManager.KEY_CALLER_UID, uid); options.putInt(AccountManager.KEY_CALLER_PID, pid); @@ -2497,8 +2498,9 @@ public class AccountManagerService throw new IllegalArgumentException("sessionBundle is empty"); } - int userId = Binder.getCallingUserHandle().getIdentifier(); - if (!canUserModifyAccounts(userId)) { + final int uid = Binder.getCallingUid(); + final int userId = UserHandle.getUserId(uid); + if (!canUserModifyAccounts(userId, uid)) { sendErrorResponse(response, AccountManager.ERROR_CODE_USER_RESTRICTED, "User is not allowed to add an account!"); @@ -2507,7 +2509,6 @@ public class AccountManagerService } final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); final Bundle decryptedBundle; final String accountType; // First decrypt session bundle to get account type for checking permission. @@ -2554,7 +2555,7 @@ public class AccountManagerService return; } - if (!canUserModifyAccountsForType(userId, accountType)) { + if (!canUserModifyAccountsForType(userId, accountType, uid)) { sendErrorResponse( response, AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE, @@ -4319,7 +4320,11 @@ public class AccountManagerService } } - private boolean canUserModifyAccounts(int userId) { + private boolean canUserModifyAccounts(int userId, int callingUid) { + // the managing app can always modify accounts + if (isProfileOwner(callingUid)) { + return true; + } if (getUserManager().getUserRestrictions(new UserHandle(userId)) .getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS)) { return false; @@ -4327,7 +4332,11 @@ public class AccountManagerService return true; } - private boolean canUserModifyAccountsForType(int userId, String accountType) { + private boolean canUserModifyAccountsForType(int userId, String accountType, int callingUid) { + // the managing app can always modify accounts + if (isProfileOwner(callingUid)) { + return true; + } DevicePolicyManager dpm = (DevicePolicyManager) mContext .getSystemService(Context.DEVICE_POLICY_SERVICE); String[] typesArray = dpm.getAccountTypesWithManagementDisabledAsUser(userId); @@ -4342,6 +4351,13 @@ public class AccountManagerService return true; } + private boolean isProfileOwner(int uid) { + final DevicePolicyManagerInternal dpmi = + LocalServices.getService(DevicePolicyManagerInternal.class); + return (dpmi != null) + && dpmi.isActiveAdminWithPolicy(uid, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + } + @Override public void updateAppPermission(Account account, String authTokenType, int uid, boolean value) throws RemoteException { |