summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorFred Quintana <fredq@google.com>2012-05-23 12:37:00 -0700
committerFred Quintana <fredq@google.com>2012-05-24 14:34:43 -0700
commitd9640ec712806508877868d08aafaa2d715ff441 (patch)
tree7f48982b04add7d3ebd4c82bf1cee0595a29d40a /core/java
parentc1cabdfbbb5de2c286fc9a4fe995b7b630a74a0d (diff)
downloadframeworks_base-d9640ec712806508877868d08aafaa2d715ff441.zip
frameworks_base-d9640ec712806508877868d08aafaa2d715ff441.tar.gz
frameworks_base-d9640ec712806508877868d08aafaa2d715ff441.tar.bz2
Add an updateAppPermission() API call to the AccountManagerService AIDL
and have the GrantCredentialsPermissionActivity call that instead of a static so that it can be made to run in a different process than the AccountManagerService. Protect this call by checking that the caller has the same UID as the system process. Bug: 6545417 Change-Id: I295e65cad68883349a47e7927c171af45c89b229
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/accounts/AccountManager.java49
-rw-r--r--core/java/android/accounts/AccountManagerService.java39
-rw-r--r--core/java/android/accounts/GrantCredentialsPermissionActivity.java70
-rw-r--r--core/java/android/accounts/IAccountManager.aidl3
4 files changed, 124 insertions, 37 deletions
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 150880c..39e83e0 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -405,6 +405,55 @@ public class AccountManager {
}
/**
+ * Change whether or not an app (identified by its uid) is allowed to retrieve an authToken
+ * for an account.
+ * <p>
+ * This is only meant to be used by system activities and is not in the SDK.
+ * @param account The account whose permissions are being modified
+ * @param authTokenType The type of token whose permissions are being modified
+ * @param uid The uid that identifies the app which is being granted or revoked permission.
+ * @param value true is permission is being granted, false for revoked
+ * @hide
+ */
+ public void updateAppPermission(Account account, String authTokenType, int uid, boolean value) {
+ try {
+ mService.updateAppPermission(account, authTokenType, uid, value);
+ } catch (RemoteException e) {
+ // won't ever happen
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Get the user-friendly label associated with an authenticator's auth token.
+ * @param accountType the type of the authenticator. must not be null.
+ * @param authTokenType the token type. must not be null.
+ * @param callback callback to invoke when the result is available. may be null.
+ * @param handler the handler on which to invoke the callback, or null for the main thread
+ * @return a future containing the label string
+ * @hide
+ */
+ public AccountManagerFuture<String> getAuthTokenLabel(
+ final String accountType, final String authTokenType,
+ AccountManagerCallback<String> callback, Handler handler) {
+ if (accountType == null) throw new IllegalArgumentException("accountType is null");
+ if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
+ return new Future2Task<String>(handler, callback) {
+ public void doWork() throws RemoteException {
+ mService.getAuthTokenLabel(mResponse, accountType, authTokenType);
+ }
+
+ @Override
+ public String bundleToResult(Bundle bundle) throws AuthenticatorException {
+ if (!bundle.containsKey(KEY_AUTH_TOKEN_LABEL)) {
+ throw new AuthenticatorException("no result in response");
+ }
+ return bundle.getString(KEY_AUTH_TOKEN_LABEL);
+ }
+ }.start();
+ }
+
+ /**
* Finds out whether a particular account has all the specified features.
* Account features are authenticator-specific string tokens identifying
* boolean account properties. For example, features are used to tell
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 2b643c2..ad4b58f 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -985,21 +985,25 @@ public class AccountManagerService
}
}
- void getAuthTokenLabel(final IAccountManagerResponse response,
- final Account account,
- final String authTokenType, int uid) {
- if (account == null) throw new IllegalArgumentException("account is null");
+ public void getAuthTokenLabel(IAccountManagerResponse response, final String accountType,
+ final String authTokenType)
+ throws RemoteException {
+ if (accountType == null) throw new IllegalArgumentException("accountType is null");
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
- checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
- UserAccounts accounts = getUserAccounts(UserId.getUserId(uid));
+ final int callingUid = getCallingUid();
+ clearCallingIdentity();
+ if (callingUid != android.os.Process.SYSTEM_UID) {
+ throw new SecurityException("can only call from system");
+ }
+ UserAccounts accounts = getUserAccounts(UserId.getUserId(callingUid));
long identityToken = clearCallingIdentity();
try {
- new Session(accounts, response, account.type, false,
+ new Session(accounts, response, accountType, false,
false /* stripAuthTokenFromResult */) {
protected String toDebugString(long now) {
return super.toDebugString(now) + ", getAuthTokenLabel"
- + ", " + account
+ + ", " + accountType
+ ", authTokenType " + authTokenType;
}
@@ -2230,6 +2234,21 @@ public class AccountManagerService
Manifest.permission.USE_CREDENTIALS);
}
+ public void updateAppPermission(Account account, String authTokenType, int uid, boolean value)
+ throws RemoteException {
+ final int callingUid = getCallingUid();
+
+ if (callingUid != android.os.Process.SYSTEM_UID) {
+ throw new SecurityException();
+ }
+
+ if (value) {
+ grantAppPermission(account, authTokenType, uid);
+ } else {
+ revokeAppPermission(account, authTokenType, uid);
+ }
+ }
+
/**
* Allow callers with the given uid permission to get credentials for account/authTokenType.
* <p>
@@ -2237,7 +2256,7 @@ public class AccountManagerService
* which is in the system. This means we don't need to protect it with permissions.
* @hide
*/
- public void grantAppPermission(Account account, String authTokenType, int uid) {
+ private void grantAppPermission(Account account, String authTokenType, int uid) {
if (account == null || authTokenType == null) {
Log.e(TAG, "grantAppPermission: called with invalid arguments", new Exception());
return;
@@ -2271,7 +2290,7 @@ public class AccountManagerService
* which is in the system. This means we don't need to protect it with permissions.
* @hide
*/
- public void revokeAppPermission(Account account, String authTokenType, int uid) {
+ private void revokeAppPermission(Account account, String authTokenType, int uid) {
if (account == null || authTokenType == null) {
Log.e(TAG, "revokeAppPermission: called with invalid arguments", new Exception());
return;
diff --git a/core/java/android/accounts/GrantCredentialsPermissionActivity.java b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
index 4419c8c..8b01c6a 100644
--- a/core/java/android/accounts/GrantCredentialsPermissionActivity.java
+++ b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
@@ -16,22 +16,22 @@
package android.accounts;
import android.app.Activity;
+import android.content.pm.RegisteredServicesCache;
+import android.content.res.Resources;
import android.os.Bundle;
-import android.os.RemoteException;
import android.widget.TextView;
import android.widget.LinearLayout;
-import android.widget.ImageView;
import android.view.View;
import android.view.LayoutInflater;
-import android.view.Window;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.content.pm.RegisteredServicesCache;
import android.text.TextUtils;
-import android.graphics.drawable.Drawable;
import com.android.internal.R;
+import java.io.IOException;
+import java.net.Authenticator;
+
/**
* @hide
*/
@@ -48,7 +48,6 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
private int mUid;
private Bundle mResultBundle = null;
protected LayoutInflater mInflater;
- private final AccountManagerService accountManagerService = AccountManagerService.getSingleton();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -81,7 +80,7 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
String accountTypeLabel;
try {
- accountTypeLabel = accountManagerService.getAccountLabel(mAccount.type);
+ accountTypeLabel = getAccountLabel(mAccount);
} catch (IllegalArgumentException e) {
// label or resource was missing. abort the activity.
setResult(Activity.RESULT_CANCELED);
@@ -92,28 +91,27 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
final TextView authTokenTypeView = (TextView) findViewById(R.id.authtoken_type);
authTokenTypeView.setVisibility(View.GONE);
- /** Handles the responses from the AccountManager */
- IAccountManagerResponse response = new IAccountManagerResponse.Stub() {
- public void onResult(Bundle bundle) {
- final String authTokenLabel =
- bundle.getString(AccountManager.KEY_AUTH_TOKEN_LABEL);
- if (!TextUtils.isEmpty(authTokenLabel)) {
- runOnUiThread(new Runnable() {
- public void run() {
- if (!isFinishing()) {
- authTokenTypeView.setText(authTokenLabel);
- authTokenTypeView.setVisibility(View.VISIBLE);
+ final AccountManagerCallback<String> callback = new AccountManagerCallback<String>() {
+ public void run(AccountManagerFuture<String> future) {
+ try {
+ final String authTokenLabel = future.getResult();
+ if (!TextUtils.isEmpty(authTokenLabel)) {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ if (!isFinishing()) {
+ authTokenTypeView.setText(authTokenLabel);
+ authTokenTypeView.setVisibility(View.VISIBLE);
+ }
}
- }
- });
+ });
+ }
+ } catch (OperationCanceledException e) {
+ } catch (IOException e) {
+ } catch (AuthenticatorException e) {
}
}
-
- public void onError(int code, String message) {
- }
};
-
- accountManagerService.getAuthTokenLabel(response, mAccount, mAuthTokenType, mUid);
+ AccountManager.get(this).getAuthTokenLabel(mAccount.type, mAuthTokenType, callback, null);
findViewById(R.id.allow_button).setOnClickListener(this);
findViewById(R.id.deny_button).setOnClickListener(this);
@@ -134,6 +132,24 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
((TextView) findViewById(R.id.account_type)).setText(accountTypeLabel);
}
+ private String getAccountLabel(Account account) {
+ final AuthenticatorDescription[] authenticatorTypes =
+ AccountManager.get(this).getAuthenticatorTypes();
+ for (int i = 0, N = authenticatorTypes.length; i < N; i++) {
+ final AuthenticatorDescription desc = authenticatorTypes[i];
+ if (desc.type.equals(account.type)) {
+ try {
+ return createPackageContext(desc.packageName, 0).getString(desc.labelId);
+ } catch (PackageManager.NameNotFoundException e) {
+ return account.type;
+ } catch (Resources.NotFoundException e) {
+ return account.type;
+ }
+ }
+ }
+ return account.type;
+ }
+
private View newPackageView(String packageLabel) {
View view = mInflater.inflate(R.layout.permissions_package_list_item, null);
((TextView) view.findViewById(R.id.package_label)).setText(packageLabel);
@@ -143,7 +159,7 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
public void onClick(View v) {
switch (v.getId()) {
case R.id.allow_button:
- accountManagerService.grantAppPermission(mAccount, mAuthTokenType, mUid);
+ AccountManager.get(this).updateAppPermission(mAccount, mAuthTokenType, mUid, true);
Intent result = new Intent();
result.putExtra("retry", true);
setResult(RESULT_OK, result);
@@ -151,7 +167,7 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
break;
case R.id.deny_button:
- accountManagerService.revokeAppPermission(mAccount, mAuthTokenType, mUid);
+ AccountManager.get(this).updateAppPermission(mAccount, mAuthTokenType, mUid, false);
setResult(RESULT_CANCELED);
break;
}
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index 36a5653..6007321 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -41,6 +41,7 @@ interface IAccountManager {
void setPassword(in Account account, String password);
void clearPassword(in Account account);
void setUserData(in Account account, String key, String value);
+ void updateAppPermission(in Account account, String authTokenType, int uid, boolean value);
void getAuthToken(in IAccountManagerResponse response, in Account account,
String authTokenType, boolean notifyOnAuthFailure, boolean expectActivityLaunch,
@@ -54,4 +55,6 @@ interface IAccountManager {
boolean expectActivityLaunch);
void confirmCredentials(in IAccountManagerResponse response, in Account account,
in Bundle options, boolean expectActivityLaunch);
+ void getAuthTokenLabel(in IAccountManagerResponse response, String accountType,
+ String authTokenType);
}