Skip to content

Commit

Permalink
Add AccessRestrictionList support
Browse files Browse the repository at this point in the history
  • Loading branch information
tleacmcsa committed Aug 12, 2024
1 parent dc5bba7 commit 5501b22
Show file tree
Hide file tree
Showing 26 changed files with 2,104 additions and 7 deletions.
1 change: 1 addition & 0 deletions examples/network-manager-app/linux/args.gni
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ chip_project_config_include_dirs = [
]

chip_config_network_layer_ble = false
chip_enable_access_restrictions = true
18 changes: 18 additions & 0 deletions examples/platform/linux/AppMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <app/InteractionModelEngine.h>
#include <app/clusters/network-commissioning/network-commissioning.h>
#include <app/server/DefaultArlStorage.h>
#include <app/server/Dnssd.h>
#include <app/server/OnboardingCodesUtil.h>
#include <app/server/Server.h>
Expand Down Expand Up @@ -103,6 +104,10 @@
#include "AppMain.h"
#include "CommissionableInit.h"

#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
#include "ExampleAccessRestriction.h"
#endif

#if CHIP_DEVICE_LAYER_TARGET_DARWIN
#include <platform/Darwin/NetworkCommissioningDriver.h>
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
Expand All @@ -121,6 +126,7 @@ using namespace chip::DeviceLayer;
using namespace chip::Inet;
using namespace chip::Transport;
using namespace chip::app::Clusters;
using namespace chip::Access;

// Network comissioning implementation
namespace {
Expand Down Expand Up @@ -593,6 +599,18 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl)
chip::app::RuntimeOptionsProvider::Instance().SetSimulateNoInternalTime(
LinuxDeviceOptions::GetInstance().mSimulateNoInternalTime);

#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
if (LinuxDeviceOptions::GetInstance().accessRestrictionEntries.HasValue())
{
initParams.accessRestriction = new ExampleAccessRestriction();
initParams.arlStorage = new app::DefaultArlStorage();
for (const auto & entry : LinuxDeviceOptions::GetInstance().accessRestrictionEntries.Value())
{
VerifyOrDie(AccessRestriction::CreateCommissioningEntry(entry) == CHIP_NO_ERROR);
}
}
#endif

// Init ZCL Data Model and CHIP App Server
Server::GetInstance().Init(initParams);

Expand Down
2 changes: 2 additions & 0 deletions examples/platform/linux/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.

