Further complete Auth support

This commit is contained in:
mar-v-in 2015-02-10 03:33:30 +01:00
parent 95919889d0
commit 189bb8966e
8 changed files with 175 additions and 47 deletions

View File

@ -24,6 +24,16 @@
android:minSdkVersion="16"
android:targetSdkVersion="21" />
<permission-tree android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" />
<permission
android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.local"
android:label="@string/permission_service_local_label"
android:description="@string/permission_service_local_description" />
<permission
android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.mail"
android:label="@string/permission_service_mail_label"
android:description="@string/permission_service_mail_description" />
<uses-permission android:name="android.permission.FAKE_PACKAGE_SIGNATURE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@ -71,6 +81,12 @@
android:value="com.google.android.location.internal.GMS_NLP" />
</service>
<!-- Services Framework -->
<provider
android:exported="true"
android:authorities="com.google.android.gsf.gservices"
android:name="org.microg.gms.gservices.GServicesProvider" />
<!-- Auth -->
<service

2
GmsApi

@ -1 +1 @@
Subproject commit 19b0b0f1d782640c0e5a9a381a0191665de0b053
Subproject commit 07e3208a26361d35253c1c50abca93689b643081

@ -1 +1 @@
Subproject commit 3efecf38ca8b1f89cd8f0c40eea4b497f1563d90
Subproject commit a650ca5beac2a374460d820935b40f9539e692db

View File

