Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add access control check to IM read, write, invoke #12645

Merged
1 change: 1 addition & 0 deletions src/app/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ static_library("app") {

public_deps = [
":app_buildconfig",
"${chip_root}/src/access",
"${chip_root}/src/app/util:device_callbacks_manager",
"${chip_root}/src/lib/support",
"${chip_root}/src/messaging",
Expand Down
18 changes: 17 additions & 1 deletion src/app/CommandHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "InteractionModelEngine.h"
#include "messaging/ExchangeContext.h"

#include <access/AccessControl.h>
#include <app/util/MatterCallbacks.h>
#include <lib/support/TypeTraits.h>
#include <protocols/secure_channel/Constants.h>
Expand Down Expand Up @@ -247,6 +248,21 @@ CHIP_ERROR CommandHandler::ProcessCommandDataIB(CommandDataIB::Parser & aCommand
VerifyOrExit(mpCallback->CommandExists(ConcreteCommandPath(endpointId, clusterId, commandId)),
err = CHIP_ERROR_INVALID_PROFILE_ID);

{
Access::SubjectDescriptor subjectDescriptor; // TODO: get actual subject descriptor
Access::RequestPath requestPath{ .cluster = clusterId, .endpoint = endpointId };
Access::Privilege requestPrivilege = Access::Privilege::kOperate; // TODO: get actual request privilege
err = Access::GetAccessControl().Check(subjectDescriptor, requestPath, requestPrivilege);
if (err != CHIP_NO_ERROR)
{
const ConcreteCommandPath concretePath(endpointId, clusterId, commandId);
mlepage-google marked this conversation as resolved.
Show resolved Hide resolved
auto status = (err == CHIP_ERROR_ACCESS_DENIED) ? Protocols::InteractionModel::Status::UnsupportedAccess
: Protocols::InteractionModel::Status::Failure;
AddStatus(concretePath, status);
mlepage-google marked this conversation as resolved.
Show resolved Hide resolved
return CHIP_NO_ERROR;
}
}

err = aCommandElement.GetData(&commandDataReader);
if (CHIP_END_OF_TLV == err)
{
Expand All @@ -270,7 +286,7 @@ CHIP_ERROR CommandHandler::ProcessCommandDataIB(CommandDataIB::Parser & aCommand
exit:
if (err != CHIP_NO_ERROR)
{
ConcreteCommandPath path(endpointId, clusterId, commandId);
const ConcreteCommandPath path(endpointId, clusterId, commandId);

// The Path is the path in the request if there are any error occurred before we dispatch the command to clusters.
// Currently, it could be failed to decode Path or failed to find cluster / command on desired endpoint.
Expand Down
32 changes: 31 additions & 1 deletion src/app/util/ember-compatibility-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* when calling ember callbacks.
*/

#include <access/AccessControl.h>
#include <app/ClusterInfo.h>
#include <app/Command.h>
#include <app/ConcreteAttributePath.h>
Expand Down Expand Up @@ -272,6 +273,23 @@ CHIP_ERROR ReadSingleClusterData(FabricIndex aAccessingFabricIndex, const Concre
return SendFailureStatus(aPath, attributeReport, Protocols::InteractionModel::Status::UnsupportedAttribute, nullptr);
}

{
Access::SubjectDescriptor subjectDescriptor; // TODO: get actual subject descriptor
Access::RequestPath requestPath{ .cluster = aPath.mClusterId, .endpoint = aPath.mEndpointId };
Access::Privilege requestPrivilege = Access::Privilege::kView; // TODO: get actual request privilege
CHIP_ERROR err = Access::GetAccessControl().Check(subjectDescriptor, requestPath, requestPrivilege);
if (err != CHIP_NO_ERROR)
{
AttributeReportIB::Builder attributeReport = aAttributeReports.CreateAttributeReport();
ReturnErrorOnFailure(aAttributeReports.GetError());
TLV::TLVWriter backup;
attributeReport.Checkpoint(backup);
mlepage-google marked this conversation as resolved.
Show resolved Hide resolved
auto status = (err == CHIP_ERROR_ACCESS_DENIED) ? Protocols::InteractionModel::Status::UnsupportedAccess
: Protocols::InteractionModel::Status::Failure;
return SendFailureStatus(aPath, attributeReport, status, &backup);
mlepage-google marked this conversation as resolved.
Show resolved Hide resolved
}
}

AttributeAccessInterface * attrOverride = findAttributeAccessOverride(aPath.mEndpointId, aPath.mClusterId);
mlepage-google marked this conversation as resolved.
Show resolved Hide resolved
// Value encoder will encode the whole AttributeReport, including the path, value and the version.
// The AttributeValueEncoder may encode more than one AttributeReportIB for the list chunking feature.
Expand Down Expand Up @@ -304,7 +322,6 @@ CHIP_ERROR ReadSingleClusterData(FabricIndex aAccessingFabricIndex, const Concre
}

AttributeReportIB::Builder attributeReport = aAttributeReports.CreateAttributeReport();

ReturnErrorOnFailure(aAttributeReports.GetError());
TLV::TLVWriter backup;
attributeReport.Checkpoint(backup);
Expand Down Expand Up @@ -728,6 +745,19 @@ CHIP_ERROR WriteSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVReader & a
return apWriteHandler->AddStatus(attributePathParams, Protocols::InteractionModel::Status::NeedsTimedInteraction);
}

{
Access::SubjectDescriptor subjectDescriptor; // TODO: get actual subject descriptor
mlepage-google marked this conversation as resolved.
Show resolved Hide resolved
Access::RequestPath requestPath{ .cluster = aPath.mClusterId, .endpoint = aPath.mEndpointId };
Access::Privilege requestPrivilege = Access::Privilege::kOperate; // TODO: get actual request privilege
CHIP_ERROR err = Access::GetAccessControl().Check(subjectDescriptor, requestPath, requestPrivilege);
if (err != CHIP_NO_ERROR)
{
auto status = (err == CHIP_ERROR_ACCESS_DENIED) ? Protocols::InteractionModel::Status::UnsupportedAccess
: Protocols::InteractionModel::Status::Failure;
return apWriteHandler->AddStatus(attributePathParams, status);
}
}

if (auto * attrOverride = findAttributeAccessOverride(aClusterInfo.mEndpointId, aClusterInfo.mClusterId))
{
AttributeValueDecoder valueDecoder(aReader, apWriteHandler->GetAccessingFabricIndex());
Expand Down