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
{
@@ -584,30 +724,13 @@ CHIP_ERROR InteractionModelEngine::ParseEventPaths(const Access::SubjectDescript
584
724
continue ;
585
725
}
586
726
587
- #if CHIP_CONFIG_USE_DATA_MODEL_INTERFACE
588
- aHasValidEventPath = mDataModelProvider ->EventPathIncludesAccessibleConcretePath (eventPath, aSubjectDescriptor);
589
- #else
590
727
// The definition of "valid path" is "path exists and ACL allows
591
728
// access". We need to do some expansion of wildcards to handle that.
592
- if (eventPath.HasWildcardEndpointId ())
593
- {
594
- for (uint16_t endpointIndex = 0 ; !aHasValidEventPath && endpointIndex < emberAfEndpointCount (); ++endpointIndex)
595
- {
596
- if (!emberAfEndpointIndexIsEnabled (endpointIndex))
597
- {
598
- continue ;
599
- }
600
- aHasValidEventPath =
601
- HasValidEventPathForEndpoint (emberAfEndpointFromIndex (endpointIndex), eventPath, aSubjectDescriptor);
602
- }
603
- }
604
- else
605
- {
606
- // No need to check whether the endpoint is enabled, because
607
- // emberAfFindEndpointType returns null for disabled endpoints.
608
- aHasValidEventPath = HasValidEventPathForEndpoint (eventPath.mEndpointId , eventPath, aSubjectDescriptor);
609
- }
610
- #endif // CHIP_CONFIG_USE_EMBER_DATA_MODEL
729
+ #if CHIP_CONFIG_USE_DATA_MODEL_INTERFACE
730
+ aHasValidEventPath = MayHaveAccessibleEventPath (mDataModelProvider , eventPath, aSubjectDescriptor);
731
+ #else
732
+ aHasValidEventPath = MayHaveAccessibleEventPath (eventPath, aSubjectDescriptor);
733
+ #endif
611
734
}
612
735
613
736
if (err == CHIP_ERROR_END_OF_TLV)
@@ -677,7 +800,7 @@ Protocols::InteractionModel::Status InteractionModelEngine::OnReadInitialRequest
677
800
size_t requestedEventPathCount = 0 ;
678
801
AttributePathIBs::Parser attributePathListParser;
679
802
bool hasValidAttributePath = false ;
680
- bool hasValidEventPath = false ;
803
+ bool mayHaveValidEventPath = false ;
681
804
682
805
CHIP_ERROR err = subscribeRequestParser.GetAttributeRequests (&attributePathListParser);
683
806
if (err == CHIP_NO_ERROR)
@@ -700,7 +823,7 @@ Protocols::InteractionModel::Status InteractionModelEngine::OnReadInitialRequest
700
823
if (err == CHIP_NO_ERROR)
701
824
{
702
825
auto subjectDescriptor = apExchangeContext->GetSessionHandle ()->AsSecureSession ()->GetSubjectDescriptor ();
703
- err = ParseEventPaths (subjectDescriptor, eventPathListParser, hasValidEventPath , requestedEventPathCount);
826
+ err = ParseEventPaths (subjectDescriptor, eventPathListParser, mayHaveValidEventPath , requestedEventPathCount);
704
827
if (err != CHIP_NO_ERROR)
705
828
{
706
829
return Status::InvalidAction;
@@ -720,7 +843,7 @@ Protocols::InteractionModel::Status InteractionModelEngine::OnReadInitialRequest
720
843
return Status::InvalidAction;
721
844
}
722
845
723
- if (!hasValidAttributePath && !hasValidEventPath )
846
+ if (!hasValidAttributePath && !mayHaveValidEventPath )
724
847
{
725
848
ChipLogError (InteractionModel,
726
849
" Subscription from [%u:" ChipLogFormatX64 " ] has no access at all. Rejecting request." ,
0 commit comments