Merge "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." into jb-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
3c144c3e69
@@ -404,6 +404,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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user