Search in sources :

Example 36 with AuthenticatorDescription

use of android.accounts.AuthenticatorDescription in project android_frameworks_base by crdroidandroid.

the class AccountManagerService method getAuthToken.

@Override
public void getAuthToken(IAccountManagerResponse response, final Account account, final String authTokenType, final boolean notifyOnAuthFailure, final boolean expectActivityLaunch, final Bundle loginOptions) {
    Bundle.setDefusable(loginOptions, true);
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "getAuthToken: " + account + ", response " + response + ", authTokenType " + authTokenType + ", notifyOnAuthFailure " + notifyOnAuthFailure + ", expectActivityLaunch " + expectActivityLaunch + ", caller's uid " + Binder.getCallingUid() + ", pid " + Binder.getCallingPid());
    }
    if (response == null)
        throw new IllegalArgumentException("response is null");
    try {
        if (account == null) {
            Slog.w(TAG, "getAuthToken called with null account");
            response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, "account is null");
            return;
        }
        if (authTokenType == null) {
            Slog.w(TAG, "getAuthToken called with null authTokenType");
            response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, "authTokenType is null");
            return;
        }
    } catch (RemoteException e) {
        Slog.w(TAG, "Failed to report error back to the client." + e);
        return;
    }
    int userId = UserHandle.getCallingUserId();
    long ident = Binder.clearCallingIdentity();
    final UserAccounts accounts;
    final RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
    try {
        accounts = getUserAccounts(userId);
        authenticatorInfo = mAuthenticatorCache.getServiceInfo(AuthenticatorDescription.newKey(account.type), accounts.userId);
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
    final boolean customTokens = authenticatorInfo != null && authenticatorInfo.type.customTokens;
    // skip the check if customTokens
    final int callerUid = Binder.getCallingUid();
    final boolean permissionGranted = customTokens || permissionIsGranted(account, authTokenType, callerUid, userId);
    // Get the calling package. We will use it for the purpose of caching.
    final String callerPkg = loginOptions.getString(AccountManager.KEY_ANDROID_PACKAGE_NAME);
    List<String> callerOwnedPackageNames;
    ident = Binder.clearCallingIdentity();
    try {
        callerOwnedPackageNames = Arrays.asList(mPackageManager.getPackagesForUid(callerUid));
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
    if (callerPkg == null || !callerOwnedPackageNames.contains(callerPkg)) {
        String msg = String.format("Uid %s is attempting to illegally masquerade as package %s!", callerUid, callerPkg);
        throw new SecurityException(msg);
    }
    // let authenticator know the identity of the caller
    loginOptions.putInt(AccountManager.KEY_CALLER_UID, callerUid);
    loginOptions.putInt(AccountManager.KEY_CALLER_PID, Binder.getCallingPid());
    if (notifyOnAuthFailure) {
        loginOptions.putBoolean(AccountManager.KEY_NOTIFY_ON_FAILURE, true);
    }
    long identityToken = clearCallingIdentity();
    try {
        // Distill the caller's package signatures into a single digest.
        final byte[] callerPkgSigDigest = calculatePackageSignatureDigest(callerPkg);
        // route of starting a Session
        if (!customTokens && permissionGranted) {
            String authToken = readAuthTokenInternal(accounts, account, authTokenType);
            if (authToken != null) {
                Bundle result = new Bundle();
                result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
                result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
                result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
                onResult(response, result);
                return;
            }
        }
        if (customTokens) {
            /*
                 * Look up tokens in the new cache only if the loginOptions don't have parameters
                 * outside of those expected to be injected by the AccountManager, e.g.
                 * ANDORID_PACKAGE_NAME.
                 */
            String token = readCachedTokenInternal(accounts, account, authTokenType, callerPkg, callerPkgSigDigest);
            if (token != null) {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "getAuthToken: cache hit ofr custom token authenticator.");
                }
                Bundle result = new Bundle();
                result.putString(AccountManager.KEY_AUTHTOKEN, token);
                result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
                result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
                onResult(response, result);
                return;
            }
        }
        new Session(accounts, response, account.type, expectActivityLaunch, false, /* stripAuthTokenFromResult */
        account.name, false) {

            /* authDetailsRequired */
            @Override
            protected String toDebugString(long now) {
                if (loginOptions != null)
                    loginOptions.keySet();
                return super.toDebugString(now) + ", getAuthToken" + ", " + account + ", authTokenType " + authTokenType + ", loginOptions " + loginOptions + ", notifyOnAuthFailure " + notifyOnAuthFailure;
            }

            @Override
            public void run() throws RemoteException {
                // "grant permission" intent instead of the "getAuthToken" intent.
                if (!permissionGranted) {
                    mAuthenticator.getAuthTokenLabel(this, authTokenType);
                } else {
                    mAuthenticator.getAuthToken(this, account, authTokenType, loginOptions);
                }
            }

            @Override
            public void onResult(Bundle result) {
                Bundle.setDefusable(result, true);
                if (result != null) {
                    if (result.containsKey(AccountManager.KEY_AUTH_TOKEN_LABEL)) {
                        Intent intent = newGrantCredentialsPermissionIntent(account, null, callerUid, new AccountAuthenticatorResponse(this), authTokenType, true);
                        Bundle bundle = new Bundle();
                        bundle.putParcelable(AccountManager.KEY_INTENT, intent);
                        onResult(bundle);
                        return;
                    }
                    String authToken = result.getString(AccountManager.KEY_AUTHTOKEN);
                    if (authToken != null) {
                        String name = result.getString(AccountManager.KEY_ACCOUNT_NAME);
                        String type = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
                        if (TextUtils.isEmpty(type) || TextUtils.isEmpty(name)) {
                            onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "the type and name should not be empty");
                            return;
                        }
                        Account resultAccount = new Account(name, type);
                        if (!customTokens) {
                            saveAuthTokenToDatabase(mAccounts, resultAccount, authTokenType, authToken);
                        }
                        long expiryMillis = result.getLong(AbstractAccountAuthenticator.KEY_CUSTOM_TOKEN_EXPIRY, 0L);
                        if (customTokens && expiryMillis > System.currentTimeMillis()) {
                            saveCachedToken(mAccounts, account, callerPkg, callerPkgSigDigest, authTokenType, authToken, expiryMillis);
                        }
                    }
                    Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
                    if (intent != null && notifyOnAuthFailure && !customTokens) {
                        /*
                             * Make sure that the supplied intent is owned by the authenticator
                             * giving it to the system. Otherwise a malicious authenticator could
                             * have users launching arbitrary activities by tricking users to
                             * interact with malicious notifications.
                             */
                        checkKeyIntent(Binder.getCallingUid(), intent);
                        doNotification(mAccounts, account, result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE), intent, "android", accounts.userId);
                    }
                }
                super.onResult(result);
            }
        }.bind();
    } finally {
        restoreCallingIdentity(identityToken);
    }
}
Also used : Account(android.accounts.Account) Bundle(android.os.Bundle) IAccountAuthenticatorResponse(android.accounts.IAccountAuthenticatorResponse) AccountAuthenticatorResponse(android.accounts.AccountAuthenticatorResponse) GeneralSecurityException(java.security.GeneralSecurityException) PendingIntent(android.app.PendingIntent) Intent(android.content.Intent) AuthenticatorDescription(android.accounts.AuthenticatorDescription) RemoteException(android.os.RemoteException) RegisteredServicesCache(android.content.pm.RegisteredServicesCache)

