Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2022 Project CHIP Authors
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : #pragma once
19 :
20 : #include <access/AccessControl.h>
21 : #include <credentials/FabricTable.h>
22 : #include <lib/core/CHIPPersistentStorageDelegate.h>
23 :
24 : #include <app-common/zap-generated/cluster-objects.h>
25 :
26 : namespace chip {
27 : namespace app {
28 :
29 : /**
30 : * Storage specifically for access control entries, which correspond to the
31 : * ACL attribute of the access control cluster.
32 : *
33 : * An object of this class should be initialized directly after the access
34 : * control module is initialized, as it will populate entries in the system
35 : * module from storage, and also install a listener in the system module to
36 : * keep storage up to date as entries change.
37 : *
38 : * This class also provides facilities for converting between access control
39 : * entries (as used by the system module) and access control entries (as used
40 : * by the generated cluster code).
41 : */
42 : class AclStorage
43 : {
44 : public:
45 : /**
46 : * Used for decoding access control entries.
47 : *
48 : * Typically used temporarily on the stack to decode:
49 : * - source: TLV
50 : * - staging: generated cluster level code
51 : * - destination: system level access control entry
52 : */
53 : class DecodableEntry
54 : {
55 : using Entry = Access::AccessControl::Entry;
56 : using StagingEntry = Clusters::AccessControl::Structs::AccessControlEntryStruct::DecodableType;
57 :
58 : public:
59 0 : DecodableEntry() = default;
60 :
61 : /**
62 : * Reader decodes into a staging entry, which is then unstaged
63 : * into a member entry.
64 : */
65 : CHIP_ERROR Decode(TLV::TLVReader & reader);
66 :
67 0 : Entry & GetEntry() { return mEntry; }
68 :
69 : const Entry & GetEntry() const { return mEntry; }
70 :
71 : public:
72 : static constexpr bool kIsFabricScoped = true;
73 :
74 : void SetFabricIndex(FabricIndex fabricIndex) { mEntry.SetFabricIndex(fabricIndex); }
75 :
76 : private:
77 : CHIP_ERROR Unstage();
78 :
79 : private:
80 : Entry mEntry;
81 :
82 : StagingEntry mStagingEntry;
83 : };
84 :
85 : /**
86 : * Used for encoding access control entries.
87 : *
88 : * Typically used temporarily on the stack to encode:
89 : * - source: system level access control entry
90 : * - staging: generated cluster level code
91 : * - destination: TLV
92 : */
93 : class EncodableEntry
94 : {
95 : using Entry = Access::AccessControl::Entry;
96 : using StagingEntry = Clusters::AccessControl::Structs::AccessControlEntryStruct::Type;
97 : using StagingTarget = Clusters::AccessControl::Structs::AccessControlTargetStruct::Type;
98 :
99 : public:
100 0 : EncodableEntry(const Entry & entry) : mEntry(entry) {}
101 :
102 : /**
103 : * Constructor-provided entry is staged into a staging entry,
104 : * which is then encoded into a writer.
105 : */
106 : CHIP_ERROR EncodeForRead(TLV::TLVWriter & writer, TLV::Tag tag, FabricIndex fabric) const;
107 :
108 : /**
109 : * Constructor-provided entry is staged into a staging entry,
110 : * which is then encoded into a writer.
111 : */
112 : CHIP_ERROR EncodeForWrite(TLV::TLVWriter & writer, TLV::Tag tag) const;
113 :
114 : /**
115 : * Constructor-provided entry is staged into a staging entry.
116 : */
117 : CHIP_ERROR Stage() const;
118 :
119 : StagingEntry & GetStagingEntry() { return mStagingEntry; }
120 :
121 : const StagingEntry & GetStagingEntry() const { return mStagingEntry; }
122 :
123 : public:
124 : static constexpr bool kIsFabricScoped = true;
125 :
126 : FabricIndex GetFabricIndex() const
127 : {
128 : FabricIndex fabricIndex = kUndefinedFabricIndex;
129 : mEntry.GetFabricIndex(fabricIndex);
130 : return fabricIndex;
131 : }
132 :
133 : private:
134 : const Entry & mEntry;
135 :
136 : mutable StagingEntry mStagingEntry;
137 : mutable NodeId mStagingSubjects[CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_SUBJECTS_PER_ENTRY];
138 : mutable StagingTarget mStagingTargets[CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_TARGETS_PER_ENTRY];
139 : };
140 :
141 1 : virtual ~AclStorage() = default;
142 :
143 : /**
144 : * Initialize should be called after chip::Access::AccessControl is initialized.
145 : *
146 : * Implementations should take this opportunity to populate AccessControl with ACL entries
147 : * loaded from persistent storage. A half-open range of fabrics [first, last) is provided
148 : * so this can be done on a per-fabric basis.
149 : *
150 : * Implementations should also install an entry change listener on AccessControl to maintain
151 : * ACL entries in persistent storage as they are changed.
152 : */
153 : virtual CHIP_ERROR Init(PersistentStorageDelegate & persistentStorage, ConstFabricIterator first, ConstFabricIterator last) = 0;
154 : };
155 :
156 : } // namespace app
157 : } // namespace chip
|