Support ADB command for denying client auth

To make it easier to verify the permissions authentication logic, add
support for immediately denying a client access to a nanoapp.

Bug: 166846988
Test: adb shell cmd contexthub disable 0 test 0x123412 and verify
the app no longer can talk to the nanoapp

Change-Id: I45e15325e8cd3cc4b216f80292b507cbc675cd10
This commit is contained in:
Anthony Stange
2021-02-17 14:26:44 +00:00
parent ab42e66b4c
commit df40469fff
4 changed files with 121 additions and 18 deletions

View File

@@ -425,6 +425,10 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
}
}
/* package */ String getPackageName() {
return mPackage;
}
/**
* Used to override the attribution tag with a newer value if a PendingIntent broker is
* retrieved.
@@ -645,6 +649,13 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
*/
private void updateNanoAppAuthState(
long nanoAppId, boolean hasPermissions, boolean gracePeriodExpired) {
updateNanoAppAuthState(
nanoAppId, hasPermissions, gracePeriodExpired, false /* forceDenied */);
}
/* package */ void updateNanoAppAuthState(
long nanoAppId, boolean hasPermissions, boolean gracePeriodExpired,
boolean forceDenied) {
int curAuthState;
int newAuthState;
synchronized (mMessageChannelNanoappIdMap) {
@@ -655,7 +666,10 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
// GRANTED -> DENIED_GRACE_PERIOD only if permissions have been lost
// DENIED_GRACE_PERIOD -> DENIED only if the grace period expires
// DENIED/DENIED_GRACE_PERIOD -> GRANTED only if permissions are granted again
if (gracePeriodExpired) {
// any state -> DENIED if "forceDenied" is true
if (forceDenied) {
newAuthState = AUTHORIZATION_DENIED;
} else if (gracePeriodExpired) {
if (curAuthState == AUTHORIZATION_DENIED_GRACE_PERIOD) {
newAuthState = AUTHORIZATION_DENIED;
}
@@ -667,13 +681,12 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
}
}
if (newAuthState == AUTHORIZATION_GRANTED) {
if (newAuthState != AUTHORIZATION_DENIED_GRACE_PERIOD) {
AuthStateDenialTimer timer = mNappToAuthTimerMap.remove(nanoAppId);
if (timer != null) {
timer.cancel();
}
} else if (curAuthState == AUTHORIZATION_GRANTED
&& newAuthState == AUTHORIZATION_DENIED_GRACE_PERIOD) {
} else if (curAuthState == AUTHORIZATION_GRANTED) {
AuthStateDenialTimer timer =
new AuthStateDenialTimer(this, nanoAppId, Looper.getMainLooper());
mNappToAuthTimerMap.put(nanoAppId, timer);

View File

@@ -318,6 +318,21 @@ import java.util.function.Consumer;
forEachClientOfHub(contextHubId, client -> client.onNanoAppAborted(nanoAppId, abortCode));
}
/**
* Runs a command for each client that is attached to a hub with the given ID.
*
* @param contextHubId the ID of the hub
* @param callback the command to invoke for the client
*/
/* package */ void forEachClientOfHub(
int contextHubId, Consumer<ContextHubClientBroker> callback) {
for (ContextHubClientBroker broker : mHostEndPointIdToClientMap.values()) {
if (broker.getAttachedContextHubId() == contextHubId) {
callback.accept(broker);
}
}
}
/**
* Returns an available host endpoint ID.
*
@@ -357,20 +372,6 @@ import java.util.function.Consumer;
message, nanoappPermissions, messagePermissions));
}
/**
* Runs a command for each client that is attached to a hub with the given ID.
*
* @param contextHubId the ID of the hub
* @param callback the command to invoke for the client
*/
private void forEachClientOfHub(int contextHubId, Consumer<ContextHubClientBroker> callback) {
for (ContextHubClientBroker broker : mHostEndPointIdToClientMap.values()) {
if (broker.getAttachedContextHubId() == contextHubId) {
callback.accept(broker);
}
}
}
/**
* Retrieves a ContextHubClientBroker object with a matching PendingIntent and Context Hub ID.
*

View File

@@ -50,6 +50,8 @@ import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
@@ -365,6 +367,12 @@ public class ContextHubService extends IContextHubService.Stub {
return wrapper;
}
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ShellCallback callback, ResultReceiver result) {
new ContextHubShellCommand(mContext, this).exec(this, in, out, err, args, callback, result);
}
@Override
public int registerCallback(IContextHubCallback callback) throws RemoteException {
checkPermissions();
@@ -933,6 +941,16 @@ public class ContextHubService extends IContextHubService.Stub {
// dump eventLog
}
/* package */ void denyClientAuthState(int contextHubId, String packageName, long nanoAppId) {
mClientManager.forEachClientOfHub(contextHubId, client -> {
if (client.getPackageName().equals(packageName)) {
client.updateNanoAppAuthState(
nanoAppId, false /* hasPermissions */, false /* gracePeriodExpired */,
true /* forceDenied */);
}
});
}
private void dump(ProtoOutputStream proto) {
mContextHubIdToInfoMap.values().forEach(hubInfo -> {
long token = proto.start(ContextHubServiceProto.CONTEXT_HUB_INFO);

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2021 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 com.android.server.location.contexthub;
import android.content.Context;
import android.os.ShellCommand;
import java.io.PrintWriter;
/**
* ShellCommands for ContextHubService.
*
* Use with {@code adb shell cmd contexthub ...}.
*
* @hide
*/
public class ContextHubShellCommand extends ShellCommand {
// Internal service impl -- must perform security checks before touching.
private final ContextHubService mInternal;
public ContextHubShellCommand(Context context, ContextHubService service) {
mInternal = service;
context.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_CONTEXT_HUB, "ContextHubShellCommand");
}
@Override
public int onCommand(String cmd) {
if ("deny".equals(cmd)) {
return runDisableAuth();
}
return handleDefaultCommands(cmd);
}
private int runDisableAuth() {
int contextHubId = Integer.decode(getNextArgRequired());
String packageName = getNextArgRequired();
long nanoAppId = Long.decode(getNextArgRequired());
mInternal.denyClientAuthState(contextHubId, packageName, nanoAppId);
return 0;
}
@Override
public void onHelp() {
PrintWriter pw = getOutPrintWriter();
pw.println("ContextHub commands:");
pw.println(" help");
pw.println(" Print this help text.");
pw.println(" deny [contextHubId] [packageName] [nanoAppId]");
pw.println(" Immediately transitions the package's authentication state to denied so");
pw.println(" can no longer communciate with the nanoapp.");
}
}