use of android.accounts.AuthenticatorDescription in project android_frameworks_base by ParanoidAndroid.
the class AccountManagerService method getAuthToken.
public void getAuthToken(IAccountManagerResponse response, final Account account, final String authTokenType, final boolean notifyOnAuthFailure, final boolean expectActivityLaunch, Bundle loginOptionsIn) {
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");
if (account == null)
throw new IllegalArgumentException("account is null");
if (authTokenType == null)
throw new IllegalArgumentException("authTokenType is null");
checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
final UserAccounts accounts = getUserAccountsForCaller();
final RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
authenticatorInfo = mAuthenticatorCache.getServiceInfo(AuthenticatorDescription.newKey(account.type), accounts.userId);
final boolean customTokens = authenticatorInfo != null && authenticatorInfo.type.customTokens;
// restricted account.
if (!ArrayUtils.contains(getAccounts((String) null), account)) {
throw new IllegalArgumentException("no such account");
}
// skip the check if customTokens
final int callerUid = Binder.getCallingUid();
final boolean permissionGranted = customTokens || permissionIsGranted(account, authTokenType, callerUid);
final Bundle loginOptions = (loginOptionsIn == null) ? new Bundle() : loginOptionsIn;
// 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 {
// 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;
}
}
new Session(accounts, response, account.type, expectActivityLaunch, false) {
/* stripAuthTokenFromResult */
protected String toDebugString(long now) {
if (loginOptions != null)
loginOptions.keySet();
return super.toDebugString(now) + ", getAuthToken" + ", " + account + ", authTokenType " + authTokenType + ", loginOptions " + loginOptions + ", notifyOnAuthFailure " + notifyOnAuthFailure;
}
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);
}
}
public void onResult(Bundle result) {
if (result != null) {
if (result.containsKey(AccountManager.KEY_AUTH_TOKEN_LABEL)) {
Intent intent = newGrantCredentialsPermissionIntent(account, callerUid, new AccountAuthenticatorResponse(this), authTokenType, result.getString(AccountManager.KEY_AUTH_TOKEN_LABEL));
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;
}
if (!customTokens) {
saveAuthTokenToDatabase(mAccounts, new Account(name, type), authTokenType, authToken);
}
}
Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
if (intent != null && notifyOnAuthFailure && !customTokens) {
doNotification(mAccounts, account, result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE), intent, accounts.userId);
}
}
super.onResult(result);
}
}.bind();
} finally {
restoreCallingIdentity(identityToken);
}
}
use of android.accounts.AuthenticatorDescription in project android_frameworks_base by ParanoidAndroid.
the class AccountManagerService method validateAccountsInternal.
/**
* Validate internal set of accounts against installed authenticators for
* given user. Clear cached authenticators before validating when requested.
*/
private void validateAccountsInternal(UserAccounts accounts, boolean invalidateAuthenticatorCache) {
if (invalidateAuthenticatorCache) {
mAuthenticatorCache.invalidateCache(accounts.userId);
}
final HashSet<AuthenticatorDescription> knownAuth = Sets.newHashSet();
for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> service : mAuthenticatorCache.getAllServices(accounts.userId)) {
knownAuth.add(service.type);
}
synchronized (accounts.cacheLock) {
final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
boolean accountDeleted = false;
Cursor cursor = db.query(TABLE_ACCOUNTS, new String[] { ACCOUNTS_ID, ACCOUNTS_TYPE, ACCOUNTS_NAME }, null, null, null, null, null);
try {
accounts.accountCache.clear();
final HashMap<String, ArrayList<String>> accountNamesByType = new LinkedHashMap<String, ArrayList<String>>();
while (cursor.moveToNext()) {
final long accountId = cursor.getLong(0);
final String accountType = cursor.getString(1);
final String accountName = cursor.getString(2);
if (!knownAuth.contains(AuthenticatorDescription.newKey(accountType))) {
Slog.w(TAG, "deleting account " + accountName + " because type " + accountType + " no longer has a registered authenticator");
db.delete(TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null);
accountDeleted = true;
final Account account = new Account(accountName, accountType);
accounts.userDataCache.remove(account);
accounts.authTokenCache.remove(account);
} else {
ArrayList<String> accountNames = accountNamesByType.get(accountType);
if (accountNames == null) {
accountNames = new ArrayList<String>();
accountNamesByType.put(accountType, accountNames);
}
accountNames.add(accountName);
}
}
for (Map.Entry<String, ArrayList<String>> cur : accountNamesByType.entrySet()) {
final String accountType = cur.getKey();
final ArrayList<String> accountNames = cur.getValue();
final Account[] accountsForType = new Account[accountNames.size()];
int i = 0;
for (String accountName : accountNames) {
accountsForType[i] = new Account(accountName, accountType);
++i;
}
accounts.accountCache.put(accountType, accountsForType);
}
} finally {
cursor.close();
if (accountDeleted) {
sendAccountsChangedBroadcast(accounts.userId);
}
}
}
}
use of android.accounts.AuthenticatorDescription in project XPrivacy by M66B.
the class XAccountManager method after.
@Override
@SuppressWarnings("unchecked")
protected void after(XParam param) throws Throwable {
int uid = Binder.getCallingUid();
switch(mMethod) {
case addOnAccountsUpdatedListener:
// Do nothing
break;
case blockingGetAuthToken:
if (param.getResult() != null && param.args.length > 0 && param.args[0] != null) {
Account account = (Account) param.args[0];
if (isRestrictedExtra(param, account == null ? null : account.name))
if (!isAccountAllowed(account, uid))
param.setResult(null);
}
break;
case getAccounts:
if (param.getResult() != null && isRestricted(param)) {
Account[] accounts = (Account[]) param.getResult();
param.setResult(filterAccounts(accounts, uid));
}
break;
case getAccountsByType:
case getAccountsByTypeForPackage:
if (param.getResult() != null && param.args.length > 0)
if (isRestrictedExtra(param, (String) param.args[0])) {
Account[] accounts = (Account[]) param.getResult();
param.setResult(filterAccounts(accounts, uid));
}
break;
case getAccountsByTypeAndFeatures:
if (param.getResult() != null && param.args.length > 0)
if (isRestrictedExtra(param, (String) param.args[0])) {
AccountManagerFuture<Account[]> future = (AccountManagerFuture<Account[]>) param.getResult();
param.setResult(new XFutureAccount(future, uid));
}
break;
case getAuthenticatorTypes:
if (param.getResult() != null && isRestricted(param))
param.setResult(new AuthenticatorDescription[0]);
break;
case getAuthToken:
if (param.getResult() != null && param.args.length > 0) {
Account account = (Account) param.args[0];
if (isRestrictedExtra(param, account == null ? null : account.name)) {
AccountManagerFuture<Bundle> future = (AccountManagerFuture<Bundle>) param.getResult();
param.setResult(new XFutureBundle(future, uid));
}
}
break;
case getAuthTokenByFeatures:
if (param.getResult() != null)
if (isRestrictedExtra(param, (String) param.args[0])) {
AccountManagerFuture<Bundle> future = (AccountManagerFuture<Bundle>) param.getResult();
param.setResult(new XFutureBundle(future, uid));
}
break;
case hasFeatures:
if (param.getResult() != null && param.args.length > 0 && param.args[0] != null) {
Account account = (Account) param.args[0];
if (isRestrictedExtra(param, account == null ? null : account.name))
if (!isAccountAllowed(account, uid))
param.setResult(new XFutureBoolean());
}
break;
case removeOnAccountsUpdatedListener:
// Do nothing
break;
case Srv_getAccounts:
case Srv_getAccountsAsUser:
case Srv_getAccountsForPackage:
case Srv_getSharedAccountsAsUser:
// Filter account list
String extra = null;
if (mMethod == Methods.Srv_getAccounts || mMethod == Methods.Srv_getAccountsAsUser || mMethod == Methods.Srv_getAccountsForPackage)
if (param.args.length > 0 && param.args[0] instanceof String)
extra = (String) param.args[0];
if (param.getResult() instanceof Account[])
if (isRestrictedExtra(param, extra)) {
Account[] accounts = (Account[]) param.getResult();
param.setResult(filterAccounts(accounts, uid));
}
break;
case Srv_getAccountsByFeatures:
// Do nothing
break;
}
}
use of android.accounts.AuthenticatorDescription in project PocketHub by pockethub.
the class AccountUtils method hasAuthenticator.
/**
* Verify authenticator registered for account type matches the package name
* of this application
*
* @param manager
* @return true is authenticator registered, false otherwise
*/
public static boolean hasAuthenticator(final AccountManager manager) {
if (!AUTHENTICATOR_CHECKED) {
final AuthenticatorDescription[] types = manager.getAuthenticatorTypes();
if (types != null && types.length > 0) {
for (AuthenticatorDescription descriptor : types) {
if (descriptor != null && ACCOUNT_TYPE.equals(descriptor.type)) {
HAS_AUTHENTICATOR = "com.github.pockethub.android".equals(descriptor.packageName);
break;
}
}
}
AUTHENTICATOR_CHECKED = true;
}
return HAS_AUTHENTICATOR;
}
use of android.accounts.AuthenticatorDescription in project platform_frameworks_base by android.
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);
}
}
Aggregations