diff options
author | Amith Yamasani <yamasani@google.com> | 2013-03-30 17:07:47 -0700 |
---|---|---|
committer | Amith Yamasani <yamasani@google.com> | 2013-03-30 18:25:49 -0700 |
commit | 27db46850b708070452c0ce49daf5f79503fbde6 (patch) | |
tree | b8ee9ba7481bbd869601b8320f5070394bde13bd | |
parent | 9e8ba8f27316c793578e68fcc6632a6ea6240f4a (diff) | |
download | frameworks_base-27db46850b708070452c0ce49daf5f79503fbde6.zip frameworks_base-27db46850b708070452c0ce49daf5f79503fbde6.tar.gz frameworks_base-27db46850b708070452c0ce49daf5f79503fbde6.tar.bz2 |
Block access to accounts for limited users.
Make sure that apps that have access to restricted accounts can see them.
If they don't have access, they shouldn't be able to add a new account either.
Show an error message in the account picker if the user/app is not authorized.
Change-Id: I117c0b14d7d06c5ac4e66506df156b174567f5f3
-rw-r--r-- | api/current.txt | 1 | ||||
-rw-r--r-- | core/java/android/accounts/AccountManager.java | 21 | ||||
-rw-r--r-- | core/java/android/accounts/ChooseTypeAndAccountActivity.java | 49 | ||||
-rw-r--r-- | core/java/android/accounts/IAccountManager.aidl | 5 | ||||
-rw-r--r-- | core/java/android/os/UserManager.java | 8 | ||||
-rw-r--r-- | core/res/res/layout/app_not_authorized.xml | 56 | ||||
-rw-r--r-- | core/res/res/values/strings.xml | 7 | ||||
-rw-r--r-- | core/res/res/values/symbols.xml | 3 | ||||
-rw-r--r-- | packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java | 2 | ||||
-rw-r--r-- | packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java | 6 | ||||
-rw-r--r-- | services/java/com/android/server/accounts/AccountManagerService.java | 80 |
11 files changed, 197 insertions, 41 deletions
diff --git a/api/current.txt b/api/current.txt index 6f0575c..31acb35 100644 --- a/api/current.txt +++ b/api/current.txt @@ -16984,6 +16984,7 @@ package android.os { } public class UserManager { + method public static synchronized android.os.UserManager get(android.content.Context); method public long getSerialNumberForUser(android.os.UserHandle); method public int getUserCount(); method public android.os.UserHandle getUserForSerialNumber(long); diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index bdc882a..241a64a 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -388,6 +388,23 @@ public class AccountManager { } /** + * @hide + * For use by internal activities. Returns the list of accounts that the calling package + * is authorized to use, particularly for shared accounts. + * @param packageName package name of the calling app. + * @param uid the uid of the calling app. + * @return the accounts that are available to this package and user. + */ + public Account[] getAccountsForPackage(String packageName, int uid) { + try { + return mService.getAccountsForPackage(packageName, uid); + } catch (RemoteException re) { + // possible security exception + throw new RuntimeException(re); + } + } + + /** * Lists all accounts of a particular type. The account type is a * string token corresponding to the authenticator and useful domain * of the account. For example, there are types corresponding to Google @@ -575,7 +592,7 @@ public class AccountManager { public boolean addAccountExplicitly(Account account, String password, Bundle userdata) { if (account == null) throw new IllegalArgumentException("account is null"); try { - return mService.addAccount(account, password, userdata); + return mService.addAccountExplicitly(account, password, userdata); } catch (RemoteException e) { // won't ever happen throw new RuntimeException(e); @@ -1123,7 +1140,7 @@ public class AccountManager { return new AmsTask(activity, handler, callback) { public void doWork() throws RemoteException { - mService.addAcount(mResponse, accountType, authTokenType, + mService.addAccount(mResponse, accountType, authTokenType, requiredFeatures, activity != null, optionsIn); } }.start(); diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java index 5358bc7..2aba163 100644 --- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java +++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java @@ -18,9 +18,14 @@ package android.accounts; import com.google.android.collect.Sets; import android.app.Activity; +import android.app.ActivityManagerNative; import android.content.Intent; import android.os.Bundle; +import android.os.IBinder; import android.os.Parcelable; +import android.os.RemoteException; +import android.os.UserHandle; +import android.os.UserManager; import android.text.TextUtils; import android.util.Log; import android.view.View; @@ -29,6 +34,7 @@ import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.TextView; +import android.widget.Toast; import com.android.internal.R; @@ -119,6 +125,9 @@ public class ChooseTypeAndAccountActivity extends Activity private Parcelable[] mExistingAccounts = null; private int mSelectedItemIndex; private Button mOkButton; + private int mCallingUid; + private String mCallingPackage; + private boolean mDisallowAddAccounts; @Override public void onCreate(Bundle savedInstanceState) { @@ -128,6 +137,24 @@ public class ChooseTypeAndAccountActivity extends Activity + savedInstanceState + ")"); } + String message = null; + + try { + IBinder activityToken = getActivityToken(); + mCallingUid = ActivityManagerNative.getDefault().getLaunchedFromUid(activityToken); + mCallingPackage = ActivityManagerNative.getDefault().getLaunchedFromPackage( + activityToken); + if (mCallingUid != 0 && mCallingPackage != null) { + Bundle restrictions = UserManager.get(this) + .getUserRestrictions(new UserHandle(UserHandle.getUserId(mCallingUid))); + mDisallowAddAccounts = + restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false); + } + } catch (RemoteException re) { + // Couldn't figure out caller details + Log.w(getClass().getSimpleName(), "Unable to get caller identity \n" + re); + } + // save some items we use frequently final Intent intent = getIntent(); @@ -179,6 +206,11 @@ public class ChooseTypeAndAccountActivity extends Activity // If there are no relevant accounts and only one relevant account type go directly to // add account. Otherwise let the user choose. if (mAccounts.isEmpty()) { + if (mDisallowAddAccounts) { + setContentView(R.layout.app_not_authorized); + setTitle(R.string.error_message_title); + return; + } if (mSetOfRelevantAccountTypes.size() == 1) { runAddAccountForAuthenticator(mSetOfRelevantAccountTypes.iterator().next()); } else { @@ -296,7 +328,8 @@ public class ChooseTypeAndAccountActivity extends Activity } if (accountName == null || accountType == null) { - Account[] currentAccounts = AccountManager.get(this).getAccounts(); + Account[] currentAccounts = AccountManager.get(this).getAccountsForPackage( + mCallingPackage, mCallingUid); Set<Account> preExistingAccounts = new HashSet<Account>(); for (Parcelable accountParcel : mExistingAccounts) { preExistingAccounts.add((Account) accountParcel); @@ -347,7 +380,8 @@ public class ChooseTypeAndAccountActivity extends Activity AccountManager.KEY_INTENT); if (intent != null) { mPendingRequest = REQUEST_ADD_ACCOUNT; - mExistingAccounts = AccountManager.get(this).getAccounts(); + mExistingAccounts = AccountManager.get(this).getAccountsForPackage(mCallingPackage, + mCallingUid); intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK); startActivityForResult(intent, REQUEST_ADD_ACCOUNT); return; @@ -424,12 +458,14 @@ public class ChooseTypeAndAccountActivity extends Activity private String[] getListOfDisplayableOptions(ArrayList<Account> accounts) { // List of options includes all accounts found together with "Add new account" as the // last item in the list. - String[] listItems = new String[accounts.size() + 1]; + String[] listItems = new String[accounts.size() + (mDisallowAddAccounts ? 0 : 1)]; for (int i = 0; i < accounts.size(); i++) { listItems[i] = accounts.get(i).name; } - listItems[accounts.size()] = getResources().getString( - R.string.add_account_button_label); + if (!mDisallowAddAccounts) { + listItems[accounts.size()] = getResources().getString( + R.string.add_account_button_label); + } return listItems; } @@ -439,7 +475,8 @@ public class ChooseTypeAndAccountActivity extends Activity * allowable accounts, if provided. */ private ArrayList<Account> getAcceptableAccountChoices(AccountManager accountManager) { - final Account[] accounts = accountManager.getAccounts(); + final Account[] accounts = accountManager.getAccountsForPackage(mCallingPackage, + mCallingUid); ArrayList<Account> accountsToPopulate = new ArrayList<Account>(accounts.length); for (Account account : accounts) { if (mSetOfAllowableAccounts != null diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl index 47b257d..8141813 100644 --- a/core/java/android/accounts/IAccountManager.aidl +++ b/core/java/android/accounts/IAccountManager.aidl @@ -31,10 +31,11 @@ interface IAccountManager { String getUserData(in Account account, String key); AuthenticatorDescription[] getAuthenticatorTypes(); Account[] getAccounts(String accountType); + Account[] getAccountsForPackage(String packageName, int uid); Account[] getAccountsAsUser(String accountType, int userId); void hasFeatures(in IAccountManagerResponse response, in Account account, in String[] features); void getAccountsByFeatures(in IAccountManagerResponse response, String accountType, in String[] features); - boolean addAccount(in Account account, String password, in Bundle extras); + boolean addAccountExplicitly(in Account account, String password, in Bundle extras); void removeAccount(in IAccountManagerResponse response, in Account account); void invalidateAuthToken(String accountType, String authToken); String peekAuthToken(in Account account, String authTokenType); @@ -47,7 +48,7 @@ interface IAccountManager { void getAuthToken(in IAccountManagerResponse response, in Account account, String authTokenType, boolean notifyOnAuthFailure, boolean expectActivityLaunch, in Bundle options); - void addAcount(in IAccountManagerResponse response, String accountType, + void addAccount(in IAccountManagerResponse response, String accountType, String authTokenType, in String[] requiredFeatures, boolean expectActivityLaunch, in Bundle options); void updateCredentials(in IAccountManagerResponse response, in Account account, diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 1ba16bd..b9b8f08 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -121,6 +121,14 @@ public class UserManager { */ public static final String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer"; + private static UserManager sInstance = null; + + public synchronized static UserManager get(Context context) { + if (sInstance == null) { + sInstance = (UserManager) context.getSystemService(Context.USER_SERVICE); + } + return sInstance; + } /** @hide */ public UserManager(Context context, IUserManager service) { diff --git a/core/res/res/layout/app_not_authorized.xml b/core/res/res/layout/app_not_authorized.xml new file mode 100644 index 0000000..bd40eeb --- /dev/null +++ b/core/res/res/layout/app_not_authorized.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2013, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <!-- Customizable description text --> + <TextView android:id="@+id/description" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceMedium" + android:layout_gravity="start|center_vertical" + android:paddingTop="16dip" + android:paddingBottom="16dip" + android:paddingStart="16dip" + android:paddingEnd="16dip" + android:text="@string/app_no_restricted_accounts" + /> + + <!-- Horizontal divider line --> + <View android:layout_height="1dip" + android:layout_width="match_parent" + android:background="?android:attr/dividerHorizontal" /> + + <!-- Alert dialog style buttons along the bottom. --> + <LinearLayout android:id="@+id/button_bar" + style="?android:attr/buttonBarStyle" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:measureWithLargestChild="true"> + <Button android:id="@android:id/button1" + style="?android:attr/buttonBarButtonStyle" + android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_weight="1" + android:text="@android:string/yes" + android:onClick="onCancelButtonClicked" /> + </LinearLayout> +</LinearLayout> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 9e10661..4a15967 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4063,5 +4063,10 @@ <string name="user_switched">Current user <xliff:g id="name" example="Bob">%1$s</xliff:g>.</string> <!-- Default name of the owner user [CHAR LIMIT=20] --> <string name="owner_name" msgid="3879126011135546571">Owner</string> - + <!-- Error message title [CHAR LIMIT=35] --> + <string name="error_message_title">Error</string> + <!-- Message informing user that app is not permitted to access accounts. [CHAR LIMIT=none] --> + <string name="app_no_restricted_accounts">This application does not support accounts for limited users</string> + <!-- Message informing user that the requested activity could not be found [CHAR LIMIT=none] --> + <string name="app_not_found">No application found to handle this action</string> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 81baaf8..757bbc8 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -869,7 +869,7 @@ <java-symbol type="string" name="config_chooseAccountActivity" /> <java-symbol type="string" name="config_chooseTypeAndAccountActivity" /> <java-symbol type="string" name="config_appsAuthorizedForSharedAccounts" /> - + <java-symbol type="string" name="error_message_title" /> <java-symbol type="plurals" name="abbrev_in_num_days" /> <java-symbol type="plurals" name="abbrev_in_num_hours" /> @@ -1121,6 +1121,7 @@ <java-symbol type="layout" name="sms_short_code_confirmation_dialog" /> <java-symbol type="layout" name="keyguard_add_widget" /> <java-symbol type="layout" name="action_bar_up_container" /> + <java-symbol type="layout" name="app_not_authorized" /> <java-symbol type="anim" name="slide_in_child_bottom" /> <java-symbol type="anim" name="slide_in_right" /> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 45319a8..659651b 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -322,7 +322,7 @@ public class SettingsProvider extends ContentProvider { @Override public boolean onCreate() { mBackupManager = new BackupManager(getContext()); - mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + mUserManager = UserManager.get(getContext()); setAppOps(AppOpsManager.OP_NONE, AppOpsManager.OP_WRITE_SETTINGS); establishDbTracking(UserHandle.USER_OWNER); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java index 60e22c5..a7c7fba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java @@ -206,8 +206,7 @@ class QuickSettings { mUserInfoTask = new AsyncTask<Void, Void, Pair<String, Drawable>>() { @Override protected Pair<String, Drawable> doInBackground(Void... params) { - final UserManager um = - (UserManager) mContext.getSystemService(Context.USER_SERVICE); + final UserManager um = UserManager.get(mContext); // Fall back to the UserManager nickname if we can't read the name from the local // profile below. @@ -292,8 +291,7 @@ class QuickSettings { @Override public void onClick(View v) { mBar.collapseAllPanels(true); - final UserManager um = - (UserManager) mContext.getSystemService(Context.USER_SERVICE); + final UserManager um = UserManager.get(mContext); if (um.getUsers(true).size() > 1) { try { WindowManagerGlobal.getWindowManagerService().lockNow(null); diff --git a/services/java/com/android/server/accounts/AccountManagerService.java b/services/java/com/android/server/accounts/AccountManagerService.java index 944bf33..5009793 100644 --- a/services/java/com/android/server/accounts/AccountManagerService.java +++ b/services/java/com/android/server/accounts/AccountManagerService.java @@ -58,6 +58,7 @@ import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; @@ -270,7 +271,7 @@ public class AccountManagerService private UserManager getUserManager() { if (mUserManager == null) { - mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + mUserManager = UserManager.get(mContext); } return mUserManager; } @@ -542,9 +543,9 @@ public class AccountManagerService } @Override - public boolean addAccount(Account account, String password, Bundle extras) { + public boolean addAccountExplicitly(Account account, String password, Bundle extras) { if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "addAccount: " + account + Log.v(TAG, "addAccountExplicitly: " + account + ", caller's uid " + Binder.getCallingUid() + ", pid " + Binder.getCallingPid()); } @@ -1167,7 +1168,7 @@ public class AccountManagerService final int callingUid = getCallingUid(); clearCallingIdentity(); - if (callingUid != android.os.Process.SYSTEM_UID) { + if (callingUid != Process.SYSTEM_UID) { throw new SecurityException("can only call from system"); } UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid)); @@ -1395,7 +1396,7 @@ public class AccountManagerService return id; } - public void addAcount(final IAccountManagerResponse response, final String accountType, + public void addAccount(final IAccountManagerResponse response, final String accountType, final String authTokenType, final String[] requiredFeatures, final boolean expectActivityLaunch, final Bundle optionsIn) { if (Log.isLoggable(TAG, Log.VERBOSE)) { @@ -1412,7 +1413,7 @@ public class AccountManagerService checkManageAccountsPermission(); // Is user disallowed from modifying accounts? - if (getUserManager().hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) { + if (!canUserModifyAccounts(Binder.getCallingUid())) { try { response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED, "User is not allowed to add an account!"); @@ -1457,7 +1458,7 @@ public class AccountManagerService int userId) { // Only allow the system process to read accounts of other users if (userId != UserHandle.getCallingUserId() - && Binder.getCallingUid() != android.os.Process.myUid()) { + && Binder.getCallingUid() != Process.myUid()) { throw new SecurityException("User " + UserHandle.getCallingUserId() + " trying to confirm account credentials for " + userId); } @@ -1573,7 +1574,8 @@ public class AccountManagerService public void run() throws RemoteException { synchronized (mAccounts.cacheLock) { - mAccountsOfType = getAccountsFromCacheLocked(mAccounts, mAccountType, mCallingUid); + mAccountsOfType = getAccountsFromCacheLocked(mAccounts, mAccountType, mCallingUid, + null); } // check whether each account matches the requested features mAccountsWithFeatures = new ArrayList<Account>(mAccountsOfType.length); @@ -1662,7 +1664,7 @@ public class AccountManagerService long identityToken = clearCallingIdentity(); try { synchronized (accounts.cacheLock) { - return getAccountsFromCacheLocked(accounts, null, callingUid); + return getAccountsFromCacheLocked(accounts, null, callingUid, null); } } finally { restoreCallingIdentity(identityToken); @@ -1703,7 +1705,7 @@ public class AccountManagerService if (userAccounts == null) continue; synchronized (userAccounts.cacheLock) { Account[] accounts = getAccountsFromCacheLocked(userAccounts, null, - Binder.getCallingUid()); + Binder.getCallingUid(), null); for (int a = 0; a < accounts.length; a++) { runningAccounts.add(new AccountAndUser(accounts[a], userId)); } @@ -1717,10 +1719,15 @@ public class AccountManagerService @Override public Account[] getAccountsAsUser(String type, int userId) { - final int callingUid = Binder.getCallingUid(); + return getAccountsAsUser(type, userId, null, -1); + } + + private Account[] getAccountsAsUser(String type, int userId, String callingPackage, + int packageUid) { + int callingUid = Binder.getCallingUid(); // Only allow the system process to read accounts of other users if (userId != UserHandle.getCallingUserId() - && callingUid != android.os.Process.myUid()) { + && callingUid != Process.myUid()) { throw new SecurityException("User " + UserHandle.getCallingUserId() + " trying to get account for " + userId); } @@ -1730,12 +1737,17 @@ public class AccountManagerService + ", caller's uid " + Binder.getCallingUid() + ", pid " + Binder.getCallingPid()); } + // If the original calling app was using the framework account chooser activity, we'll + // be passed in the original caller's uid here, which is what should be used for filtering. + if (packageUid != -1 && UserHandle.isSameApp(callingUid, Process.myUid())) { + callingUid = packageUid; + } checkReadAccountsPermission(); UserAccounts accounts = getUserAccounts(userId); long identityToken = clearCallingIdentity(); try { synchronized (accounts.cacheLock) { - return getAccountsFromCacheLocked(accounts, type, callingUid); + return getAccountsFromCacheLocked(accounts, type, callingUid, callingPackage); } } finally { restoreCallingIdentity(identityToken); @@ -1806,6 +1818,16 @@ public class AccountManagerService return getAccountsAsUser(type, UserHandle.getCallingUserId()); } + @Override + public Account[] getAccountsForPackage(String packageName, int uid) { + int callingUid = Binder.getCallingUid(); + if (!UserHandle.isSameApp(callingUid, Process.myUid())) { + throw new SecurityException("getAccountsForPackage() called from unauthorized uid " + + callingUid + " with uid=" + uid); + } + return getAccountsAsUser(null, UserHandle.getCallingUserId(), packageName, uid); + } + public void getAccountsByFeatures(IAccountManagerResponse response, String type, String[] features) { if (Log.isLoggable(TAG, Log.VERBOSE)) { @@ -1825,7 +1847,7 @@ public class AccountManagerService if (features == null || features.length == 0) { Account[] accounts; synchronized (userAccounts.cacheLock) { - accounts = getAccountsFromCacheLocked(userAccounts, type, callingUid); + accounts = getAccountsFromCacheLocked(userAccounts, type, callingUid, null); } Bundle result = new Bundle(); result.putParcelableArray(AccountManager.KEY_ACCOUNTS, accounts); @@ -2348,7 +2370,7 @@ public class AccountManagerService } } else { Account[] accounts = getAccountsFromCacheLocked(userAccounts, null /* type */, - android.os.Process.myUid()); + Process.myUid(), null); fout.println("Accounts: " + accounts.length); for (Account account : accounts) { fout.println(" " + account); @@ -2501,7 +2523,7 @@ public class AccountManagerService private boolean hasExplicitlyGrantedPermission(Account account, String authTokenType, int callerUid) { - if (callerUid == android.os.Process.SYSTEM_UID) { + if (callerUid == Process.SYSTEM_UID) { return true; } UserAccounts accounts = getUserAccountsForCaller(); @@ -2554,8 +2576,10 @@ public class AccountManagerService } private boolean canUserModifyAccounts(int callingUid) { - if (callingUid != android.os.Process.myUid()) { - if (getUserManager().hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) { + if (callingUid != Process.myUid()) { + if (getUserManager().getUserRestrictions( + new UserHandle(UserHandle.getUserId(callingUid))) + .getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS)) { return false; } } @@ -2566,7 +2590,7 @@ public class AccountManagerService throws RemoteException { final int callingUid = getCallingUid(); - if (callingUid != android.os.Process.SYSTEM_UID) { + if (callingUid != Process.SYSTEM_UID) { throw new SecurityException(); } @@ -2686,9 +2710,9 @@ public class AccountManagerService } private Account[] filterSharedAccounts(UserAccounts userAccounts, Account[] unfiltered, - int callingUid) { + int callingUid, String callingPackage) { if (getUserManager() == null || userAccounts == null || userAccounts.userId < 0 - || callingUid == android.os.Process.myUid()) { + || callingUid == Process.myUid()) { return unfiltered; } if (mUserManager.getUserInfo(userAccounts.userId).isRestricted()) { @@ -2712,6 +2736,10 @@ public class AccountManagerService PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0); if (pi != null && pi.restrictedAccountType != null) { requiredAccountType = pi.restrictedAccountType; + // If it matches the package name of the original caller, use this choice. + if (callingPackage != null && packageName.equals(callingPackage)) { + break; + } } } } catch (NameNotFoundException nnfe) { @@ -2740,15 +2768,19 @@ public class AccountManagerService } } + /* + * packageName can be null. If not null, it should be used to filter out restricted accounts + * that the package is not allowed to access. + */ protected Account[] getAccountsFromCacheLocked(UserAccounts userAccounts, String accountType, - int callingUid) { + int callingUid, String callingPackage) { if (accountType != null) { final Account[] accounts = userAccounts.accountCache.get(accountType); if (accounts == null) { return EMPTY_ACCOUNT_ARRAY; } else { return filterSharedAccounts(userAccounts, Arrays.copyOf(accounts, accounts.length), - callingUid); + callingUid, callingPackage); } } else { int totalLength = 0; @@ -2765,7 +2797,7 @@ public class AccountManagerService accountsOfType.length); totalLength += accountsOfType.length; } - return filterSharedAccounts(userAccounts, accounts, callingUid); + return filterSharedAccounts(userAccounts, accounts, callingUid, callingPackage); } } |