Merge "Pass set allowed providers permission to UI" into udc-dev

This commit is contained in:
TreeHugger Robot
2023-03-24 01:23:17 +00:00
committed by Android (Google) Code Review
6 changed files with 114 additions and 31 deletions

View File

@@ -74,13 +74,30 @@ public final class RequestInfo implements Parcelable {
@NonNull @NonNull
private final String mAppPackageName; private final String mAppPackageName;
private final boolean mHasPermissionToOverrideDefault;
/** Creates new {@code RequestInfo} for a create-credential flow. */ /** Creates new {@code RequestInfo} for a create-credential flow. */
@NonNull @NonNull
public static RequestInfo newCreateRequestInfo( public static RequestInfo newCreateRequestInfo(
@NonNull IBinder token, @NonNull CreateCredentialRequest createCredentialRequest, @NonNull IBinder token, @NonNull CreateCredentialRequest createCredentialRequest,
@NonNull String appPackageName) { @NonNull String appPackageName) {
return new RequestInfo( return new RequestInfo(
token, TYPE_CREATE, appPackageName, createCredentialRequest, null); token, TYPE_CREATE, appPackageName, createCredentialRequest, null,
/*hasPermissionToOverrideDefault=*/ false);
}
/**
* Creates new {@code RequestInfo} for a create-credential flow.
*
* @hide
*/
@NonNull
public static RequestInfo newCreateRequestInfo(
@NonNull IBinder token, @NonNull CreateCredentialRequest createCredentialRequest,
@NonNull String appPackageName, boolean hasPermissionToOverrideDefault) {
return new RequestInfo(
token, TYPE_CREATE, appPackageName, createCredentialRequest, null,
hasPermissionToOverrideDefault);
} }
/** Creates new {@code RequestInfo} for a get-credential flow. */ /** Creates new {@code RequestInfo} for a get-credential flow. */
@@ -89,7 +106,18 @@ public final class RequestInfo implements Parcelable {
@NonNull IBinder token, @NonNull GetCredentialRequest getCredentialRequest, @NonNull IBinder token, @NonNull GetCredentialRequest getCredentialRequest,
@NonNull String appPackageName) { @NonNull String appPackageName) {
return new RequestInfo( return new RequestInfo(
token, TYPE_GET, appPackageName, null, getCredentialRequest); token, TYPE_GET, appPackageName, null, getCredentialRequest,
/*hasPermissionToOverrideDefault=*/ false);
}
/**
* Returns whether the calling package has the permission
*
* @hide
*/
public boolean hasPermissionToOverrideDefault() {
return mHasPermissionToOverrideDefault;
} }
/** Returns the request token matching the user request. */ /** Returns the request token matching the user request. */
@@ -132,12 +160,14 @@ public final class RequestInfo implements Parcelable {
private RequestInfo(@NonNull IBinder token, @NonNull @RequestType String type, private RequestInfo(@NonNull IBinder token, @NonNull @RequestType String type,
@NonNull String appPackageName, @NonNull String appPackageName,
@Nullable CreateCredentialRequest createCredentialRequest, @Nullable CreateCredentialRequest createCredentialRequest,
@Nullable GetCredentialRequest getCredentialRequest) { @Nullable GetCredentialRequest getCredentialRequest,
boolean hasPermissionToOverrideDefault) {
mToken = token; mToken = token;
mType = type; mType = type;
mAppPackageName = appPackageName; mAppPackageName = appPackageName;
mCreateCredentialRequest = createCredentialRequest; mCreateCredentialRequest = createCredentialRequest;
mGetCredentialRequest = getCredentialRequest; mGetCredentialRequest = getCredentialRequest;
mHasPermissionToOverrideDefault = hasPermissionToOverrideDefault;
} }
private RequestInfo(@NonNull Parcel in) { private RequestInfo(@NonNull Parcel in) {
@@ -157,6 +187,7 @@ public final class RequestInfo implements Parcelable {
AnnotationValidations.validate(NonNull.class, null, mAppPackageName); AnnotationValidations.validate(NonNull.class, null, mAppPackageName);
mCreateCredentialRequest = createCredentialRequest; mCreateCredentialRequest = createCredentialRequest;
mGetCredentialRequest = getCredentialRequest; mGetCredentialRequest = getCredentialRequest;
mHasPermissionToOverrideDefault = in.readBoolean();
} }
@Override @Override
@@ -166,6 +197,7 @@ public final class RequestInfo implements Parcelable {
dest.writeString8(mAppPackageName); dest.writeString8(mAppPackageName);
dest.writeTypedObject(mCreateCredentialRequest, flags); dest.writeTypedObject(mCreateCredentialRequest, flags);
dest.writeTypedObject(mGetCredentialRequest, flags); dest.writeTypedObject(mGetCredentialRequest, flags);
dest.writeBoolean(mHasPermissionToOverrideDefault);
} }
@Override @Override

View File

@@ -163,29 +163,13 @@ public final class CredentialProviderInfoFactory {
private static boolean isSystemProviderWithValidPermission( private static boolean isSystemProviderWithValidPermission(
ServiceInfo serviceInfo, Context context) { ServiceInfo serviceInfo, Context context) {
requireNonNull(context, "context must not be null"); if (context == null) {
Slog.w(TAG, "Context is null in isSystemProviderWithValidPermission");
final String permission = Manifest.permission.PROVIDE_DEFAULT_ENABLED_CREDENTIAL_SERVICE;
try {
ApplicationInfo appInfo =
context.getPackageManager()
.getApplicationInfo(
serviceInfo.packageName,
PackageManager.ApplicationInfoFlags.of(
PackageManager.MATCH_SYSTEM_ONLY));
if (appInfo != null
&& context.checkPermission(permission, /* pid= */ -1, appInfo.uid)
== PackageManager.PERMISSION_GRANTED) {
Slog.i(TAG, "SYS permission granted for: " + serviceInfo.packageName);
return true;
} else {
Slog.i(TAG, "SYS permission failed for: " + serviceInfo.packageName);
}
} catch (PackageManager.NameNotFoundException e) {
Slog.e(TAG, "Error getting info for " + serviceInfo + ": " + e);
}
return false; return false;
} }
return PermissionUtils.hasPermission(context, serviceInfo.packageName,
Manifest.permission.PROVIDE_DEFAULT_ENABLED_CREDENTIAL_SERVICE);
}
private static boolean isValidSystemProvider( private static boolean isValidSystemProvider(
Context context, Context context,

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* 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 android.service.credentials;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
/**
* Utils for checking permissions, or any other permission related function
*
* @hide
*/
public class PermissionUtils {
//TODO(274838409): Move all CredentialManagerService permission checks here
/** Checks whether the given package name hold the given permission **/
public static boolean hasPermission(Context context, String packageName, String permission) {
try {
ApplicationInfo appInfo =
context.getPackageManager()
.getApplicationInfo(
packageName,
PackageManager.ApplicationInfoFlags.of(
PackageManager.MATCH_SYSTEM_ONLY));
if (appInfo != null
&& context.checkPermission(permission, /* pid= */ -1, appInfo.uid)
== PackageManager.PERMISSION_GRANTED) {
return true;
}
} catch (PackageManager.NameNotFoundException e) {
}
return false;
}
}

View File

@@ -16,6 +16,7 @@
package com.android.server.credentials; package com.android.server.credentials;
import android.Manifest;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.content.ComponentName; import android.content.ComponentName;
@@ -31,6 +32,7 @@ import android.credentials.ui.RequestInfo;
import android.os.CancellationSignal; import android.os.CancellationSignal;
import android.os.RemoteException; import android.os.RemoteException;
import android.service.credentials.CallingAppInfo; import android.service.credentials.CallingAppInfo;
import android.service.credentials.PermissionUtils;
import android.util.Log; import android.util.Log;
import com.android.server.credentials.metrics.ApiName; import com.android.server.credentials.metrics.ApiName;
@@ -88,7 +90,9 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR
mClientCallback.onPendingIntent(mCredentialManagerUi.createPendingIntent( mClientCallback.onPendingIntent(mCredentialManagerUi.createPendingIntent(
RequestInfo.newCreateRequestInfo( RequestInfo.newCreateRequestInfo(
mRequestId, mClientRequest, mRequestId, mClientRequest,
mClientAppInfo.getPackageName()), mClientAppInfo.getPackageName(),
PermissionUtils.hasPermission(mContext, mClientAppInfo.getPackageName(),
Manifest.permission.CREDENTIAL_MANAGER_SET_ALLOWED_PROVIDERS)),
providerDataList)); providerDataList));
} catch (RemoteException e) { } catch (RemoteException e) {
mChosenProviderFinalPhaseMetric.setUiReturned(false); mChosenProviderFinalPhaseMetric.setUiReturned(false);

View File

@@ -227,7 +227,9 @@ public class PrepareGetRequestSession extends RequestSession<GetCredentialReques
try { try {
mPrepareGetCredentialCallback.onResponse( mPrepareGetCredentialCallback.onResponse(
new PrepareGetCredentialResponseInternal( new PrepareGetCredentialResponseInternal(
false, null, false, false, getUiIntent())); false, null,
false, false,
getUiIntent()));
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "EXCEPTION while mPendingCallback.onResponse", e); Log.e(TAG, "EXCEPTION while mPendingCallback.onResponse", e);
} }

View File

@@ -95,7 +95,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
android.credentials.GetCredentialRequest filteredRequest = android.credentials.GetCredentialRequest filteredRequest =
filterOptions(providerInfo.getCapabilities(), filterOptions(providerInfo.getCapabilities(),
getRequestSession.mClientRequest, getRequestSession.mClientRequest,
providerInfo.getComponentName()); providerInfo);
if (filteredRequest != null) { if (filteredRequest != null) {
Map<String, CredentialOption> beginGetOptionToCredentialOptionMap = Map<String, CredentialOption> beginGetOptionToCredentialOptionMap =
new HashMap<>(); new HashMap<>();
@@ -120,7 +120,8 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
} }
/** Creates a new provider session to be used by the request session. */ /** Creates a new provider session to be used by the request session. */
@Nullable public static ProviderGetSession createNewSession( @Nullable
public static ProviderGetSession createNewSession(
Context context, Context context,
@UserIdInt int userId, @UserIdInt int userId,
CredentialProviderInfo providerInfo, CredentialProviderInfo providerInfo,
@@ -129,7 +130,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
android.credentials.GetCredentialRequest filteredRequest = android.credentials.GetCredentialRequest filteredRequest =
filterOptions(providerInfo.getCapabilities(), filterOptions(providerInfo.getCapabilities(),
getRequestSession.mClientRequest, getRequestSession.mClientRequest,
providerInfo.getComponentName()); providerInfo);
if (filteredRequest != null) { if (filteredRequest != null) {
Map<String, CredentialOption> beginGetOptionToCredentialOptionMap = Map<String, CredentialOption> beginGetOptionToCredentialOptionMap =
new HashMap<>(); new HashMap<>();
@@ -178,12 +179,13 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
private static android.credentials.GetCredentialRequest filterOptions( private static android.credentials.GetCredentialRequest filterOptions(
List<String> providerCapabilities, List<String> providerCapabilities,
android.credentials.GetCredentialRequest clientRequest, android.credentials.GetCredentialRequest clientRequest,
ComponentName componentName CredentialProviderInfo info
) { ) {
List<CredentialOption> filteredOptions = new ArrayList<>(); List<CredentialOption> filteredOptions = new ArrayList<>();
for (CredentialOption option : clientRequest.getCredentialOptions()) { for (CredentialOption option : clientRequest.getCredentialOptions()) {
if (providerCapabilities.contains(option.getType()) if (providerCapabilities.contains(option.getType())
&& isProviderAllowed(option, componentName)) { && isProviderAllowed(option, info.getComponentName())
&& checkSystemProviderRequirement(option, info.isSystemProvider())) {
Log.i(TAG, "In createProviderRequest - capability found : " Log.i(TAG, "In createProviderRequest - capability found : "
+ option.getType()); + option.getType());
filteredOptions.add(option); filteredOptions.add(option);
@@ -212,6 +214,15 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
return true; return true;
} }
private static boolean checkSystemProviderRequirement(CredentialOption option,
boolean isSystemProvider) {
if (option.isSystemProviderRequired() && !isSystemProvider) {
Log.d(TAG, "System provider required, but this service is not a system provider");
return false;
}
return true;
}
public ProviderGetSession(Context context, public ProviderGetSession(Context context,
CredentialProviderInfo info, CredentialProviderInfo info,
ProviderInternalCallback<GetCredentialResponse> callbacks, ProviderInternalCallback<GetCredentialResponse> callbacks,