Merge "Pass set allowed providers permission to UI" into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
cecb5e23af
@@ -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
|
||||||
|
|||||||
@@ -163,28 +163,12 @@ 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;
|
return false;
|
||||||
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 PermissionUtils.hasPermission(context, serviceInfo.packageName,
|
||||||
|
Manifest.permission.PROVIDE_DEFAULT_ENABLED_CREDENTIAL_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isValidSystemProvider(
|
private static boolean isValidSystemProvider(
|
||||||
|
|||||||
50
core/java/android/service/credentials/PermissionUtils.java
Normal file
50
core/java/android/service/credentials/PermissionUtils.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user