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 ACL validation #14756

Merged
merged 16 commits into from
Feb 9, 2022
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 74 additions & 1 deletion src/access/AccessControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ bool CheckRequestPrivilegeAgainstEntryPrivilege(Privilege requestPrivilege, Priv
return false;
}

constexpr bool IsValidCaseNodeId(NodeId aNodeId)
{
return chip::IsOperationalNodeId(aNodeId) || (chip::IsCASEAuthTag(aNodeId) && ((aNodeId & chip::kTagVersionMask) != 0));
}

constexpr bool IsValidGroupNodeId(NodeId aNodeId)
{
return chip::IsGroupId(aNodeId) && chip::IsValidGroupId(chip::GroupIdFromNodeId(aNodeId));
}

#if CHIP_DETAIL_LOGGING

char GetAuthModeStringForLogging(AuthMode authMode)
Expand Down Expand Up @@ -273,7 +283,7 @@ CHIP_ERROR AccessControl::Check(const SubjectDescriptor & subjectDescriptor, con
{
continue;
}
// TODO: check against target.deviceType (requires lookup)
// TODO(#14431): device type target not yet supported (add lookup/match when supported)
targetMatched = true;
break;
}
Expand All @@ -291,6 +301,69 @@ CHIP_ERROR AccessControl::Check(const SubjectDescriptor & subjectDescriptor, con
return CHIP_ERROR_ACCESS_DENIED;
}

bool AccessControl::IsValid(const Entry & entry)
{
const char * msg = "unexpected error";

AuthMode authMode;
FabricIndex fabricIndex;
Privilege privilege;
size_t subjectCount = 0;
size_t targetCount = 0;

SuccessOrExit(entry.GetAuthMode(authMode));
SuccessOrExit(entry.GetFabricIndex(fabricIndex));
SuccessOrExit(entry.GetPrivilege(privilege));
SuccessOrExit(entry.GetSubjectCount(subjectCount));
SuccessOrExit(entry.GetTargetCount(targetCount));

// Fabric index must be defined.
VerifyOrExit(fabricIndex != kUndefinedFabricIndex, msg = "invalid fabric index");

if (authMode != AuthMode::kCase)
{
// Operational PASE not supported for v1.0 (so must be group).
VerifyOrExit(authMode == AuthMode::kGroup, msg = "invalid auth mode");

// Privilege must not be administer.
VerifyOrExit(privilege != Privilege::kAdminister, msg = "invalid privilege");

// Subject must be present.
VerifyOrExit(subjectCount > 0, msg = "invalid subject count");
}

for (size_t i = 0; i < subjectCount; ++i)
{
NodeId subject;
SuccessOrExit(entry.GetSubject(i, subject));
const bool kIsCase = authMode == AuthMode::kCase;
const bool kIsGroup = authMode == AuthMode::kGroup;
VerifyOrExit((kIsCase && IsValidCaseNodeId(subject)) || (kIsGroup && IsValidGroupNodeId(subject)), msg = "invalid subject");
}

for (size_t i = 0; i < targetCount; ++i)
{
Entry::Target target;
SuccessOrExit(entry.GetTarget(i, target));
const bool kHasCluster = target.flags & Entry::Target::kCluster;
const bool kHasEndpoint = target.flags & Entry::Target::kEndpoint;
const bool kHasDeviceType = target.flags & Entry::Target::kDeviceType;
VerifyOrExit((kHasCluster || kHasEndpoint || kHasDeviceType) && !(kHasEndpoint && kHasDeviceType) &&
(!kHasCluster || IsValidClusterId(target.cluster)) &&
(!kHasEndpoint || IsValidEndpointId(target.endpoint)) &&
(!kHasDeviceType || IsValidDeviceTypeId(target.deviceType)),
msg = "invalid target");
// TODO(#14431): device type target not yet supported (remove check when supported)
VerifyOrExit(!kHasDeviceType, msg = "device type target not yet supported");
}

return true;

exit:
ChipLogError(DataManagement, "AccessControl: %s", msg);
mlepage-google marked this conversation as resolved.
Show resolved Hide resolved
return false;
}

AccessControl & GetAccessControl()
{
return *globalAccessControl;
Expand Down
4 changes: 4 additions & 0 deletions src/access/AccessControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ class AccessControl
*/
CHIP_ERROR CreateEntry(size_t * index, const Entry & entry, FabricIndex * fabricIndex = nullptr)
{
ReturnErrorCodeIf(!IsValid(entry), CHIP_ERROR_INVALID_ARGUMENT);
return mDelegate.CreateEntry(index, entry, fabricIndex);
}

Expand All @@ -417,6 +418,7 @@ class AccessControl
*/
CHIP_ERROR UpdateEntry(size_t index, const Entry & entry, const FabricIndex * fabricIndex = nullptr)
{
ReturnErrorCodeIf(!IsValid(entry), CHIP_ERROR_INVALID_ARGUMENT);
return mDelegate.UpdateEntry(index, entry, fabricIndex);
}

Expand Down Expand Up @@ -453,6 +455,8 @@ class AccessControl
CHIP_ERROR Check(const SubjectDescriptor & subjectDescriptor, const RequestPath & requestPath, Privilege requestPrivilege);

private:
bool IsValid(const Entry & entry);

static Delegate mDefaultDelegate;
Delegate & mDelegate = mDefaultDelegate;
};
Expand Down
Loading