Skip to content

Commit 2c7bc26

Browse files
author
Amith Yamasani
committed
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
1 parent 37238e5 commit 2c7bc26

File tree

5 files changed

+67
-16
lines changed

5 files changed

+67
-16
lines changed

core/java/android/accounts/AccountManager.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import android.os.RemoteException;
2929
import android.os.Parcelable;
3030
import android.os.Build;
31+
import android.os.Process;
32+
import android.os.UserHandle;
3133
import android.util.Log;
3234
import android.text.TextUtils;
3335

@@ -42,7 +44,6 @@
4244
import java.util.HashMap;
4345
import java.util.Map;
4446

45-
import com.google.android.collect.Lists;
4647
import com.google.android.collect.Maps;
4748

4849
/**
@@ -396,8 +397,13 @@ public Account[] getAccounts() {
396397
* (never null) if no accounts of the specified type have been added.
397398
*/
398399
public Account[] getAccountsByType(String type) {
400+
return getAccountsByTypeAsUser(type, Process.myUserHandle());
401+
}
402+
403+
/** @hide Same as {@link #getAccountsByType(String)} but for a specific user. */
404+
public Account[] getAccountsByTypeAsUser(String type, UserHandle userHandle) {
399405
try {
400-
return mService.getAccounts(type);
406+
return mService.getAccountsAsUser(type, userHandle.getIdentifier());
401407
} catch (RemoteException e) {
402408
// won't ever happen
403409
throw new RuntimeException(e);
@@ -1175,10 +1181,26 @@ public AccountManagerFuture<Bundle> confirmCredentials(final Account account,
11751181
final Activity activity,
11761182
final AccountManagerCallback<Bundle> callback,
11771183
final Handler handler) {
1184+
return confirmCredentialsAsUser(account, options, activity, callback, handler,
1185+
Process.myUserHandle());
1186+
}
1187+
1188+
/**
1189+
* @hide
1190+
* Same as {@link #confirmCredentials(Account, Bundle, Activity, AccountManagerCallback, Handler)}
1191+
* but for the specified user.
1192+
*/
1193+
public AccountManagerFuture<Bundle> confirmCredentialsAsUser(final Account account,
1194+
final Bundle options,
1195+
final Activity activity,
1196+
final AccountManagerCallback<Bundle> callback,
1197+
final Handler handler, UserHandle userHandle) {
11781198
if (account == null) throw new IllegalArgumentException("account is null");
1199+
final int userId = userHandle.getIdentifier();
11791200
return new AmsTask(activity, handler, callback) {
11801201
public void doWork() throws RemoteException {
1181-
mService.confirmCredentials(mResponse, account, options, activity != null);
1202+
mService.confirmCredentialsAsUser(mResponse, account, options, activity != null,
1203+
userId);
11821204
}
11831205
}.start();
11841206
}

core/java/android/accounts/AccountManagerService.java

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,8 +1297,17 @@ protected String toDebugString(long now) {
12971297
}
12981298
}
12991299

1300-
public void confirmCredentials(IAccountManagerResponse response,
1301-
final Account account, final Bundle options, final boolean expectActivityLaunch) {
1300+
@Override
1301+
public void confirmCredentialsAsUser(IAccountManagerResponse response,
1302+
final Account account, final Bundle options, final boolean expectActivityLaunch,
1303+
int userId) {
1304+
// Only allow the system process to read accounts of other users
1305+
if (userId != UserHandle.getCallingUserId()
1306+
&& Binder.getCallingUid() != android.os.Process.myUid()) {
1307+
throw new SecurityException("User " + UserHandle.getCallingUserId()
1308+
+ " trying to confirm account credentials for " + userId);
1309+
}
1310+
13021311
if (Log.isLoggable(TAG, Log.VERBOSE)) {
13031312
Log.v(TAG, "confirmCredentials: " + account
13041313
+ ", response " + response
@@ -1309,7 +1318,7 @@ public void confirmCredentials(IAccountManagerResponse response,
13091318
if (response == null) throw new IllegalArgumentException("response is null");
13101319
if (account == null) throw new IllegalArgumentException("account is null");
13111320
checkManageAccountsPermission();
1312-
UserAccounts accounts = getUserAccountsForCaller();
1321+
UserAccounts accounts = getUserAccounts(userId);
13131322
long identityToken = clearCallingIdentity();
13141323
try {
13151324
new Session(accounts, response, account.type, expectActivityLaunch,
@@ -1548,14 +1557,22 @@ private AccountAndUser[] getAccounts(int[] userIds) {
15481557
return runningAccounts.toArray(accountsArray);
15491558
}
15501559

1551-
public Account[] getAccounts(String type) {
1560+
@Override
1561+
public Account[] getAccountsAsUser(String type, int userId) {
1562+
// Only allow the system process to read accounts of other users
1563+
if (userId != UserHandle.getCallingUserId()
1564+
&& Binder.getCallingUid() != android.os.Process.myUid()) {
1565+
throw new SecurityException("User " + UserHandle.getCallingUserId()
1566+
+ " trying to get account for " + userId);
1567+
}
1568+
15521569
if (Log.isLoggable(TAG, Log.VERBOSE)) {
15531570
Log.v(TAG, "getAccounts: accountType " + type
15541571
+ ", caller's uid " + Binder.getCallingUid()
15551572
+ ", pid " + Binder.getCallingPid());
15561573
}
15571574
checkReadAccountsPermission();
1558-
UserAccounts accounts = getUserAccountsForCaller();
1575+
UserAccounts accounts = getUserAccounts(userId);
15591576
long identityToken = clearCallingIdentity();
15601577
try {
15611578
synchronized (accounts.cacheLock) {
@@ -1566,6 +1583,11 @@ public Account[] getAccounts(String type) {
15661583
}
15671584
}
15681585

1586+
@Override
1587+
public Account[] getAccounts(String type) {
1588+
return getAccountsAsUser(type, UserHandle.getCallingUserId());
1589+
}
1590+
15691591
public void getAccountsByFeatures(IAccountManagerResponse response,
15701592
String type, String[] features) {
15711593
if (Log.isLoggable(TAG, Log.VERBOSE)) {

core/java/android/accounts/IAccountManager.aidl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ interface IAccountManager {
3131
String getUserData(in Account account, String key);
3232
AuthenticatorDescription[] getAuthenticatorTypes();
3333
Account[] getAccounts(String accountType);
34+
Account[] getAccountsAsUser(String accountType, int userId);
3435
void hasFeatures(in IAccountManagerResponse response, in Account account, in String[] features);
3536
void getAccountsByFeatures(in IAccountManagerResponse response, String accountType, in String[] features);
3637
boolean addAccount(in Account account, String password, in Bundle extras);
@@ -53,8 +54,8 @@ interface IAccountManager {
5354
String authTokenType, boolean expectActivityLaunch, in Bundle options);
5455
void editProperties(in IAccountManagerResponse response, String accountType,
5556
boolean expectActivityLaunch);
56-
void confirmCredentials(in IAccountManagerResponse response, in Account account,
57-
in Bundle options, boolean expectActivityLaunch);
57+
void confirmCredentialsAsUser(in IAccountManagerResponse response, in Account account,
58+
in Bundle options, boolean expectActivityLaunch, int userId);
5859
void getAuthTokenLabel(in IAccountManagerResponse response, String accountType,
5960
String authTokenType);
6061
}

policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import android.content.Intent;
2828
import android.graphics.Rect;
2929
import android.os.Bundle;
30+
import android.os.UserHandle;
3031
import android.text.Editable;
3132
import android.text.InputFilter;
3233
import android.text.LoginFilter;
@@ -175,7 +176,8 @@ public void run() {
175176
Intent intent = new Intent();
176177
intent.setClassName(LOCK_PATTERN_PACKAGE, LOCK_PATTERN_CLASS);
177178
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
178-
mContext.startActivity(intent);
179+
mContext.startActivityAsUser(intent,
180+
new UserHandle(mLockPatternUtils.getCurrentUser()));
179181
mCallback.reportSuccessfulUnlockAttempt();
180182

181183
// dismiss keyguard
@@ -220,7 +222,8 @@ public boolean dispatchKeyEvent(KeyEvent event) {
220222
* find a single best match.
221223
*/
222224
private Account findIntendedAccount(String username) {
223-
Account[] accounts = AccountManager.get(mContext).getAccountsByType("com.google");
225+
Account[] accounts = AccountManager.get(mContext).getAccountsByTypeAsUser("com.google",
226+
new UserHandle(mLockPatternUtils.getCurrentUser()));
224227

225228
// Try to figure out which account they meant if they
226229
// typed only the username (and not the domain), or got
@@ -267,7 +270,7 @@ private void asyncCheckPassword() {
267270
getProgressDialog().show();
268271
Bundle options = new Bundle();
269272
options.putString(AccountManager.KEY_PASSWORD, password);
270-
AccountManager.get(mContext).confirmCredentials(account, options, null /* activity */,
273+
AccountManager.get(mContext).confirmCredentialsAsUser(account, options, null /* activity */,
271274
new AccountManagerCallback<Bundle>() {
272275
public void run(AccountManagerFuture<Bundle> future) {
273276
try {
@@ -289,7 +292,7 @@ public void run() {
289292
});
290293
}
291294
}
292-
}, null /* handler */);
295+
}, null /* handler */, new UserHandle(mLockPatternUtils.getCurrentUser()));
293296
}
294297

295298
private Dialog getProgressDialog() {

policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import android.os.Bundle;
2727
import android.os.CountDownTimer;
2828
import android.os.SystemClock;
29+
import android.os.UserHandle;
2930
import android.util.AttributeSet;
3031
import android.util.Log;
3132
import android.view.MotionEvent;
@@ -287,7 +288,8 @@ private class AccountAnalyzer implements AccountManagerCallback<Bundle> {
287288

288289
private AccountAnalyzer(AccountManager accountManager) {
289290
mAccountManager = accountManager;
290-
mAccounts = accountManager.getAccountsByType("com.google");
291+
mAccounts = accountManager.getAccountsByTypeAsUser("com.google",
292+
new UserHandle(mLockPatternUtils.getCurrentUser()));
291293
}
292294

293295
private void next() {
@@ -298,7 +300,8 @@ private void next() {
298300
}
299301

300302
// lookup the confirmCredentials intent for the current account
301-
mAccountManager.confirmCredentials(mAccounts[mAccountIndex], null, null, this, null);
303+
mAccountManager.confirmCredentialsAsUser(mAccounts[mAccountIndex], null, null, this,
304+
null, new UserHandle(mLockPatternUtils.getCurrentUser()));
302305
}
303306

304307
public void start() {

0 commit comments

Comments
 (0)