@ -17,6 +17,9 @@
package org.microg.gms.auth;
import android.accounts.Account;
import android.accounts.AccountAuthenticatorActivity;
import android.accounts.AccountAuthenticatorResponse;
import android.accounts.AccountManager;
import android.app.Activity;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@ -35,9 +38,10 @@ import android.widget.TextView;
import com.google.android.gms.R;
import org.microg.gms.common.Utils;
import org.microg.gms.userinfo.ProfileManager;
public class AskPermissionActivity extends Activity {
public class AskPermissionActivity extends AccountAuthenticatorActivity {
private static final String TAG = "GmsAuthAskPermission";
private Account account;
private String packageName;
@ -55,6 +59,13 @@ public class AskPermissionActivity extends Activity {
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
getWindow().setAttributes(lp);
account = new Account(getIntent().getStringExtra(AccountManager.KEY_ACCOUNT_NAME),
getIntent().getStringExtra(AccountManager.KEY_ACCOUNT_TYPE));
packageName = getIntent().getStringExtra(AccountManager.KEY_ANDROID_PACKAGE_NAME);
service = getIntent().getStringExtra(AccountManager.KEY_AUTHTOKEN);
int callerUid = getIntent().getIntExtra(AccountManager.KEY_CALLER_UID, 0);
Utils.checkPackage(this, packageName, callerUid);
// receive package info
PackageManager packageManager = getPackageManager();
ApplicationInfo applicationInfo;
@ -69,6 +80,7 @@ public class AskPermissionActivity extends Activity {
Drawable appIcon = packageManager.getApplicationIcon(applicationInfo);
Bitmap profileIcon = ProfileManager.getProfilePicture(this, account, false);
// receive profile icon
if (profileIcon != null) {
((ImageView) findViewById(R.id.account_photo)).setImageBitmap(profileIcon);
} else {
@ -113,6 +125,11 @@ public class AskPermissionActivity extends Activity {
finish();
}
@Override
public void finish() {
super.finish();
}
private class PermissionAdapter extends BaseAdapter {
private boolean isOAuth() {
@ -155,7 +172,7 @@ public class AskPermissionActivity extends Activity {
if (view == null) {
view = LayoutInflater.from(AskPermissionActivity.this).inflate(R.layout.ask_permission_list_entry, null);
}
((TextView)view.findViewById(android.R.id.text1)).setText(label);
((TextView) view.findViewById(android.R.id.text1)).setText(label);
return view;
}
}

View File

@ -19,6 +19,7 @@ package org.microg.gms.auth;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.util.Log;
import org.microg.gms.common.Utils;
@ -26,6 +27,7 @@ import org.microg.gms.common.Utils;
public class AuthManager {
private static final String TAG = "GmsAuthManager";
public static final String PERMISSION_TREE_BASE = "com.google.android.googleapps.permission.GOOGLE_AUTH.";
public static void storeResponse(Context context, Account account, String packageName,
String sig, String service, AuthResponse response) {
@ -44,12 +46,31 @@ public class AuthManager {
}
}
public static String getToken(Context context, Account account, String packageName,
String sig, String service) {
AccountManager accountManager = AccountManager.get(context);
return accountManager.peekAuthToken(account, buildTokenKey(packageName, sig, service));
}
public static boolean isPermitted(Context context, Account account, String packageName,
String sig, String service) {
if (service.startsWith("audience:server:client_id:")) {
// https://developers.google.com/accounts/docs/CrossClientAuth
Log.d(TAG, "Always permitting scope: " + service);
return true;
}
if (!service.startsWith("oauth")) {
if (context.getPackageManager().checkPermission(PERMISSION_TREE_BASE + service, packageName) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Permitting, permission is present");
return true;
}
}
AccountManager accountManager = AccountManager.get(context);
String perm = accountManager.getUserData(account, buildPermKey(packageName, sig, service));
if (!"1".equals(perm))
if (!"1".equals(perm)) {
Log.d(TAG, "Not permitting, permission not stored for " + packageName + ": " + service);
return false;
}
String exp = accountManager.getUserData(account, buildExpireKey(packageName, sig, service));
if (exp != null) {
long expLong = Long.parseLong(exp);

View File

@ -28,10 +28,14 @@ import android.os.RemoteException;
import android.util.Log;
import com.google.android.auth.IAuthManagerService;
import com.google.android.gms.auth.AccountChangeEventsRequest;
import com.google.android.gms.auth.AccountChangeEventsResponse;
import org.microg.gms.common.Utils;
public class AuthManagerServiceImpl extends IAuthManagerService.Stub {
private static final String TAG = "GmsAuthManagerService";
public static final String GOOGLE_ACCOUNT_TYPE = "com.google";
public static final String KEY_AUTHORITY = "authority";
@ -51,10 +55,6 @@ public class AuthManagerServiceImpl extends IAuthManagerService.Stub {
private Context context;
private class State {
String authToken;
}
public AuthManagerServiceImpl(Context context) {
this.context = context;
}
@ -66,12 +66,23 @@ public class AuthManagerServiceImpl extends IAuthManagerService.Stub {
Utils.checkPackage(context, packageName, callerUid, getCallingUid());
boolean notify = extras.getBoolean(KEY_HANDLE_NOTIFICATION, false);
Log.d("AuthManagerService", "getToken: account:" + accountName + " scope:" + scope + " extras:" + extras);
Log.d(TAG, "getToken: account:" + accountName + " scope:" + scope + " extras:" + extras);
Account account = new Account(accountName, GOOGLE_ACCOUNT_TYPE);
String sig = Utils.getFirstPackageSignatureDigest(context, packageName);
//AccountManagerFuture<Bundle> authToken = AccountManager.get(context).getAuthToken(new Account(accountName, GOOGLE_ACCOUNT_TYPE), scope, extras, notify, null, new Handler(Looper.getMainLooper()));
if (!AuthManager.isPermitted(context, account, packageName, sig, scope)) {
Bundle result = new Bundle();
result.putString(KEY_ERROR, "Unknown");
Intent i = new Intent(context, AskPermissionActivity.class);
i.putExtras(extras);
i.putExtra(AccountManager.KEY_ANDROID_PACKAGE_NAME, packageName);
i.putExtra(AccountManager.KEY_ACCOUNT_TYPE, account.type);
i.putExtra(AccountManager.KEY_ACCOUNT_NAME, account.name);
i.putExtra(AccountManager.KEY_AUTHTOKEN, scope);
result.putParcelable(KEY_USER_RECOVERY_INTENT, i);
return result;
}
try {
Account account = new Account(accountName, GOOGLE_ACCOUNT_TYPE);
String sig = Utils.getFirstPackageSignatureDigest(context, packageName);
AuthResponse response = new AuthRequest().fromContext(context)
.app(packageName, sig)
.callerIsApp()
@ -80,17 +91,10 @@ public class AuthManagerServiceImpl extends IAuthManagerService.Stub {
.service(scope)
.getResponse();
AuthManager.storeResponse(context, account, packageName, sig, scope, response);
//Bundle requestResult = authToken.getResult();
/*if (!requestResult.containsKey(AccountManager.KEY_AUTHTOKEN) && requestResult.containsKey(AccountManager.KEY_INTENT)) {
Intent intent = requestResult.getParcelable(AccountManager.KEY_INTENT);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}*/
Log.d("getToken", response.auth);
Bundle result = new Bundle();
result.putString(KEY_AUTH_TOKEN, response.auth);
result.putString(KEY_ERROR, "Unknown");
//result.putParcelable(KEY_USER_RECOVERY_INTENT, requestResult.getParcelable(AccountManager.KEY_INTENT));
return result;
} catch (Exception e) {
Log.w("AuthManagerService", e);
@ -98,6 +102,11 @@ public class AuthManagerServiceImpl extends IAuthManagerService.Stub {
}
}
@Override
public AccountChangeEventsResponse getChangeEvents(AccountChangeEventsRequest request) {
return new AccountChangeEventsResponse();
}
@Override
public Bundle clearToken(String token, Bundle extras) throws RemoteException {
return null;

View File

@ -29,7 +29,7 @@ import android.util.Log;
import com.google.android.gms.R;
import org.microg.gms.auth.AuthClient;
import org.microg.gms.auth.AskPermissionActivity;
import org.microg.gms.auth.AuthManager;
import org.microg.gms.auth.AuthRequest;
import org.microg.gms.auth.AuthResponse;
@ -93,9 +93,9 @@ public class GoogleLoginService extends Service {
@Override
public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {
Log.d(TAG, "hasFeatures: " + account + ", " + Arrays.toString(features));
Bundle b = new Bundle();
b.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
return b;
Bundle result = new Bundle();
result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
return result;
}
}.getIBinder();
}
@ -108,30 +108,41 @@ public class GoogleLoginService extends Service {
String app = options.getString(AccountManager.KEY_ANDROID_PACKAGE_NAME);
Utils.checkPackage(this, app, options.getInt(AccountManager.KEY_CALLER_UID), options.getInt(AccountManager.KEY_CALLER_UID));
String appSignature = Utils.getFirstPackageSignatureDigest(this, app);
try {
AuthRequest request = new AuthRequest().fromContext(this)
.email(account.name)
.token(AccountManager.get(this).getPassword(account))
.service(authTokenType)
.app(app, appSignature)
.callerIsGms()
.calledFromAccountManager();
if (AuthManager.isPermitted(this, account, app, appSignature, authTokenType)) {
request.hasPermission();
}
AuthResponse r = request.getResponse();
AuthManager.storeResponse(this, account, app, appSignature, authTokenType, r);
if (r.expiry == 0)
Log.d(TAG, "Auth: " + r.auth);
Bundle bundle = new Bundle();
bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
bundle.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
bundle.putString(AccountManager.KEY_AUTHTOKEN, r.auth);
return bundle;
} catch (IOException e) {
Log.w(TAG, e);
if (!AuthManager.isPermitted(this, account, app, appSignature, authTokenType)) {
Bundle result = new Bundle();
Intent i = new Intent(this, AskPermissionActivity.class);
i.putExtras(options);
i.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
i.putExtra(AccountManager.KEY_ANDROID_PACKAGE_NAME, app);
i.putExtra(AccountManager.KEY_ACCOUNT_TYPE, account.type);
i.putExtra(AccountManager.KEY_ACCOUNT_NAME, account.name);
i.putExtra(AccountManager.KEY_AUTHTOKEN, authTokenType);
result.putParcelable(AccountManager.KEY_INTENT, i);
return result;
}
return null;
String token = AuthManager.getToken(this, account, app, appSignature, authTokenType);
if (token == null) {
try {
AuthRequest request = new AuthRequest().fromContext(this)
.email(account.name)
.token(AccountManager.get(this).getPassword(account))
.service(authTokenType)
.app(app, appSignature)
.callerIsGms()
.calledFromAccountManager()
.hasPermission();
AuthResponse r = request.getResponse();
AuthManager.storeResponse(this, account, app, appSignature, authTokenType, r);
token = r.auth;
} catch (IOException e) {
Log.w(TAG, e);
}
}
Bundle result = new Bundle();
result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_AUTHTOKEN, token);
return result;
}
private Bundle addAccount(AccountAuthenticatorResponse response, String authTokenType, String[] requiredFeatures, Bundle options) {

View File

@ -0,0 +1,54 @@
/*
* Copyright 2013-2015 µg Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.microg.gms.gservices;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
public class GServicesProvider extends ContentProvider{
@Override
public boolean onCreate() {
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
return null;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
}