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 1 : 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 63 : 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 : private:
237 : static Global<Delegate> mDefaultDelegate;
238 : Delegate * mDelegate = &mDefaultDelegate.get();
239 : };
240 :
241 : /**
242 : * Handle to an entry iterator in the access control list.
243 : *
244 : * Must be initialized (`AccessControl::Entries`) before first use.
245 : */
246 : class EntryIterator
247 : {
248 : public:
249 : class Delegate
250 : {
251 : public:
252 2 : Delegate() = default;
253 :
254 : Delegate(const Delegate &) = delete;
255 : Delegate & operator=(const Delegate &) = delete;
256 :
257 65 : virtual ~Delegate() = default;
258 :
259 53 : virtual void Release() {}
260 :
261 0 : virtual CHIP_ERROR Next(Entry & entry) { return CHIP_ERROR_SENTINEL; }
262 : };
263 :
264 0 : EntryIterator() = default;
265 :
266 : EntryIterator(const EntryIterator &) = delete;
267 : EntryIterator & operator=(const EntryIterator &) = delete;
268 :
269 0 : ~EntryIterator() { mDelegate->Release(); }
270 :
271 0 : CHIP_ERROR Next(Entry & entry) { return mDelegate->Next(entry); }
272 :
273 : const Delegate & GetDelegate() const { return *mDelegate; }
274 :
275 56 : Delegate & GetDelegate() { return *mDelegate; }
276 :
277 56 : void SetDelegate(Delegate & delegate)
278 : {
279 56 : mDelegate->Release();
280 56 : mDelegate = &delegate;
281 56 : }
282 :
283 : void ResetDelegate()
284 : {
285 : mDelegate->Release();
286 : mDelegate = &mDefaultDelegate.get();
287 : }
288 :
289 : private:
290 : static Global<Delegate> mDefaultDelegate;
291 : Delegate * mDelegate = &mDefaultDelegate.get();
292 : };
293 :
294 : /**
295 : * Used by access control to notify of changes in access control list.
296 : */
297 : class EntryListener
298 : {
299 : public:
300 : enum class ChangeType
301 : {
302 : kAdded = 1,
303 : kRemoved = 2,
304 : kUpdated = 3
305 : };
306 :
307 1 : virtual ~EntryListener() = default;
308 :
309 : /**
310 : * Notifies of a change in the access control list.
311 : *
312 : * The fabric is indicated by its own parameter. If available, a subject descriptor will
313 : * have more detail (and its fabric index will match). A best effort is made to provide
314 : * the latest value of the changed entry.
315 : *
316 : * @param [in] subjectDescriptor Optional (if available) subject descriptor for this operation.
317 : * @param [in] fabric Index of fabric in which entry has changed.
318 : * @param [in] index Index of entry to which has changed (relative to fabric).
319 : * @param [in] entry Optional (best effort) latest value of entry which has changed.
320 : * @param [in] changeType Type of change.
321 : */
322 : virtual void OnEntryChanged(const SubjectDescriptor * subjectDescriptor, FabricIndex fabric, size_t index,
323 : const Entry * entry, ChangeType changeType) = 0;
324 :
325 : private:
326 : EntryListener * mNext = nullptr;
327 :
328 : friend class AccessControl;
329 : };
330 :
331 : class Delegate
332 : {
333 : public:
334 : Delegate() = default;
335 :
336 : Delegate(const Delegate &) = delete;
337 : Delegate & operator=(const Delegate &) = delete;
338 :
339 25 : virtual ~Delegate() = default;
340 :
341 0 : virtual void Release() {}
342 :
343 0 : virtual CHIP_ERROR Init() { return CHIP_NO_ERROR; }
344 0 : virtual void Finish() {}
345 :
346 : // Capabilities
347 0 : virtual CHIP_ERROR GetMaxEntriesPerFabric(size_t & value) const
348 : {
349 0 : value = 0;
350 0 : return CHIP_NO_ERROR;
351 : }
352 :
353 0 : virtual CHIP_ERROR GetMaxSubjectsPerEntry(size_t & value) const
354 : {
355 0 : value = 0;
356 0 : return CHIP_NO_ERROR;
357 : }
358 :
359 0 : virtual CHIP_ERROR GetMaxTargetsPerEntry(size_t & value) const
360 : {
361 0 : value = 0;
362 0 : return CHIP_NO_ERROR;
363 : }
364 :
365 0 : virtual CHIP_ERROR GetMaxEntryCount(size_t & value) const
366 : {
367 0 : value = 0;
368 0 : return CHIP_NO_ERROR;
369 : }
370 :
371 : // Actualities
372 0 : virtual CHIP_ERROR GetEntryCount(FabricIndex fabric, size_t & value) const
373 : {
374 0 : value = 0;
375 0 : return CHIP_NO_ERROR;
376 : }
377 :
378 0 : virtual CHIP_ERROR GetEntryCount(size_t & value) const
379 : {
380 0 : value = 0;
381 0 : return CHIP_NO_ERROR;
382 : }
383 :
384 : // Preparation
385 0 : virtual CHIP_ERROR PrepareEntry(Entry & entry) { return CHIP_NO_ERROR; }
386 :
387 : // CRUD
388 0 : virtual CHIP_ERROR CreateEntry(size_t * index, const Entry & entry, FabricIndex * fabricIndex) { return CHIP_NO_ERROR; }
389 0 : virtual CHIP_ERROR ReadEntry(size_t index, Entry & entry, const FabricIndex * fabricIndex) const { return CHIP_NO_ERROR; }
390 0 : virtual CHIP_ERROR UpdateEntry(size_t index, const Entry & entry, const FabricIndex * fabricIndex) { return CHIP_NO_ERROR; }
391 0 : virtual CHIP_ERROR DeleteEntry(size_t index, const FabricIndex * fabricIndex) { return CHIP_NO_ERROR; }
392 :
393 : // Iteration
394 0 : virtual CHIP_ERROR Entries(EntryIterator & iterator, const FabricIndex * fabricIndex) const { return CHIP_NO_ERROR; }
395 :
396 : // Check
397 : // Return CHIP_NO_ERROR if allowed, CHIP_ERROR_ACCESS_DENIED if denied,
398 : // CHIP_ERROR_NOT_IMPLEMENTED to use the default check algorithm (against entries),
399 : // or any other CHIP_ERROR if another error occurred.
400 0 : virtual CHIP_ERROR Check(const SubjectDescriptor & subjectDescriptor, const RequestPath & requestPath,
401 : Privilege requestPrivilege)
402 : {
403 0 : return CHIP_ERROR_ACCESS_DENIED;
404 : }
405 : };
406 :
407 1 : AccessControl() = default;
408 :
409 : AccessControl(const AccessControl &) = delete;
410 : AccessControl & operator=(const AccessControl &) = delete;
411 :
412 38 : ~AccessControl()
413 : {
414 : // Never-initialized AccessControl instances will not have the delegate set.
415 38 : if (IsInitialized())
416 : {
417 0 : mDelegate->Release();
418 : }
419 38 : }
420 :
421 : /**
422 : * Initialize the access control module. Must be called before first use.
423 : *
424 : * @return CHIP_NO_ERROR on success, CHIP_ERROR_INCORRECT_STATE if called more than once,
425 : * CHIP_ERROR_INVALID_ARGUMENT if delegate is null, or other fatal error.
426 : */
427 : CHIP_ERROR Init(AccessControl::Delegate * delegate, DeviceTypeResolver & deviceTypeResolver);
428 :
429 : /**
430 : * Deinitialize the access control module. Must be called when finished.
431 : */
432 : void Finish();
433 :
434 : // Capabilities
435 : CHIP_ERROR GetMaxEntriesPerFabric(size_t & value) const
436 : {
437 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
438 : return mDelegate->GetMaxEntriesPerFabric(value);
439 : }
440 :
441 : CHIP_ERROR GetMaxSubjectsPerEntry(size_t & value) const
442 : {
443 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
444 : return mDelegate->GetMaxSubjectsPerEntry(value);
445 : }
446 :
447 : CHIP_ERROR GetMaxTargetsPerEntry(size_t & value) const
448 : {
449 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
450 : return mDelegate->GetMaxTargetsPerEntry(value);
451 : }
452 :
453 : CHIP_ERROR GetMaxEntryCount(size_t & value) const
454 : {
455 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
456 : return mDelegate->GetMaxEntryCount(value);
457 : }
458 :
459 : // Actualities
460 0 : CHIP_ERROR GetEntryCount(FabricIndex fabric, size_t & value) const
461 : {
462 0 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
463 0 : return mDelegate->GetEntryCount(fabric, value);
464 : }
465 :
466 : CHIP_ERROR GetEntryCount(size_t & value) const
467 : {
468 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
469 : return mDelegate->GetEntryCount(value);
470 : }
471 :
472 : /**
473 : * Prepares an entry.
474 : *
475 : * An entry must be prepared or read (`ReadEntry`) before first use.
476 : *
477 : * @param [in] entry Entry to prepare.
478 : */
479 0 : CHIP_ERROR PrepareEntry(Entry & entry)
480 : {
481 0 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
482 0 : return mDelegate->PrepareEntry(entry);
483 : }
484 :
485 : /**
486 : * Creates an entry in the access control list.
487 : *
488 : * @param [in] subjectDescriptor Optional subject descriptor for this operation.
489 : * @param [in] fabric Index of fabric in which to create entry.
490 : * @param [out] index (If not nullptr) index of created entry (relative to fabric).
491 : * @param [in] entry Entry from which created entry is copied.
492 : */
493 : CHIP_ERROR CreateEntry(const SubjectDescriptor * subjectDescriptor, FabricIndex fabric, size_t * index, const Entry & entry);
494 :
495 : /**
496 : * Creates an entry in the access control list.
497 : *
498 : * @param [out] index Entry index of created entry, if not null. May be relative to `fabricIndex`.
499 : * @param [in] entry Entry from which to copy.
500 : * @param [out] fabricIndex Fabric index of created entry, if not null, in which case entry `index` will be relative to fabric.
501 : */
502 : CHIP_ERROR CreateEntry(size_t * index, const Entry & entry, FabricIndex * fabricIndex = nullptr)
503 : {
504 : VerifyOrReturnError(IsValid(entry), CHIP_ERROR_INVALID_ARGUMENT);
505 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
506 : return mDelegate->CreateEntry(index, entry, fabricIndex);
507 : }
508 :
509 : /**
510 : * Reads an entry in the access control list.
511 : *
512 : * @param [in] fabric Index of fabric in which to read entry.
513 : * @param [in] index Index of entry to read (relative to fabric).
514 : * @param [in] entry Entry into which read entry is copied.
515 : */
516 0 : CHIP_ERROR ReadEntry(FabricIndex fabric, size_t index, Entry & entry) const
517 : {
518 0 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
519 0 : return mDelegate->ReadEntry(index, entry, &fabric);
520 : }
521 :
522 : /**
523 : * Reads an entry from the access control list.
524 : *
525 : * @param [in] index Entry index of entry to read. May be relative to `fabricIndex`.
526 : * @param [out] entry Entry into which to copy.
527 : * @param [in] fabricIndex Fabric to which entry `index` is relative, if not null.
528 : */
529 : CHIP_ERROR ReadEntry(size_t index, Entry & entry, const FabricIndex * fabricIndex = nullptr) const
530 : {
531 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
532 : return mDelegate->ReadEntry(index, entry, fabricIndex);
533 : }
534 :
535 : /**
536 : * Updates an entry in the access control list.
537 : *
538 : * @param [in] subjectDescriptor Optional subject descriptor for this operation.
539 : * @param [in] fabric Index of fabric in which to update entry.
540 : * @param [in] index Index of entry to update (relative to fabric).
541 : * @param [in] entry Entry from which updated entry is copied.
542 : */
543 : CHIP_ERROR UpdateEntry(const SubjectDescriptor * subjectDescriptor, FabricIndex fabric, size_t index, const Entry & entry);
544 :
545 : /**
546 : * Updates an entry in the access control list.
547 : *
548 : * @param [in] index Entry index of entry to update, if not null. May be relative to `fabricIndex`.
549 : * @param [in] entry Entry from which to copy.
550 : * @param [in] fabricIndex Fabric to which entry `index` is relative, if not null.
551 : */
552 : CHIP_ERROR UpdateEntry(size_t index, const Entry & entry, const FabricIndex * fabricIndex = nullptr)
553 : {
554 : VerifyOrReturnError(IsValid(entry), CHIP_ERROR_INVALID_ARGUMENT);
555 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
556 : return mDelegate->UpdateEntry(index, entry, fabricIndex);
557 : }
558 :
559 : /**
560 : * Deletes an entry in the access control list.
561 : *
562 : * @param [in] subjectDescriptor Optional subject descriptor for this operation.
563 : * @param [in] fabric Index of fabric in which to delete entry.
564 : * @param [in] index Index of entry to delete (relative to fabric).
565 : */
566 : CHIP_ERROR DeleteEntry(const SubjectDescriptor * subjectDescriptor, FabricIndex fabric, size_t index);
567 :
568 : /**
569 : * Deletes an entry from the access control list.
570 : *
571 : * @param [in] index Entry index of entry to delete. May be relative to `fabricIndex`.
572 : * @param [in] fabricIndex Fabric to which entry `index` is relative, if not null.
573 : */
574 : CHIP_ERROR DeleteEntry(size_t index, const FabricIndex * fabricIndex = nullptr)
575 : {
576 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
577 : return mDelegate->DeleteEntry(index, fabricIndex);
578 : }
579 :
580 : /**
581 : * @brief Remove all ACL entries for the given fabricIndex
582 : *
583 : * @param[in] fabricIndex fabric index for which to remove all entries
584 : */
585 0 : CHIP_ERROR DeleteAllEntriesForFabric(FabricIndex fabricIndex)
586 : {
587 0 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
588 :
589 0 : CHIP_ERROR stickyError = CHIP_NO_ERROR;
590 :
591 : // Remove access control entries in reverse order (it could be any order, but reverse order
592 : // will cause less churn in persistent storage).
593 0 : size_t aclCount = 0;
594 0 : if (GetEntryCount(fabricIndex, aclCount) == CHIP_NO_ERROR)
595 : {
596 0 : while (aclCount)
597 : {
598 0 : CHIP_ERROR err = DeleteEntry(nullptr, fabricIndex, --aclCount);
599 0 : stickyError = (stickyError == CHIP_NO_ERROR) ? err : stickyError;
600 : }
601 : }
602 :
603 0 : return stickyError;
604 : }
605 :
606 : /**
607 : * Iterates over entries in the access control list.
608 : *
609 : * @param [in] fabric Fabric over which to iterate entries.
610 : * @param [out] iterator Iterator controlling the iteration.
611 : */
612 : CHIP_ERROR Entries(FabricIndex fabric, EntryIterator & iterator) const
613 : {
614 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
615 : return mDelegate->Entries(iterator, &fabric);
616 : }
617 :
618 : /**
619 : * Iterates over entries in the access control list.
620 : *
621 : * @param [out] iterator Iterator controlling the iteration.
622 : * @param [in] fabricIndex Iteration is confined to fabric, if not null.
623 : */
624 0 : CHIP_ERROR Entries(EntryIterator & iterator, const FabricIndex * fabricIndex = nullptr) const
625 : {
626 0 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
627 0 : return mDelegate->Entries(iterator, fabricIndex);
628 : }
629 :
630 : // Adds a listener to the end of the listener list, if not already in the list.
631 : void AddEntryListener(EntryListener & listener);
632 :
633 : // Removes a listener from the listener list, if in the list.
634 : void RemoveEntryListener(EntryListener & listener);
635 :
636 : #if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
637 : // Set an optional AcceessRestriction object for MNGD feature.
638 : void SetAccessRestrictionProvider(AccessRestrictionProvider * accessRestrictionProvider)
639 : {
640 : mAccessRestrictionProvider = accessRestrictionProvider;
641 : }
642 :
643 : AccessRestrictionProvider * GetAccessRestrictionProvider() { return mAccessRestrictionProvider; }
644 : #endif
645 :
646 : /**
647 : * Check whether or not Access Restriction List is supported.
648 : *
649 : * @retval true if Access Restriction List is supported.
650 : */
651 : bool IsAccessRestrictionListSupported() const;
652 :
653 : /**
654 : * Check whether access (by a subject descriptor, to a request path,
655 : * requiring a privilege) should be allowed or denied.
656 : *
657 : * If an AccessRestrictionProvider object is set, it will be checked for additional access restrictions.
658 : *
659 : * @retval #CHIP_ERROR_ACCESS_DENIED if denied.
660 : * @retval other errors should also be treated as denied.
661 : * @retval #CHIP_NO_ERROR if allowed.
662 : */
663 : CHIP_ERROR Check(const SubjectDescriptor & subjectDescriptor, const RequestPath & requestPath, Privilege requestPrivilege);
664 :
665 : #if CHIP_ACCESS_CONTROL_DUMP_ENABLED
666 : CHIP_ERROR Dump(const Entry & entry);
667 : #endif
668 :
669 : private:
670 457 : bool IsInitialized() const { return (mDelegate != nullptr); }
671 :
672 : bool IsValid(const Entry & entry);
673 :
674 : void NotifyEntryChanged(const SubjectDescriptor * subjectDescriptor, FabricIndex fabric, size_t index, const Entry * entry,
675 : EntryListener::ChangeType changeType);
676 :
677 : /**
678 : * Check ACL for whether access (by a subject descriptor, to a request path,
679 : * requiring a privilege) should be allowed or denied.
680 : */
681 : CHIP_ERROR CheckACL(const SubjectDescriptor & subjectDescriptor, const RequestPath & requestPath, Privilege requestPrivilege);
682 :
683 : /**
684 : * Check CommissioningARL or ARL (as appropriate) for whether access (by a
685 : * subject descriptor, to a request path, requiring a privilege) should
686 : * be allowed or denied.
687 : */
688 : CHIP_ERROR CheckARL(const SubjectDescriptor & subjectDescriptor, const RequestPath & requestPath, Privilege requestPrivilege);
689 :
690 : private:
691 : Delegate * mDelegate = nullptr;
692 :
693 : DeviceTypeResolver * mDeviceTypeResolver = nullptr;
694 :
695 : EntryListener * mEntryListener = nullptr;
696 :
697 : #if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
698 : AccessRestrictionProvider * mAccessRestrictionProvider;
699 : #endif
700 : };
701 :
702 : /**
703 : * Get the global instance set by SetAccessControl, or the default.
704 : *
705 : * Calls to this function must be synchronized externally.
706 : */
707 : AccessControl & GetAccessControl();
708 :
709 : /**
710 : * Set the global instance returned by GetAccessControl.
711 : *
712 : * Calls to this function must be synchronized externally.
713 : */
714 : void SetAccessControl(AccessControl & accessControl);
715 :
716 : /**
717 : * Reset the global instance to the default.
718 : *
719 : * Calls to this function must be synchronized externally.
720 : */
721 : void ResetAccessControlToDefault();
722 :
723 : } // namespace Access
724 : } // namespace chip
|