import("//build_overrides/chip.gni")
import("//build_overrides/jsoncpp.gni")
import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni")
import("${chip_root}/src/app/common_flags.gni")
import("${chip_root}/src/lib/core/core.gni")
Expand Down Expand Up @@ -94,6 +95,7 @@ source_set("app-main") {
"${chip_root}/src/controller:gen_check_chip_controller_headers",
"${chip_root}/src/lib",
"${chip_root}/src/platform/logging:default",
jsoncpp_root,
]
deps = [
":ota-test-event-trigger",
Expand Down
66 changes: 66 additions & 0 deletions examples/platform/linux/ExampleAccessRestriction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
*
* Copyright (c) 2024 Project CHIP Authors
* All rights reserved.
*
* 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.
*/

/*
* AccessRestriction implementation for Linux examples.
*/

#pragma once

#include <access/AccessRestriction.h>

namespace chip {
namespace Access {

class ExampleAccessRestriction : public AccessRestriction
{
public:
class ExampleAccessRestrictionEntryListener : public AccessRestriction::EntryListener
{
void OnEntryChanged(FabricIndex fabricIndex, size_t index, SharedPtr<AccessRestriction::Entry> entry,
ChangeType changeType) override
{
ChipLogProgress(NotSpecified, "AccessRestriction Entry changed: fabricIndex %d, index %ld, changeType %d", fabricIndex,
index, static_cast<int>(changeType));
}

void OnFabricRestrictionReviewUpdate(FabricIndex fabricIndex, uint64_t token, const char * instruction,
const char * redirectUrl) override
{}
};

ExampleAccessRestriction() : AccessRestriction() { AccessRestriction::AddListener(listener); }

~ExampleAccessRestriction() { AccessRestriction::RemoveListener(listener); }

protected:
CHIP_ERROR DoRequestFabricRestrictionReview(const FabricIndex fabricIndex, uint64_t token, const std::vector<Entry> & arl)
{
// this example simply removes all restrictions
while (Access::GetAccessControl().GetAccessRestriction()->DeleteEntry(0, fabricIndex) == CHIP_NO_ERROR)
;

return CHIP_NO_ERROR;
}

private:
ExampleAccessRestrictionEntryListener listener;
};

} // namespace Access
} // namespace chip
60 changes: 60 additions & 0 deletions examples/platform/linux/Options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <app/server/OnboardingCodesUtil.h>

#include <crypto/CHIPCryptoPAL.h>
#include <json/json.h>
#include <lib/core/CHIPError.h>
#include <lib/support/Base64.h>
#include <lib/support/BytesToHex.h>
Expand All @@ -47,6 +48,11 @@

using namespace chip;
using namespace chip::ArgParser;
using namespace chip::Platform;

#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
using namespace chip::Access;
#endif

namespace {
LinuxDeviceOptions gDeviceOptions;
Expand Down Expand Up @@ -82,6 +88,9 @@ enum
kDeviceOption_TraceFile,
kDeviceOption_TraceLog,
kDeviceOption_TraceDecode,
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
kDeviceOption_UseAccessRestrictions,
#endif
kOptionCSRResponseCSRIncorrectType,
kOptionCSRResponseCSRNonceIncorrectType,
kOptionCSRResponseCSRNonceTooLong,
Expand Down Expand Up @@ -154,6 +163,9 @@ OptionDef sDeviceOptionDefs[] = {
{ "trace_log", kArgumentRequired, kDeviceOption_TraceLog },
{ "trace_decode", kArgumentRequired, kDeviceOption_TraceDecode },
#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
{ "enable-access-restrictions", kArgumentRequired, kDeviceOption_UseAccessRestrictions },
#endif // CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
{ "cert_error_csr_incorrect_type", kNoArgument, kOptionCSRResponseCSRIncorrectType },
{ "cert_error_csr_existing_keypair", kNoArgument, kOptionCSRResponseCSRExistingKeyPair },
{ "cert_error_csr_nonce_incorrect_type", kNoArgument, kOptionCSRResponseCSRNonceIncorrectType },
Expand Down Expand Up @@ -280,6 +292,9 @@ const char * sDeviceOptionHelp =
" --trace_decode <1/0>\n"
" A value of 1 enables traces decoding, 0 disables this (default 0).\n"
#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
" --enable-access-restrictions <CommissioningARL JSON>\n"
" Enable ACL cluster access restrictions with the provided JSON CommissioningARL. Example:\n"
" \"[{\\\"endpoint\\\": 1,\\\"cluster\\\": 2,\\\"restrictions\\\": [{\\\"type\\\": 0,\\\"id\\\": 3}]}]\"\n"
" --cert_error_csr_incorrect_type\n"
" Configure the CSRResponse to be built with an invalid CSR type.\n"
" --cert_error_csr_existing_keypair\n"
Expand Down Expand Up @@ -320,6 +335,39 @@ const char * sDeviceOptionHelp =
#endif
"\n";

#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
bool ParseAccessRestrictionEntriesFromJson(const char * jsonString, std::vector<SharedPtr<AccessRestriction::Entry>> & entries)
{
Json::Value root;
Json::Reader reader;
VerifyOrReturnValue(reader.parse(jsonString, root), false);

for (Json::Value::const_iterator eIt = root.begin(); eIt != root.end(); eIt++)
{
auto entry = MakeShared<AccessRestriction::Entry>();

entry->endpointNumber = (*eIt)["endpoint"].asInt();
entry->clusterId = (*eIt)["cluster"].asInt();

Json::Value restrictions = (*eIt)["restrictions"];
for (Json::Value::const_iterator rIt = restrictions.begin(); rIt != restrictions.end(); rIt++)
{
AccessRestriction::Restriction restriction;
restriction.restrictionType = static_cast<AccessRestriction::Type>((*rIt)["type"].asInt());
if ((*rIt).isMember("id"))
{
restriction.id.SetValue((*rIt)["id"].asInt());
}
entry->restrictions.push_back(restriction);
}

entries.push_back(entry);
}

return true;
}
#endif // CHIP_CONFIG_USE_ACCESS_RESTRICTIONS

bool Base64ArgToVector(const char * arg, size_t maxSize, std::vector<uint8_t> & outVector)
{
size_t maxBase64Size = BASE64_ENCODED_LEN(maxSize);
Expand Down Expand Up @@ -529,6 +577,18 @@ bool HandleOption(const char * aProgram, OptionSet * aOptions, int aIdentifier,
break;
#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED

#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
case kDeviceOption_UseAccessRestrictions: {
std::vector<SharedPtr<AccessRestriction::Entry>> accessRestrictionEntries;
retval = ParseAccessRestrictionEntriesFromJson(aValue, accessRestrictionEntries);
if (retval)
{
LinuxDeviceOptions::GetInstance().accessRestrictionEntries.SetValue(std::move(accessRestrictionEntries));
}
}
break;
#endif // CHIP_CONFIG_USE_ACCESS_RESTRICTIONS

case kOptionCSRResponseCSRIncorrectType:
LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrIncorrectType = true;
break;
Expand Down
8 changes: 8 additions & 0 deletions examples/platform/linux/Options.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <string>
#include <vector>

#include <access/AccessConfig.h>
#include <inet/InetInterface.h>
#include <lib/core/CHIPError.h>
#include <lib/core/Optional.h>
Expand All @@ -38,6 +39,10 @@
#include <credentials/DeviceAttestationCredsProvider.h>
#include <testing/CustomCSRResponse.h>

#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
#include <access/AccessRestriction.h>
#endif

struct LinuxDeviceOptions
{
chip::PayloadContents payload;
Expand Down Expand Up @@ -81,6 +86,9 @@ struct LinuxDeviceOptions
#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
int32_t subscriptionCapacity = CHIP_IM_MAX_NUM_SUBSCRIPTIONS;
int32_t subscriptionResumptionRetryIntervalSec = -1;
#endif
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
chip::Optional<std::vector<chip::Platform::SharedPtr<chip::Access::AccessRestriction::Entry>>> accessRestrictionEntries;
#endif
static LinuxDeviceOptions & GetInstance();
};
Expand Down
22 changes: 22 additions & 0 deletions src/access/AccessConfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
*
* Copyright (c) 2020-2024 Project CHIP Authors
*
* 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.
*/

#pragma once

#if CHIP_HAVE_CONFIG_H
#include <access/AccessBuildConfig.h>
#endif
19 changes: 18 additions & 1 deletion src/access/AccessControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,11 @@ void AccessControl::RemoveEntryListener(EntryListener & listener)

bool AccessControl::IsAccessRestrictionListSupported() const
{
return false; // not yet supported
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
return mAccessRestriction != nullptr;
#else
return false;
#endif
}

CHIP_ERROR AccessControl::Check(const SubjectDescriptor & subjectDescriptor, const RequestPath & requestPath,
Expand All @@ -352,6 +356,19 @@ CHIP_ERROR AccessControl::Check(const SubjectDescriptor & subjectDescriptor, con
VerifyOrReturnError(requestPath.requestType != RequestType::kRequestTypeUnknown, CHIP_ERROR_INVALID_ARGUMENT);
}

#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
if (mAccessRestriction != nullptr)
{
CHIP_ERROR result = mAccessRestriction->Check(subjectDescriptor, requestPath);
if (result != CHIP_NO_ERROR)
{
ChipLogProgress(DataManagement, "AccessControl: %s",
(result == CHIP_ERROR_ACCESS_DENIED) ? "denied (restricted)" : "denied (restriction error)");
return result;
}
}
#endif

{
CHIP_ERROR result = mDelegate->Check(subjectDescriptor, requestPath, requestPrivilege);
if (result != CHIP_ERROR_NOT_IMPLEMENTED)
Expand Down
19 changes: 19 additions & 0 deletions src/access/AccessControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@

#pragma once

#include <access/AccessConfig.h>

#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
#include "AccessRestriction.h"
#endif

#include "Privilege.h"
#include "RequestPath.h"
#include "SubjectDescriptor.h"
Expand Down Expand Up @@ -627,6 +633,13 @@ class AccessControl
// Removes a listener from the listener list, if in the list.
void RemoveEntryListener(EntryListener & listener);

#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
// Set an optional AcceessRestriction object for MNGD feature.
void SetAccessRestriction(AccessRestriction * accessRestriction) { mAccessRestriction = accessRestriction; }

AccessRestriction * GetAccessRestriction() { return mAccessRestriction; }
#endif

/**
* Check whether or not Access Restriction List is supported.
*
Expand All @@ -638,6 +651,8 @@ class AccessControl
* Check whether access (by a subject descriptor, to a request path,
* requiring a privilege) should be allowed or denied.
*
* If an AccessRestriction object is set, it will be checked for additional access restrictions.
*
* @retval #CHIP_ERROR_ACCESS_DENIED if denied.
* @retval other errors should also be treated as denied.
* @retval #CHIP_NO_ERROR if allowed.
Expand All @@ -662,6 +677,10 @@ class AccessControl
DeviceTypeResolver * mDeviceTypeResolver = nullptr;

EntryListener * mEntryListener = nullptr;

#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
AccessRestriction * mAccessRestriction;
#endif
};

/**
Expand Down
Loading

0 comments on commit 5501b22

Please sign in to comment.