From 2c7bc26a7447e6ac9eadcf328259aa3bb1be2949 Mon Sep 17 00:00:00 2001 From: Amith Yamasani Date: Mon, 5 Nov 2012 16:46:02 -0800 Subject: [PATCH] Authenticate correct user's account when pattern fails multiple times. Bug: 7473142 Provide hidden methods in AccountManager for querying accounts and authenticating for a specific user. Lockscreen is running in the system process. Allow only system process to access accounts across users. Also make sure to launch the lock settings screen on the just reset user using startActivityAsUser() Change-Id: Ifefc0039ba2b51396b8bd0268f36d5271a3d8676 --- .../java/android/accounts/AccountManager.java | 28 ++++++++++++++-- .../accounts/AccountManagerService.java | 32 ++++++++++++++++--- .../android/accounts/IAccountManager.aidl | 5 +-- .../impl/keyguard/KeyguardAccountView.java | 11 ++++--- .../impl/keyguard/KeyguardPatternView.java | 7 ++-- 5 files changed, 67 insertions(+), 16 deletions(-) diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index f3c6566eaf769..bcb35d5fdaf0d 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -28,6 +28,8 @@ import android.os.Looper; import android.os.RemoteException; import android.os.Parcelable; import android.os.Build; +import android.os.Process; +import android.os.UserHandle; import android.util.Log; import android.text.TextUtils; @@ -42,7 +44,6 @@ import java.util.concurrent.TimeUnit; import java.util.HashMap; import java.util.Map; -import com.google.android.collect.Lists; import com.google.android.collect.Maps; /** @@ -396,8 +397,13 @@ public class AccountManager { * (never null) if no accounts of the specified type have been added. */ public Account[] getAccountsByType(String type) { + return getAccountsByTypeAsUser(type, Process.myUserHandle()); + } + + /** @hide Same as {@link #getAccountsByType(String)} but for a specific user. */ + public Account[] getAccountsByTypeAsUser(String type, UserHandle userHandle) { try { - return mService.getAccounts(type); + return mService.getAccountsAsUser(type, userHandle.getIdentifier()); } catch (RemoteException e) { // won't ever happen throw new RuntimeException(e); @@ -1175,10 +1181,26 @@ public class AccountManager { final Activity activity, final AccountManagerCallback callback, final Handler handler) { + return confirmCredentialsAsUser(account, options, activity, callback, handler, + Process.myUserHandle()); + } + + /** + * @hide + * Same as {@link #confirmCredentials(Account, Bundle, Activity, AccountManagerCallback, Handler)} + * but for the specified user. + */ + public AccountManagerFuture confirmCredentialsAsUser(final Account account, + final Bundle options, + final Activity activity, + final AccountManagerCallback callback, + final Handler handler, UserHandle userHandle) { if (account == null) throw new IllegalArgumentException("account is null"); + final int userId = userHandle.getIdentifier(); return new AmsTask(activity, handler, callback) { public void doWork() throws RemoteException { - mService.confirmCredentials(mResponse, account, options, activity != null); + mService.confirmCredentialsAsUser(mResponse, account, options, activity != null, + userId); } }.start(); } diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java index 03e0c0fc04a65..2b1a2b21c5a3e 100644 --- a/core/java/android/accounts/AccountManagerService.java +++ b/core/java/android/accounts/AccountManagerService.java @@ -1297,8 +1297,17 @@ public class AccountManagerService } } - public void confirmCredentials(IAccountManagerResponse response, - final Account account, final Bundle options, final boolean expectActivityLaunch) { + @Override + public void confirmCredentialsAsUser(IAccountManagerResponse response, + final Account account, final Bundle options, final boolean expectActivityLaunch, + int userId) { + // Only allow the system process to read accounts of other users + if (userId != UserHandle.getCallingUserId() + && Binder.getCallingUid() != android.os.Process.myUid()) { + throw new SecurityException("User " + UserHandle.getCallingUserId() + + " trying to confirm account credentials for " + userId); + } + if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "confirmCredentials: " + account + ", response " + response @@ -1309,7 +1318,7 @@ public class AccountManagerService if (response == null) throw new IllegalArgumentException("response is null"); if (account == null) throw new IllegalArgumentException("account is null"); checkManageAccountsPermission(); - UserAccounts accounts = getUserAccountsForCaller(); + UserAccounts accounts = getUserAccounts(userId); long identityToken = clearCallingIdentity(); try { new Session(accounts, response, account.type, expectActivityLaunch, @@ -1548,14 +1557,22 @@ public class AccountManagerService return runningAccounts.toArray(accountsArray); } - public Account[] getAccounts(String type) { + @Override + public Account[] getAccountsAsUser(String type, int userId) { + // Only allow the system process to read accounts of other users + if (userId != UserHandle.getCallingUserId() + && Binder.getCallingUid() != android.os.Process.myUid()) { + throw new SecurityException("User " + UserHandle.getCallingUserId() + + " trying to get account for " + userId); + } + if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "getAccounts: accountType " + type + ", caller's uid " + Binder.getCallingUid() + ", pid " + Binder.getCallingPid()); } checkReadAccountsPermission(); - UserAccounts accounts = getUserAccountsForCaller(); + UserAccounts accounts = getUserAccounts(userId); long identityToken = clearCallingIdentity(); try { synchronized (accounts.cacheLock) { @@ -1566,6 +1583,11 @@ public class AccountManagerService } } + @Override + public Account[] getAccounts(String type) { + return getAccountsAsUser(type, UserHandle.getCallingUserId()); + } + public void getAccountsByFeatures(IAccountManagerResponse response, String type, String[] features) { if (Log.isLoggable(TAG, Log.VERBOSE)) { diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl index 60073217c3f40..dbb492424acb3 100644 --- a/core/java/android/accounts/IAccountManager.aidl +++ b/core/java/android/accounts/IAccountManager.aidl @@ -31,6 +31,7 @@ interface IAccountManager { String getUserData(in Account account, String key); AuthenticatorDescription[] getAuthenticatorTypes(); Account[] getAccounts(String accountType); + 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); @@ -53,8 +54,8 @@ interface IAccountManager { String authTokenType, boolean expectActivityLaunch, in Bundle options); void editProperties(in IAccountManagerResponse response, String accountType, boolean expectActivityLaunch); - void confirmCredentials(in IAccountManagerResponse response, in Account account, - in Bundle options, boolean expectActivityLaunch); + void confirmCredentialsAsUser(in IAccountManagerResponse response, in Account account, + in Bundle options, boolean expectActivityLaunch, int userId); void getAuthTokenLabel(in IAccountManagerResponse response, String accountType, String authTokenType); } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java index 9c877550d4e08..c487ddf00d6e2 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java @@ -27,6 +27,7 @@ import android.content.Context; import android.content.Intent; import android.graphics.Rect; import android.os.Bundle; +import android.os.UserHandle; import android.text.Editable; import android.text.InputFilter; import android.text.LoginFilter; @@ -175,7 +176,8 @@ public class KeyguardAccountView extends LinearLayout implements KeyguardSecurit Intent intent = new Intent(); intent.setClassName(LOCK_PATTERN_PACKAGE, LOCK_PATTERN_CLASS); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mContext.startActivity(intent); + mContext.startActivityAsUser(intent, + new UserHandle(mLockPatternUtils.getCurrentUser())); mCallback.reportSuccessfulUnlockAttempt(); // dismiss keyguard @@ -220,7 +222,8 @@ public class KeyguardAccountView extends LinearLayout implements KeyguardSecurit * find a single best match. */ private Account findIntendedAccount(String username) { - Account[] accounts = AccountManager.get(mContext).getAccountsByType("com.google"); + Account[] accounts = AccountManager.get(mContext).getAccountsByTypeAsUser("com.google", + new UserHandle(mLockPatternUtils.getCurrentUser())); // Try to figure out which account they meant if they // typed only the username (and not the domain), or got @@ -267,7 +270,7 @@ public class KeyguardAccountView extends LinearLayout implements KeyguardSecurit getProgressDialog().show(); Bundle options = new Bundle(); options.putString(AccountManager.KEY_PASSWORD, password); - AccountManager.get(mContext).confirmCredentials(account, options, null /* activity */, + AccountManager.get(mContext).confirmCredentialsAsUser(account, options, null /* activity */, new AccountManagerCallback() { public void run(AccountManagerFuture future) { try { @@ -289,7 +292,7 @@ public class KeyguardAccountView extends LinearLayout implements KeyguardSecurit }); } } - }, null /* handler */); + }, null /* handler */, new UserHandle(mLockPatternUtils.getCurrentUser())); } private Dialog getProgressDialog() { diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java index 82cb44baa9456..52768d2f216a8 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java @@ -26,6 +26,7 @@ import android.graphics.Rect; import android.os.Bundle; import android.os.CountDownTimer; import android.os.SystemClock; +import android.os.UserHandle; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; @@ -287,7 +288,8 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit private AccountAnalyzer(AccountManager accountManager) { mAccountManager = accountManager; - mAccounts = accountManager.getAccountsByType("com.google"); + mAccounts = accountManager.getAccountsByTypeAsUser("com.google", + new UserHandle(mLockPatternUtils.getCurrentUser())); } private void next() { @@ -298,7 +300,8 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit } // lookup the confirmCredentials intent for the current account - mAccountManager.confirmCredentials(mAccounts[mAccountIndex], null, null, this, null); + mAccountManager.confirmCredentialsAsUser(mAccounts[mAccountIndex], null, null, this, + null, new UserHandle(mLockPatternUtils.getCurrentUser())); } public void start() {