Skip to content

Commit 293318c

Browse files
committed
Make Write Client reject a first ACL entry that doesn't grant Administer privelege to at least one subject and return a new Error Code when that happens
1 parent f104949 commit 293318c

File tree

6 files changed

+274
-260
lines changed

6 files changed

+274
-260
lines changed

docs/ids_and_codes/ERROR_CODES.md

+250-247
Large diffs are not rendered by default.

scripts/error_table.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#
1919

2020
#
21-
# Execute as `python scripts/error_table.py > docs/ERROR_CODES.md` from root of repos
21+
# Execute as `python scripts/error_table.py > docs/ids_and_codes/ERROR_CODES.md` from root of repos
2222
#
2323
# This script uses heuristics scraping of the headers to generate nice tables
2424
#
@@ -145,7 +145,7 @@ def main():
145145
print("# Matter SDK `CHIP_ERROR` enums values")
146146
print()
147147
print("This file was **AUTOMATICALLY** generated by")
148-
print("`python scripts/error_table.py > docs/ERROR_CODES.md`. DO NOT EDIT BY HAND!")
148+
print("`python scripts/error_table.py > docs/ids_and_codes/ERROR_CODES.md`. DO NOT EDIT BY HAND!")
149149
print()
150150
print("## Table of contents")
151151

src/app/WriteClient.h

+17-9
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#pragma once
2020

21+
#include <app-common/zap-generated/cluster-objects.h>
2122
#include <app/AttributePathParams.h>
2223
#include <app/ConcreteAttributePath.h>
2324
#include <app/InteractionModelTimeout.h>
@@ -174,21 +175,28 @@ class WriteClient : public Messaging::ExchangeDelegate
174175

175176
ReturnErrorOnFailure(EnsureMessage());
176177

177-
bool emptyListNotEncoded = true;
178-
// Encode an empty list for the chunking protocol.
179-
if (path.mClusterId != 0x1F)
178+
// Encode an empty list for the chunking protocol, except when encoding ACLs.
179+
// for ACLs, we encode the first ACL entry directly, which will trigger a ReplaceAll operation on the server side.
180+
// The first ACL entry must grant Administer privileges to at least one subject.
181+
bool firstEntryEncoded = false;
182+
if constexpr (!std::is_same_v<T, Clusters::AccessControl::Structs::AccessControlEntryStruct::Type const>)
180183
{
181184
ReturnErrorOnFailure(EncodeSingleAttributeDataIB(path, DataModel::List<uint8_t>()));
182-
emptyListNotEncoded = false;
183185
}
184186
else
185187
{
186-
// When we are trying to Encode ACL, we encode the first entry instead of an empty list
187-
ReturnErrorOnFailure(EncodeSingleAttributeDataIB(path, DataModel::List<T>(value.data(), 1)));
188-
emptyListNotEncoded = true;
188+
if (value.data()[0].privilege != Clusters::AccessControl::AccessControlEntryPrivilegeEnum::kAdminister)
189+
{
190+
return CHIP_ERROR_FIRST_ACL_ENTRY_NOT_ADMIN;
191+
}
192+
193+
ReturnErrorOnFailure(EncodeSingleAttributeDataIB(path, DataModel::List<T>(value.SubSpan(0, 1))));
194+
firstEntryEncoded = true;
189195
}
190-
path.mListOp = ConcreteDataAttributePath::ListOperation::AppendItem;
191-
for (size_t i = static_cast<size_t>(emptyListNotEncoded); i < value.size(); i++)
196+
197+
path.mListOp = ConcreteDataAttributePath::ListOperation::AppendItem;
198+
size_t startIndex = firstEntryEncoded ? 1 : 0;
199+
for (size_t i = startIndex; i < value.size(); i++)
192200
{
193201
ReturnErrorOnFailure(EncodeSingleAttributeDataIB(path, value.data()[i]));
194202
}

src/app/WriteHandler.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,7 @@ CHIP_ERROR WriteHandler::ProcessAttributeDataIBs(TLV::TLVReader & aAttributeData
377377
if (mDelegate->HasConflictWriteRequests(this, dataAttributePath) ||
378378
// Per chunking protocol, we are processing the list entries, but the initial empty list is not processed, so we reject
379379
// it with Busy status code.
380-
(dataAttributePath.IsListItemOperation() && !IsSameAttribute(mProcessingAttributePath, dataAttributePath) &&
381-
dataAttributePath.mClusterId != 0x1F))
380+
(dataAttributePath.IsListItemOperation() && !IsSameAttribute(mProcessingAttributePath, dataAttributePath)))
382381
{
383382
err = AddStatusInternal(dataAttributePath, StatusIB(Status::Busy));
384383
continue;

src/lib/core/CHIPError.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,9 @@ bool FormatCHIPError(char * buf, uint16_t bufSize, CHIP_ERROR err)
475475
case CHIP_ERROR_HANDLER_NOT_SET.AsInteger():
476476
desc = "Callback function or callable object is not set";
477477
break;
478+
case CHIP_ERROR_FIRST_ACL_ENTRY_NOT_ADMIN.AsInteger():
479+
desc = "The first ACL entry must grant Administer privileges to at least one subject";
480+
break;
478481
}
479482
#endif // !CHIP_CONFIG_SHORT_ERROR_STR
480483

src/lib/core/tests/TestCHIPErrorStr.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ static const CHIP_ERROR kTestElements[] =
7878
CHIP_ERROR_UNKNOWN_IMPLICIT_TLV_TAG,
7979
CHIP_ERROR_WRONG_TLV_TYPE,
8080
CHIP_ERROR_TLV_CONTAINER_OPEN,
81+
CHIP_ERROR_FIRST_ACL_ENTRY_NOT_ADMIN,
8182
CHIP_ERROR_INVALID_MESSAGE_TYPE,
8283
CHIP_ERROR_UNEXPECTED_TLV_ELEMENT,
8384
CHIP_ERROR_NOT_IMPLEMENTED,

0 commit comments

Comments
 (0)