Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e3fada79 authored by Fred Quintana's avatar Fred Quintana Committed by Android Git Automerger
Browse files

am 3c144c3e: Merge "Add an updateAppPermission() API call to the...

am 3c144c3e: 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 

* commit '3c144c3e':
  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.
parents 2e73f4c0 3c144c3e
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -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
+29 −10
Original line number Diff line number Diff line
@@ -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;
+43 −27
Original line number Diff line number Diff line
@@ -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,11 +91,10 @@ 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);
        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() {
@@ -107,13 +105,13 @@ public class GrantCredentialsPermissionActivity extends Activity implements View
                            }
                        });
                    }
                } 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;
        }
+3 −0
Original line number Diff line number Diff line
@@ -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);
}