Example 37 with AuthenticatorDescription

use of android.accounts.AuthenticatorDescription in project android_frameworks_base by crdroidandroid.

the class AccountAuthenticatorCache method parseServiceAttributes.

public AuthenticatorDescription parseServiceAttributes(Resources res, String packageName, AttributeSet attrs) {
    TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AccountAuthenticator);
    try {
        final String accountType = sa.getString(com.android.internal.R.styleable.AccountAuthenticator_accountType);
        final int labelId = sa.getResourceId(com.android.internal.R.styleable.AccountAuthenticator_label, 0);
        final int iconId = sa.getResourceId(com.android.internal.R.styleable.AccountAuthenticator_icon, 0);
        final int smallIconId = sa.getResourceId(com.android.internal.R.styleable.AccountAuthenticator_smallIcon, 0);
        final int prefId = sa.getResourceId(com.android.internal.R.styleable.AccountAuthenticator_accountPreferences, 0);
        final boolean customTokens = sa.getBoolean(com.android.internal.R.styleable.AccountAuthenticator_customTokens, false);
        if (TextUtils.isEmpty(accountType)) {
            return null;
        }
        return new AuthenticatorDescription(accountType, packageName, labelId, iconId, smallIconId, prefId, customTokens);
    } finally {
        sa.recycle();
    }
}
Also used : AuthenticatorDescription(android.accounts.AuthenticatorDescription) TypedArray(android.content.res.TypedArray)

Aggregations

AuthenticatorDescription (android.accounts.AuthenticatorDescription)37 Context (android.content.Context)17 PackageManager (android.content.pm.PackageManager)12 Resources (android.content.res.Resources)11 Account (android.accounts.Account)10 Drawable (android.graphics.drawable.Drawable)9 RegisteredServicesCache (android.content.pm.RegisteredServicesCache)7 TypedArray (android.content.res.TypedArray)7 Bundle (android.os.Bundle)7 RemoteException (android.os.RemoteException)7 AccountAuthenticatorResponse (android.accounts.AccountAuthenticatorResponse)6 IAccountAuthenticatorResponse (android.accounts.IAccountAuthenticatorResponse)6 PendingIntent (android.app.PendingIntent)6 Intent (android.content.Intent)6 GeneralSecurityException (java.security.GeneralSecurityException)5 ResolveInfo (android.content.pm.ResolveInfo)2 AccountManager (android.accounts.AccountManager)1 AccountManagerFuture (android.accounts.AccountManagerFuture)1 ActivityInfo (android.content.pm.ActivityInfo)1 ApplicationInfo (android.content.pm.ApplicationInfo)1