27
27
28
28
#include < cinttypes>
29
29
30
+ #include < access/AccessRestrictionProvider.h>
31
+ #include < access/Privilege.h>
30
32
#include < access/RequestPath.h>
31
33
#include < access/SubjectDescriptor.h>
32
34
#include < app/AppConfig.h>
33
35
#include < app/CommandHandlerInterfaceRegistry.h>
36
+ #include < app/EventPathParams.h>
34
37
#include < app/RequiredPrivilege.h>
35
38
#include < app/data-model-provider/ActionReturnStatus.h>
36
39
#include < app/data-model-provider/MetadataTypes.h>
39
42
#include < app/util/af-types.h>
40
43
#include < app/util/ember-compatibility-functions.h>
41
44
#include < app/util/endpoint-config-api.h>
45
+ #include < lib/core/CHIPError.h>
42
46
#include < lib/core/DataModelTypes.h>
43
47
#include < lib/core/Global.h>
44
48
#include < lib/core/TLVUtilities.h>
53
57
#include < app/codegen-data-model-provider/Instance.h>
54
58
#endif
55
59
56
- #if !CHIP_CONFIG_USE_DATA_MODEL_INTERFACE
57
- #include < app/ember_coupling/EventPathValidity.mixin.h> // nogncheck
58
- #endif
59
-
60
60
namespace chip {
61
61
namespace app {
62
+ namespace {
63
+
64
+ /* *
65
+ * Helper to handle wildcard events in the event path.
66
+ *
67
+ * Validates that ACL access is permitted to:
68
+ * - Cluster::View in case the path is a wildcard for the event id
69
+ * - Event read if the path is a concrete event path
70
+ */
71
+ bool MayHaveAccessibleEventPathForEndpointAndCluster (const ConcreteClusterPath & path, const EventPathParams & aEventPath,
72
+ const Access::SubjectDescriptor & aSubjectDescriptor)
73
+ {
74
+ Access::RequestPath requestPath{ .cluster = path.mClusterId ,
75
+ .endpoint = path.mEndpointId ,
76
+ .requestType = Access::RequestType::kEventReadRequest };
77
+
78
+ Access::Privilege requiredPrivilege = Access::Privilege::kView ;
79
+
80
+ if (!aEventPath.HasWildcardEventId ())
81
+ {
82
+ requestPath.entityId = aEventPath.mEventId ;
83
+ requiredPrivilege =
84
+ RequiredPrivilege::ForReadEvent (ConcreteEventPath (path.mEndpointId , path.mClusterId , aEventPath.mEventId ));
85
+ }
86
+
87
+ return (Access::GetAccessControl ().Check (aSubjectDescriptor, requestPath, requiredPrivilege) == CHIP_NO_ERROR);
88
+ }
89
+
90
+ #if CHIP_CONFIG_USE_DATA_MODEL_INTERFACE
91
+
92
+ bool MayHaveAccessibleEventPathForEndpoint (DataModel::Provider * aProvider, EndpointId aEndpoint,
93
+ const EventPathParams & aEventPath, const Access::SubjectDescriptor & aSubjectDescriptor)
94
+ {
95
+ if (!aEventPath.HasWildcardClusterId ())
96
+ {
97
+ return MayHaveAccessibleEventPathForEndpointAndCluster (ConcreteClusterPath (aEndpoint, aEventPath.mClusterId ), aEventPath,
98
+ aSubjectDescriptor);
99
+ }
100
+
101
+ DataModel::ClusterEntry clusterEntry = aProvider->FirstCluster (aEventPath.mEndpointId );
102
+ while (clusterEntry.IsValid ())
103
+ {
104
+ if (MayHaveAccessibleEventPathForEndpointAndCluster (clusterEntry.path , aEventPath, aSubjectDescriptor))
105
+ {
106
+ return true ;
107
+ }
108
+ clusterEntry = aProvider->NextCluster (clusterEntry.path );
109
+ }
110
+
111
+ return false ;
112
+ }
113
+
114
+ bool MayHaveAccessibleEventPath (DataModel::Provider * aProvider, const EventPathParams & aEventPath,
115
+ const Access::SubjectDescriptor & subjectDescriptor)
116
+ {
117
+ VerifyOrReturnValue (aProvider != nullptr , false );
118
+
119
+ if (!aEventPath.HasWildcardEndpointId ())
120
+ {
121
+ return MayHaveAccessibleEventPathForEndpoint (aProvider, aEventPath.mEndpointId , aEventPath, subjectDescriptor);
122
+ }
123
+
124
+ for (EndpointId endpointId = aProvider->FirstEndpoint (); endpointId != kInvalidEndpointId ;
125
+ endpointId = aProvider->NextEndpoint (endpointId))
126
+ {
127
+ if (MayHaveAccessibleEventPathForEndpoint (aProvider, endpointId, aEventPath, subjectDescriptor))
128
+ {
129
+ return true ;
130
+ }
131
+ }
132
+ return false ;
133
+ }
134
+
135
+ #else
136
+
137
+ /* *
138
+ * Helper to handle wildcard clusters in the event path.
139
+ */
140
+ bool MayHaveAccessibleEventPathForEndpoint (EndpointId aEndpoint, const EventPathParams & aEventPath,
141
+ const Access::SubjectDescriptor & aSubjectDescriptor)
142
+ {
143
+ if (aEventPath.HasWildcardClusterId ())
144
+ {
145
+ auto * endpointType = emberAfFindEndpointType (aEndpoint);
146
+ if (endpointType == nullptr )
147
+ {
148
+ // Not going to have any valid paths in here.
149
+ return false ;
150
+ }
151
+
152
+ for (decltype (endpointType->clusterCount ) idx = 0 ; idx < endpointType->clusterCount ; ++idx)
153
+ {
154
+ bool mayHaveAccessiblePath = MayHaveAccessibleEventPathForEndpointAndCluster (
155
+ ConcreteClusterPath (aEndpoint, endpointType->cluster [idx].clusterId ), aEventPath, aSubjectDescriptor);
156
+ if (mayHaveAccessiblePath)
157
+ {
158
+ return true ;
159
+ }
160
+ }
161
+
162
+ return false ;
163
+ }
164
+
165
+ auto * cluster = emberAfFindServerCluster (aEndpoint, aEventPath.mClusterId );
166
+ if (cluster == nullptr )
167
+ {
168
+ // Nothing valid here.
169
+ return false ;
170
+ }
171
+ return MayHaveAccessibleEventPathForEndpointAndCluster (ConcreteClusterPath (aEndpoint, cluster->clusterId ), aEventPath,
172
+ aSubjectDescriptor);
173
+ }
174
+
175
+ bool MayHaveAccessibleEventPath (const EventPathParams & aEventPath, const Access::SubjectDescriptor & aSubjectDescriptor)
176
+ {
177
+ if (!aEventPath.HasWildcardEndpointId ())
178
+ {
179
+ // No need to check whether the endpoint is enabled, because
180
+ // emberAfFindEndpointType returns null for disabled endpoints.
181
+ return MayHaveAccessibleEventPathForEndpoint (aEventPath.mEndpointId , aEventPath, aSubjectDescriptor);
182
+ }
183
+
184
+ for (uint16_t endpointIndex = 0 ; endpointIndex < emberAfEndpointCount (); ++endpointIndex)
185
+ {
186
+ if (!emberAfEndpointIndexIsEnabled (endpointIndex))
187
+ {
188
+ continue ;
189
+ }
190
+ if (MayHaveAccessibleEventPathForEndpoint (emberAfEndpointFromIndex (endpointIndex), aEventPath, aSubjectDescriptor))
191
+ {
192
+ return true ;
193
+ }
194
+ }
195
+
196
+ // none of the paths matched
197
+ return false ;
198
+ }
199
+ #endif
200
+
201
+ } // namespace
62
202
63
203
class AutoReleaseSubscriptionInfoIterator
64
204
{
@@ -583,30 +723,13 @@ CHIP_ERROR InteractionModelEngine::ParseEventPaths(const Access::SubjectDescript
583
723
continue ;
584
724
}
585
725
586
- #if CHIP_CONFIG_USE_DATA_MODEL_INTERFACE
587
- aHasValidEventPath = mDataModelProvider ->EventPathIncludesAccessibleConcretePath (eventPath, aSubjectDescriptor);
588
- #else
589
726
// The definition of "valid path" is "path exists and ACL allows
590
727
// access". We need to do some expansion of wildcards to handle that.
591
- if (eventPath.HasWildcardEndpointId ())
592
- {
593
- for (uint16_t endpointIndex = 0 ; !aHasValidEventPath && endpointIndex < emberAfEndpointCount (); ++endpointIndex)
594
- {
595
- if (!emberAfEndpointIndexIsEnabled (endpointIndex))
596
- {
597
- continue ;
598
- }
599
- aHasValidEventPath =
600
- HasValidEventPathForEndpoint (emberAfEndpointFromIndex (endpointIndex), eventPath, aSubjectDescriptor);
601
- }
602
- }
603
- else
604
- {
605
- // No need to check whether the endpoint is enabled, because
606
- // emberAfFindEndpointType returns null for disabled endpoints.
607
- aHasValidEventPath = HasValidEventPathForEndpoint (eventPath.mEndpointId , eventPath, aSubjectDescriptor);
608
- }
609
- #endif // CHIP_CONFIG_USE_EMBER_DATA_MODEL
728
+ #if CHIP_CONFIG_USE_DATA_MODEL_INTERFACE
729
+ aHasValidEventPath = MayHaveAccessibleEventPath (mDataModelProvider , eventPath, aSubjectDescriptor);
730
+ #else
731
+ aHasValidEventPath = MayHaveAccessibleEventPath (eventPath, aSubjectDescriptor);
732
+ #endif
610
733
}
611
734
612
735
if (err == CHIP_ERROR_END_OF_TLV)
@@ -676,7 +799,7 @@ Protocols::InteractionModel::Status InteractionModelEngine::OnReadInitialRequest
676
799
size_t requestedEventPathCount = 0 ;
677
800
AttributePathIBs::Parser attributePathListParser;
678
801
bool hasValidAttributePath = false ;
679
- bool hasValidEventPath = false ;
802
+ bool mayHaveValidEventPath = false ;
680
803
681
804
CHIP_ERROR err = subscribeRequestParser.GetAttributeRequests (&attributePathListParser);
682
805
if (err == CHIP_NO_ERROR)
@@ -699,7 +822,7 @@ Protocols::InteractionModel::Status InteractionModelEngine::OnReadInitialRequest
699
822
if (err == CHIP_NO_ERROR)
700
823
{
701
824
auto subjectDescriptor = apExchangeContext->GetSessionHandle ()->AsSecureSession ()->GetSubjectDescriptor ();
702
- err = ParseEventPaths (subjectDescriptor, eventPathListParser, hasValidEventPath , requestedEventPathCount);
825
+ err = ParseEventPaths (subjectDescriptor, eventPathListParser, mayHaveValidEventPath , requestedEventPathCount);
703
826
if (err != CHIP_NO_ERROR)
704
827
{
705
828
return Status::InvalidAction;
@@ -719,7 +842,7 @@ Protocols::InteractionModel::Status InteractionModelEngine::OnReadInitialRequest
719
842
return Status::InvalidAction;
720
843
}
721
844
722
- if (!hasValidAttributePath && !hasValidEventPath )
845
+ if (!hasValidAttributePath && !mayHaveValidEventPath )
723
846
{
724
847
ChipLogError (InteractionModel,
725
848
" Subscription from [%u:" ChipLogFormatX64 " ] has no access at all. Rejecting request." ,
0 commit comments