/* * * Copyright (c) 2020-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. */ // This is intended as a TOP LEVEL INCLUDE inside code that uses it namespace chip { namespace app { namespace { static bool CanAccessEvent(const Access::SubjectDescriptor & aSubjectDescriptor, const ConcreteClusterPath & aPath, Access::Privilege aNeededPrivilege) { Access::RequestPath requestPath{ .cluster = aPath.mClusterId, .endpoint = aPath.mEndpointId, .requestType = Access::RequestType::kEventReadRequest }; // leave requestPath.entityId optional value unset to indicate wildcard CHIP_ERROR err = Access::GetAccessControl().Check(aSubjectDescriptor, requestPath, aNeededPrivilege); return (err == CHIP_NO_ERROR); } static bool CanAccessEvent(const Access::SubjectDescriptor & aSubjectDescriptor, const ConcreteEventPath & aPath) { Access::RequestPath requestPath{ .cluster = aPath.mClusterId, .endpoint = aPath.mEndpointId, .requestType = Access::RequestType::kEventReadRequest, .entityId = aPath.mEventId }; CHIP_ERROR err = Access::GetAccessControl().Check(aSubjectDescriptor, requestPath, RequiredPrivilege::ForReadEvent(aPath)); return (err == CHIP_NO_ERROR); } /** * Helper to handle wildcard events in the event path. */ static bool HasValidEventPathForEndpointAndCluster(EndpointId aEndpoint, const EmberAfCluster * aCluster, const EventPathParams & aEventPath, const Access::SubjectDescriptor & aSubjectDescriptor) { if (aEventPath.HasWildcardEventId()) { // We have no way to expand wildcards. Just assume that we would need // View permissions for whatever events are involved. ConcreteClusterPath clusterPath(aEndpoint, aCluster->clusterId); return CanAccessEvent(aSubjectDescriptor, clusterPath, Access::Privilege::kView); } ConcreteEventPath path(aEndpoint, aCluster->clusterId, aEventPath.mEventId); return CanAccessEvent(aSubjectDescriptor, path); } /** * Helper to handle wildcard clusters in the event path. */ static bool HasValidEventPathForEndpoint(EndpointId aEndpoint, const EventPathParams & aEventPath, const Access::SubjectDescriptor & aSubjectDescriptor) { if (aEventPath.HasWildcardClusterId()) { auto * endpointType = emberAfFindEndpointType(aEndpoint); if (endpointType == nullptr) { // Not going to have any valid paths in here. return false; } for (decltype(endpointType->clusterCount) idx = 0; idx < endpointType->clusterCount; ++idx) { bool hasValidPath = HasValidEventPathForEndpointAndCluster(aEndpoint, &endpointType->cluster[idx], aEventPath, aSubjectDescriptor); if (hasValidPath) { return true; } } return false; } auto * cluster = emberAfFindServerCluster(aEndpoint, aEventPath.mClusterId); if (cluster == nullptr) { // Nothing valid here. return false; } return HasValidEventPathForEndpointAndCluster(aEndpoint, cluster, aEventPath, aSubjectDescriptor); } } // namespace } // namespace app } // namespace chip