Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2021 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : #pragma once
20 :
21 : #include <access/AccessConfig.h>
22 :
23 : #if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
24 : #include "AccessRestrictionProvider.h"
25 : #endif
26 :
27 : #include "Privilege.h"
28 : #include "RequestPath.h"
29 : #include "SubjectDescriptor.h"
30 :
31 : #include <lib/core/CHIPCore.h>
32 : #include <lib/core/Global.h>
33 : #include <lib/support/CodeUtils.h>
34 :
35 : // Dump function for use during development only (0 for disabled, non-zero for enabled).
36 : #define CHIP_ACCESS_CONTROL_DUMP_ENABLED 0
37 :
38 : namespace chip {
39 : namespace Access {
40 :
41 : class AccessControl
42 : {
43 : public:
44 : /**
45 : * Used by access control to determine if a device type resolves to an endpoint.
46 : */
47 : struct DeviceTypeResolver
48 : {
49 : public:
50 2 : virtual ~DeviceTypeResolver() = default;
51 :
52 : virtual bool IsDeviceTypeOnEndpoint(DeviceTypeId deviceType, EndpointId endpoint) = 0;
53 : };
54 :
55 : /**
56 : * Handle to an entry in the access control list.
57 : *
58 : * Must be prepared (`AccessControl::PrepareEntry`) or read (`AccessControl::ReadEntry`) before first use.
59 : */
60 : class Entry
61 : {
62 : public:
63 : struct Target
64 : {
65 : using Flags = unsigned;
66 : static constexpr Flags kCluster = 1 << 0;
67 : static constexpr Flags kEndpoint = 1 << 1;
68 : static constexpr Flags kDeviceType = 1 << 2;
69 : Flags flags = 0;
70 : ClusterId cluster;
71 : EndpointId endpoint;
72 : DeviceTypeId deviceType;
73 : };
74 :
75 : class Delegate
76 : {
77 : public:
78 : Delegate() = default;
79 :
80 : Delegate(const Delegate &) = delete;
81 : Delegate & operator=(const Delegate &) = delete;
82 :
83 67 : virtual ~Delegate() = default;
84 :
85 0 : virtual void Release() {}
86 :
87 : // Simple getters
88 0 : virtual CHIP_ERROR GetAuthMode(AuthMode & authMode) const { return CHIP_ERROR_NOT_IMPLEMENTED; }
89 0 : virtual CHIP_ERROR GetFabricIndex(FabricIndex & fabricIndex) const { return CHIP_ERROR_NOT_IMPLEMENTED; }
90 0 : virtual CHIP_ERROR GetPrivilege(Privilege & privilege) const { return CHIP_ERROR_NOT_IMPLEMENTED; }
91 :
92 : // Simple setters
93 0 : virtual CHIP_ERROR SetAuthMode(AuthMode authMode) { return CHIP_ERROR_NOT_IMPLEMENTED; }
94 0 : virtual CHIP_ERROR SetFabricIndex(FabricIndex fabricIndex) { return CHIP_ERROR_NOT_IMPLEMENTED; }
95 0 : virtual CHIP_ERROR SetPrivilege(Privilege privilege) { return CHIP_ERROR_NOT_IMPLEMENTED; }
96 :
97 : // Subjects
98 0 : virtual CHIP_ERROR GetSubjectCount(size_t & count) const { return CHIP_ERROR_NOT_IMPLEMENTED; }
99 0 : virtual CHIP_ERROR GetSubject(size_t index, NodeId & subject) const { return CHIP_ERROR_NOT_IMPLEMENTED; }
100 0 : virtual CHIP_ERROR SetSubject(size_t index, NodeId subject) { return CHIP_ERROR_NOT_IMPLEMENTED; }
101 0 : virtual CHIP_ERROR AddSubject(size_t * index, NodeId subject) { return CHIP_ERROR_NOT_IMPLEMENTED; }
102 0 : virtual CHIP_ERROR RemoveSubject(size_t index) { return CHIP_ERROR_NOT_IMPLEMENTED; }
103 :
104 : // Targets
105 0 : virtual CHIP_ERROR GetTargetCount(size_t & count) const { return CHIP_ERROR_NOT_IMPLEMENTED; }
106 0 : virtual CHIP_ERROR GetTarget(size_t index, Target & target) const { return CHIP_ERROR_NOT_IMPLEMENTED; }
107 0 : virtual CHIP_ERROR SetTarget(size_t index, const Target & target) { return CHIP_ERROR_NOT_IMPLEMENTED; }
108 0 : virtual CHIP_ERROR AddTarget(size_t * index, const Target & target) { return CHIP_ERROR_NOT_IMPLEMENTED; }
109 0 : virtual CHIP_ERROR RemoveTarget(size_t index) { return CHIP_ERROR_NOT_IMPLEMENTED; }
110 : };
111 :
112 0 : Entry() = default;
113 :
114 : Entry(Entry && other) : mDelegate(other.mDelegate) { other.mDelegate = &mDefaultDelegate.get(); }
115 :
116 : Entry & operator=(Entry && other)
117 : {
118 : if (this != &other)
119 : {
120 : mDelegate->Release();
121 : mDelegate = other.mDelegate;
122 : other.mDelegate = &mDefaultDelegate.get();
123 : }
124 : return *this;
125 : }
126 :
127 : Entry(const Entry &) = delete;
128 : Entry & operator=(const Entry &) = delete;
129 :
130 0 : ~Entry() { mDelegate->Release(); }
131 :
132 : // Simple getters
133 0 : CHIP_ERROR GetAuthMode(AuthMode & authMode) const { return mDelegate->GetAuthMode(authMode); }
134 0 : CHIP_ERROR GetFabricIndex(FabricIndex & fabricIndex) const { return mDelegate->GetFabricIndex(fabricIndex); }
135 0 : CHIP_ERROR GetPrivilege(Privilege & privilege) const { return mDelegate->GetPrivilege(privilege); }
136 :
137 : // Simple setters
138 0 : CHIP_ERROR SetAuthMode(AuthMode authMode) { return mDelegate->SetAuthMode(authMode); }
139 0 : CHIP_ERROR SetFabricIndex(FabricIndex fabricIndex) { return mDelegate->SetFabricIndex(fabricIndex); }
140 0 : CHIP_ERROR SetPrivilege(Privilege privilege) { return mDelegate->SetPrivilege(privilege); }
141 :
142 : /**
143 : * Gets the number of subjects.
144 : *
145 : * @param [out] count The number of subjects.
146 : */
147 0 : CHIP_ERROR GetSubjectCount(size_t & count) const { return mDelegate->GetSubjectCount(count); }
148 :
149 : /**
150 : * Gets the specified subject.
151 : *
152 : * @param [in] index The index of the subject to get.
153 : * @param [out] subject The subject into which to get.
154 : */
155 0 : CHIP_ERROR GetSubject(size_t index, NodeId & subject) const { return mDelegate->GetSubject(index, subject); }
156 :
157 : /**
158 : * Sets the specified subject.
159 : *
160 : * @param [in] index The index of the subject to set.
161 : * @param [in] subject The subject from which to set.
162 : */
163 : CHIP_ERROR SetSubject(size_t index, NodeId subject) { return mDelegate->SetSubject(index, subject); }
164 :
165 : /**
166 : * Adds the specified subject.
167 : *
168 : * @param [out] index The index of the added subject, if not null.
169 : * @param [in] subject The subject to add.
170 : */
171 0 : CHIP_ERROR AddSubject(size_t * index, NodeId subject) { return mDelegate->AddSubject(index, subject); }
172 :
173 : /**
174 : * Removes the specified subject.
175 : *
176 : * @param [in] index The index of the subject to delete.
177 : */
178 : CHIP_ERROR RemoveSubject(size_t index) { return mDelegate->RemoveSubject(index); }
179 :
180 : /**
181 : * Gets the number of targets.
182 : *
183 : * @param [out] count The number of targets.
184 : */
185 0 : CHIP_ERROR GetTargetCount(size_t & count) const { return mDelegate->GetTargetCount(count); }
186 :
187 : /**
188 : * Gets the specified target.
189 : *
190 : * @param [in] index The index of the target to get.
191 : * @param [out] target The target into which to get.
192 : */
193 0 : CHIP_ERROR GetTarget(size_t index, Target & target) const { return mDelegate->GetTarget(index, target); }
194 :
195 : /**
196 : * Sets the specified target.
197 : *
198 : * @param [in] index The index of the target to set.
199 : * @param [in] target The target from which to set.
200 : */
201 : CHIP_ERROR SetTarget(size_t index, const Target & target) { return mDelegate->SetTarget(index, target); }
202 :
203 : /**
204 : * Adds the specified target.
205 : *
206 : * @param [out] index The index of the added target, if not null.
207 : * @param [in] target The target to add.
208 : */
209 0 : CHIP_ERROR AddTarget(size_t * index, const Target & target) { return mDelegate->AddTarget(index, target); }
210 :
211 : /**
212 : * Removes the specified target.
213 : *
214 : * @param [in] index The index of the target to delete.
215 : */
216 : CHIP_ERROR RemoveTarget(size_t index) { return mDelegate->RemoveTarget(index); }
217 :
218 0 : bool HasDefaultDelegate() const { return mDelegate == &mDefaultDelegate.get(); }
219 :
220 1416 : const Delegate & GetDelegate() const { return *mDelegate; }
221 :
222 1251 : Delegate & GetDelegate() { return *mDelegate; }
223 :
224 0 : void SetDelegate(Delegate & delegate)
225 : {
226 0 : mDelegate->Release();
227 0 : mDelegate = &delegate;
228 0 : }
229 :
230 0 : void ResetDelegate()
231 : {
232 0 : mDelegate->Release();
233 0 : mDelegate = &mDefaultDelegate.get();
234 0 : }
235 :
236 : /**
237 : * Validate whether an ACL Entry is valid and complies with all defined constraints.
238 : *
239 : * @retval true if all the fields within the Entry are valid and compliant.
240 : */
241 : bool IsValid() const;
242 :
243 : private:
244 : static Global<Delegate> mDefaultDelegate;
245 : Delegate * mDelegate = &mDefaultDelegate.get();
246 : };
247 :
248 : /**
249 : * Handle to an entry iterator in the access control list.
250 : *
251 : * Must be initialized (`AccessControl::Entries`) before first use.
252 : */
253 : class EntryIterator
254 : {
255 : public:
256 : class Delegate
257 : {
258 : public:
259 2 : Delegate() = default;
260 :
261 : Delegate(const Delegate &) = delete;
262 : Delegate & operator=(const Delegate &) = delete;
263 :
264 69 : virtual ~Delegate() = default;
265 :
266 53 : virtual void Release() {}
267 :
268 0 : virtual CHIP_ERROR Next(Entry & entry) { return CHIP_ERROR_SENTINEL; }
269 : };
270 :
271 0 : EntryIterator() = default;
272 :
273 : EntryIterator(const EntryIterator &) = delete;
274 : EntryIterator & operator=(const EntryIterator &) = delete;
275 :
276 0 : ~EntryIterator() { mDelegate->Release(); }
277 :
278 0 : CHIP_ERROR Next(Entry & entry) { return mDelegate->Next(entry); }
279 :
280 : const Delegate & GetDelegate() const { return *mDelegate; }
281 :
282 56 : Delegate & GetDelegate() { return *mDelegate; }
283 :
284 56 : void SetDelegate(Delegate & delegate)
285 : {
286 56 : mDelegate->Release();
287 56 : mDelegate = &delegate;
288 56 : }
289 :
290 : void ResetDelegate()
291 : {
292 : mDelegate->Release();
293 : mDelegate = &mDefaultDelegate.get();
294 : }
295 :
296 : private:
297 : static Global<Delegate> mDefaultDelegate;
298 : Delegate * mDelegate = &mDefaultDelegate.get();
299 : };
300 :
301 : /**
302 : * Used by access control to notify of changes in access control list.
303 : */
304 : class EntryListener
305 : {
306 : public:
307 : enum class ChangeType
308 : {
309 : kAdded = 1,
310 : kRemoved = 2,
311 : kUpdated = 3
312 : };
313 :
314 2 : virtual ~EntryListener() = default;
315 :
316 : /**
317 : * Notifies of a change in the access control list.
318 : *
319 : * The fabric is indicated by its own parameter. If available, a subject descriptor will
320 : * have more detail (and its fabric index will match). A best effort is made to provide
321 : * the latest value of the changed entry.
322 : *
323 : * @param [in] subjectDescriptor Optional (if available) subject descriptor for this operation.
324 : * @param [in] fabric Index of fabric in which entry has changed.
325 : * @param [in] index Index of entry to which has changed (relative to fabric).
326 : * @param [in] entry Optional (best effort) latest value of entry which has changed.
327 : * @param [in] changeType Type of change.
328 : */
329 : virtual void OnEntryChanged(const SubjectDescriptor * subjectDescriptor, FabricIndex fabric, size_t index,
330 : const Entry * entry, ChangeType changeType) = 0;
331 :
332 : private:
333 : EntryListener * mNext = nullptr;
334 :
335 : friend class AccessControl;
336 : };
337 :
338 : class Delegate
339 : {
340 : public:
341 : Delegate() = default;
342 :
343 : Delegate(const Delegate &) = delete;
344 : Delegate & operator=(const Delegate &) = delete;
345 :
346 25 : virtual ~Delegate() = default;
347 :
348 0 : virtual void Release() {}
349 :
350 0 : virtual CHIP_ERROR Init() { return CHIP_NO_ERROR; }
351 0 : virtual void Finish() {}
352 :
353 : // Capabilities
354 0 : virtual CHIP_ERROR GetMaxEntriesPerFabric(size_t & value) const
355 : {
356 0 : value = 0;
357 0 : return CHIP_NO_ERROR;
358 : }
359 :
360 0 : virtual CHIP_ERROR GetMaxSubjectsPerEntry(size_t & value) const
361 : {
362 0 : value = 0;
363 0 : return CHIP_NO_ERROR;
364 : }
365 :
366 0 : virtual CHIP_ERROR GetMaxTargetsPerEntry(size_t & value) const
367 : {
368 0 : value = 0;
369 0 : return CHIP_NO_ERROR;
370 : }
371 :
372 0 : virtual CHIP_ERROR GetMaxEntryCount(size_t & value) const
373 : {
374 0 : value = 0;
375 0 : return CHIP_NO_ERROR;
376 : }
377 :
378 : // Actualities
379 0 : virtual CHIP_ERROR GetEntryCount(FabricIndex fabric, size_t & value) const
380 : {
381 0 : value = 0;
382 0 : return CHIP_NO_ERROR;
383 : }
384 :
385 0 : virtual CHIP_ERROR GetEntryCount(size_t & value) const
386 : {
387 0 : value = 0;
388 0 : return CHIP_NO_ERROR;
389 : }
390 :
391 : // Preparation
392 0 : virtual CHIP_ERROR PrepareEntry(Entry & entry) { return CHIP_NO_ERROR; }
393 :
394 : // CRUD
395 0 : virtual CHIP_ERROR CreateEntry(size_t * index, const Entry & entry, FabricIndex * fabricIndex) { return CHIP_NO_ERROR; }
396 0 : virtual CHIP_ERROR ReadEntry(size_t index, Entry & entry, const FabricIndex * fabricIndex) const { return CHIP_NO_ERROR; }
397 0 : virtual CHIP_ERROR UpdateEntry(size_t index, const Entry & entry, const FabricIndex * fabricIndex) { return CHIP_NO_ERROR; }
398 0 : virtual CHIP_ERROR DeleteEntry(size_t index, const FabricIndex * fabricIndex) { return CHIP_NO_ERROR; }
399 :
400 : // Iteration
401 0 : virtual CHIP_ERROR Entries(EntryIterator & iterator, const FabricIndex * fabricIndex) const { return CHIP_NO_ERROR; }
402 :
403 : // Check
404 : // Return CHIP_NO_ERROR if allowed, CHIP_ERROR_ACCESS_DENIED if denied,
405 : // CHIP_ERROR_NOT_IMPLEMENTED to use the default check algorithm (against entries),
406 : // or any other CHIP_ERROR if another error occurred.
407 0 : virtual CHIP_ERROR Check(const SubjectDescriptor & subjectDescriptor, const RequestPath & requestPath,
408 : Privilege requestPrivilege)
409 : {
410 0 : return CHIP_ERROR_ACCESS_DENIED;
411 : }
412 : };
413 :
414 2 : AccessControl() = default;
415 :
416 : AccessControl(const AccessControl &) = delete;
417 : AccessControl & operator=(const AccessControl &) = delete;
418 :
419 43 : ~AccessControl()
420 : {
421 : // Never-initialized AccessControl instances will not have the delegate set.
422 43 : if (IsInitialized())
423 : {
424 0 : mDelegate->Release();
425 : }
426 43 : }
427 :
428 : /**
429 : * Initialize the access control module. Must be called before first use.
430 : *
431 : * @return CHIP_NO_ERROR on success, CHIP_ERROR_INCORRECT_STATE if called more than once,
432 : * CHIP_ERROR_INVALID_ARGUMENT if delegate is null, or other fatal error.
433 : */
434 : CHIP_ERROR Init(AccessControl::Delegate * delegate, DeviceTypeResolver & deviceTypeResolver);
435 :
436 : /**
437 : * Deinitialize the access control module. Must be called when finished.
438 : */
439 : void Finish();
440 :
441 : // Capabilities
442 : CHIP_ERROR GetMaxEntriesPerFabric(size_t & value) const
443 : {
444 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
445 : return mDelegate->GetMaxEntriesPerFabric(value);
446 : }
447 :
448 : CHIP_ERROR GetMaxSubjectsPerEntry(size_t & value) const
449 : {
450 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
451 : return mDelegate->GetMaxSubjectsPerEntry(value);
452 : }
453 :
454 : CHIP_ERROR GetMaxTargetsPerEntry(size_t & value) const
455 : {
456 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
457 : return mDelegate->GetMaxTargetsPerEntry(value);
458 : }
459 :
460 : CHIP_ERROR GetMaxEntryCount(size_t & value) const
461 : {
462 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
463 : return mDelegate->GetMaxEntryCount(value);
464 : }
465 :
466 : // Actualities
467 0 : CHIP_ERROR GetEntryCount(FabricIndex fabric, size_t & value) const
468 : {
469 0 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
470 0 : return mDelegate->GetEntryCount(fabric, value);
471 : }
472 :
473 : CHIP_ERROR GetEntryCount(size_t & value) const
474 : {
475 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
476 : return mDelegate->GetEntryCount(value);
477 : }
478 :
479 : /**
480 : * Prepares an entry.
481 : *
482 : * An entry must be prepared or read (`ReadEntry`) before first use.
483 : *
484 : * @param [in] entry Entry to prepare.
485 : */
486 0 : CHIP_ERROR PrepareEntry(Entry & entry)
487 : {
488 0 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
489 0 : return mDelegate->PrepareEntry(entry);
490 : }
491 :
492 : /**
493 : * Creates an entry in the access control list.
494 : *
495 : * @param [in] subjectDescriptor Optional subject descriptor for this operation.
496 : * @param [in] fabric Index of fabric in which to create entry.
497 : * @param [out] index (If not nullptr) index of created entry (relative to fabric).
498 : * @param [in] entry Entry from which created entry is copied.
499 : */
500 : CHIP_ERROR CreateEntry(const SubjectDescriptor * subjectDescriptor, FabricIndex fabric, size_t * index, const Entry & entry);
501 :
502 : /**
503 : * Creates an entry in the access control list.
504 : *
505 : * @param [out] index Entry index of created entry, if not null. May be relative to `fabricIndex`.
506 : * @param [in] entry Entry from which to copy.
507 : * @param [out] fabricIndex Fabric index of created entry, if not null, in which case entry `index` will be relative to fabric.
508 : */
509 : CHIP_ERROR CreateEntry(size_t * index, const Entry & entry, FabricIndex * fabricIndex = nullptr)
510 : {
511 : VerifyOrReturnError(entry.IsValid(), CHIP_ERROR_INVALID_ARGUMENT);
512 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
513 : return mDelegate->CreateEntry(index, entry, fabricIndex);
514 : }
515 :
516 : /**
517 : * Reads an entry in the access control list.
518 : *
519 : * @param [in] fabric Index of fabric in which to read entry.
520 : * @param [in] index Index of entry to read (relative to fabric).
521 : * @param [in] entry Entry into which read entry is copied.
522 : */
523 0 : CHIP_ERROR ReadEntry(FabricIndex fabric, size_t index, Entry & entry) const
524 : {
525 0 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
526 0 : return mDelegate->ReadEntry(index, entry, &fabric);
527 : }
528 :
529 : /**
530 : * Reads an entry from the access control list.
531 : *
532 : * @param [in] index Entry index of entry to read. May be relative to `fabricIndex`.
533 : * @param [out] entry Entry into which to copy.
534 : * @param [in] fabricIndex Fabric to which entry `index` is relative, if not null.
535 : */
536 : CHIP_ERROR ReadEntry(size_t index, Entry & entry, const FabricIndex * fabricIndex = nullptr) const
537 : {
538 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
539 : return mDelegate->ReadEntry(index, entry, fabricIndex);
540 : }
541 :
542 : /**
543 : * Updates an entry in the access control list.
544 : *
545 : * @param [in] subjectDescriptor Optional subject descriptor for this operation.
546 : * @param [in] fabric Index of fabric in which to update entry.
547 : * @param [in] index Index of entry to update (relative to fabric).
548 : * @param [in] entry Entry from which updated entry is copied.
549 : */
550 : CHIP_ERROR UpdateEntry(const SubjectDescriptor * subjectDescriptor, FabricIndex fabric, size_t index, const Entry & entry);
551 :
552 : /**
553 : * Updates an entry in the access control list.
554 : *
555 : * @param [in] index Entry index of entry to update, if not null. May be relative to `fabricIndex`.
556 : * @param [in] entry Entry from which to copy.
557 : * @param [in] fabricIndex Fabric to which entry `index` is relative, if not null.
558 : */
559 : CHIP_ERROR UpdateEntry(size_t index, const Entry & entry, const FabricIndex * fabricIndex = nullptr)
560 : {
561 : VerifyOrReturnError(entry.IsValid(), CHIP_ERROR_INVALID_ARGUMENT);
562 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
563 : return mDelegate->UpdateEntry(index, entry, fabricIndex);
564 : }
565 :
566 : /**
567 : * Deletes an entry in the access control list.
568 : *
569 : * @param [in] subjectDescriptor Optional subject descriptor for this operation.
570 : * @param [in] fabric Index of fabric in which to delete entry.
571 : * @param [in] index Index of entry to delete (relative to fabric).
572 : */
573 : CHIP_ERROR DeleteEntry(const SubjectDescriptor * subjectDescriptor, FabricIndex fabric, size_t index);
574 :
575 : /**
576 : * Deletes an entry from the access control list.
577 : *
578 : * @param [in] index Entry index of entry to delete. May be relative to `fabricIndex`.
579 : * @param [in] fabricIndex Fabric to which entry `index` is relative, if not null.
580 : */
581 : CHIP_ERROR DeleteEntry(size_t index, const FabricIndex * fabricIndex = nullptr)
582 : {
583 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
584 : return mDelegate->DeleteEntry(index, fabricIndex);
585 : }
586 :
587 : /**
588 : * @brief Remove all ACL entries for the given fabricIndex
589 : *
590 : * @param[in] fabricIndex fabric index for which to remove all entries
591 : */
592 0 : CHIP_ERROR DeleteAllEntriesForFabric(FabricIndex fabricIndex)
593 : {
594 0 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
595 :
596 0 : CHIP_ERROR stickyError = CHIP_NO_ERROR;
597 :
598 : // Remove access control entries in reverse order (it could be any order, but reverse order
599 : // will cause less churn in persistent storage).
600 0 : size_t aclCount = 0;
601 0 : if (GetEntryCount(fabricIndex, aclCount) == CHIP_NO_ERROR)
602 : {
603 0 : while (aclCount)
604 : {
605 0 : CHIP_ERROR err = DeleteEntry(nullptr, fabricIndex, --aclCount);
606 0 : stickyError = (stickyError == CHIP_NO_ERROR) ? err : stickyError;
607 : }
608 : }
609 :
610 0 : return stickyError;
611 : }
612 :
613 : /**
614 : * Iterates over entries in the access control list.
615 : *
616 : * @param [in] fabric Fabric over which to iterate entries.
617 : * @param [out] iterator Iterator controlling the iteration.
618 : */
619 : CHIP_ERROR Entries(FabricIndex fabric, EntryIterator & iterator) const
620 : {
621 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
622 : return mDelegate->Entries(iterator, &fabric);
623 : }
624 :
625 : /**
626 : * Iterates over entries in the access control list.
627 : *
628 : * @param [out] iterator Iterator controlling the iteration.
629 : * @param [in] fabricIndex Iteration is confined to fabric, if not null.
630 : */
631 0 : CHIP_ERROR Entries(EntryIterator & iterator, const FabricIndex * fabricIndex = nullptr) const
632 : {
633 0 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
634 0 : return mDelegate->Entries(iterator, fabricIndex);
635 : }
636 :
637 : // Adds a listener to the end of the listener list, if not already in the list.
638 : void AddEntryListener(EntryListener & listener);
639 :
640 : // Removes a listener from the listener list, if in the list.
641 : void RemoveEntryListener(EntryListener & listener);
642 :
643 : #if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
644 : // Set an optional AcceessRestriction object for MNGD feature.
645 : void SetAccessRestrictionProvider(AccessRestrictionProvider * accessRestrictionProvider)
646 : {
647 : mAccessRestrictionProvider = accessRestrictionProvider;
648 : }
649 :
650 : AccessRestrictionProvider * GetAccessRestrictionProvider() { return mAccessRestrictionProvider; }
651 : #endif
652 :
653 : /**
654 : * Check whether or not Access Restriction List is supported.
655 : *
656 : * @retval true if Access Restriction List is supported.
657 : */
658 : bool IsAccessRestrictionListSupported() const;
659 :
660 : /**
661 : * Check whether access (by a subject descriptor, to a request path,
662 : * requiring a privilege) should be allowed or denied.
663 : *
664 : * If an AccessRestrictionProvider object is set, it will be checked for additional access restrictions.
665 : *
666 : * @retval #CHIP_ERROR_ACCESS_DENIED if denied.
667 : * @retval other errors should also be treated as denied.
668 : * @retval #CHIP_NO_ERROR if allowed.
669 : */
670 : CHIP_ERROR Check(const SubjectDescriptor & subjectDescriptor, const RequestPath & requestPath, Privilege requestPrivilege);
671 :
672 : #if CHIP_ACCESS_CONTROL_DUMP_ENABLED
673 : CHIP_ERROR Dump(const Entry & entry);
674 : #endif
675 :
676 : private:
677 307 : bool IsInitialized() const { return (mDelegate != nullptr); }
678 :
679 : void NotifyEntryChanged(const SubjectDescriptor * subjectDescriptor, FabricIndex fabric, size_t index, const Entry * entry,
680 : EntryListener::ChangeType changeType);
681 :
682 : /**
683 : * Check ACL for whether access (by a subject descriptor, to a request path,
684 : * requiring a privilege) should be allowed or denied.
685 : */
686 : CHIP_ERROR CheckACL(const SubjectDescriptor & subjectDescriptor, const RequestPath & requestPath, Privilege requestPrivilege);
687 :
688 : /**
689 : * Check CommissioningARL or ARL (as appropriate) for whether access (by a
690 : * subject descriptor, to a request path, requiring a privilege) should
691 : * be allowed or denied.
692 : */
693 : CHIP_ERROR CheckARL(const SubjectDescriptor & subjectDescriptor, const RequestPath & requestPath, Privilege requestPrivilege);
694 :
695 : private:
696 : Delegate * mDelegate = nullptr;
697 :
698 : DeviceTypeResolver * mDeviceTypeResolver = nullptr;
699 :
700 : EntryListener * mEntryListener = nullptr;
701 :
702 : #if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
703 : AccessRestrictionProvider * mAccessRestrictionProvider;
704 : #endif
705 : };
706 :
707 : /**
708 : * Get the global instance set by SetAccessControl, or the default.
709 : *
710 : * Calls to this function must be synchronized externally.
711 : */
712 : AccessControl & GetAccessControl();
713 :
714 : /**
715 : * Set the global instance returned by GetAccessControl.
716 : *
717 : * Calls to this function must be synchronized externally.
718 : */
719 : void SetAccessControl(AccessControl & accessControl);
720 :
721 : /**
722 : * Reset the global instance to the default.
723 : *
724 : * Calls to this function must be synchronized externally.
725 : */
726 : void ResetAccessControlToDefault();
727 :
728 : } // namespace Access
729 : } // namespace chip
|