]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2000-2007,2011 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
24 | ||
25 | // | |
26 | // cssmaclpod - enhanced PodWrappers for ACL-related CSSM data structures | |
27 | // | |
28 | #ifndef _CSSMACLPOD | |
29 | #define _CSSMACLPOD | |
30 | ||
31 | #include <security_utilities/utilities.h> | |
32 | #include <security_cdsa_utilities/cssmlist.h> | |
33 | #include <security_cdsa_utilities/cssmalloc.h> | |
34 | ||
35 | namespace Security { | |
36 | ||
37 | // a nicer name for an authorization tag | |
38 | typedef CSSM_ACL_AUTHORIZATION_TAG AclAuthorization; | |
39 | ||
40 | ||
41 | // | |
42 | // An STL set of authorization tags, with some convenience features | |
43 | // | |
44 | class AclAuthorizationSet : public std::set<AclAuthorization> { | |
45 | public: | |
46 | AclAuthorizationSet() { } | |
47 | AclAuthorizationSet(AclAuthorization auth) { insert(auth); } | |
48 | AclAuthorizationSet(AclAuthorization *authBegin, AclAuthorization *authEnd) | |
49 | : set<AclAuthorization>(authBegin, authEnd) { } | |
50 | AclAuthorizationSet(AclAuthorization a1, AclAuthorization a2, ...); // list of auths, end with zero | |
51 | }; | |
52 | ||
53 | ||
54 | // | |
55 | // Enhanced POD Wrappers for the public ACL-related CSSM structures | |
56 | // | |
57 | class AuthorizationGroup : public PodWrapper<AuthorizationGroup, CSSM_AUTHORIZATIONGROUP> { | |
58 | public: | |
59 | AuthorizationGroup() { NumberOfAuthTags = 0; } | |
60 | AuthorizationGroup(const AclAuthorizationSet &, Allocator &alloc); | |
61 | AuthorizationGroup(AclAuthorization tag, Allocator &alloc); | |
62 | void destroy(Allocator &alloc); | |
63 | ||
64 | bool empty() const { return NumberOfAuthTags == 0; } | |
65 | unsigned int size() const { return NumberOfAuthTags; } | |
66 | unsigned int count() const { return NumberOfAuthTags; } | |
67 | CSSM_ACL_AUTHORIZATION_TAG operator [] (unsigned ix) const | |
68 | { assert(ix < size()); return AuthTags[ix]; } | |
69 | ||
70 | bool contains(CSSM_ACL_AUTHORIZATION_TAG tag) const; | |
71 | operator AclAuthorizationSet () const; | |
72 | }; | |
73 | ||
74 | class AclOwnerPrototype; | |
75 | ||
76 | class AclEntryPrototype : public PodWrapper<AclEntryPrototype, CSSM_ACL_ENTRY_PROTOTYPE> { | |
77 | public: | |
78 | AclEntryPrototype() { clearPod(); } | |
79 | explicit AclEntryPrototype(const AclOwnerPrototype &proto); | |
80 | AclEntryPrototype(const CSSM_LIST &subj, bool delegate = false) | |
81 | { clearPod(); TypedSubject = subj; Delegate = delegate; } | |
82 | ||
83 | TypedList &subject() { return TypedList::overlay(TypedSubject); } | |
84 | const TypedList &subject() const { return TypedList::overlay(TypedSubject); } | |
85 | ||
86 | bool delegate() const { return Delegate; } | |
87 | void delegate(bool d) { Delegate = d; } | |
88 | ||
89 | char *tag() { return EntryTag[0] ? EntryTag : NULL; } | |
90 | void tag(const char *tagString); | |
91 | void tag(const std::string &tagString); | |
92 | const char *tag() const { return EntryTag[0] ? EntryTag : NULL; } | |
93 | std::string s_tag() const { return EntryTag; } | |
94 | ||
95 | AuthorizationGroup &authorization() { return AuthorizationGroup::overlay(Authorization); } | |
96 | const AuthorizationGroup &authorization() const | |
97 | { return AuthorizationGroup::overlay(Authorization); } | |
98 | }; | |
99 | ||
100 | class AclOwnerPrototype : public PodWrapper<AclOwnerPrototype, CSSM_ACL_OWNER_PROTOTYPE> { | |
101 | public: | |
102 | AclOwnerPrototype() { clearPod(); } | |
103 | explicit AclOwnerPrototype(const AclEntryPrototype &proto) | |
104 | { TypedSubject = proto.subject(); delegate(proto.delegate()); } | |
105 | AclOwnerPrototype(const CSSM_LIST &subj, bool del = false) | |
106 | { TypedSubject = subj; delegate(del); } | |
107 | ||
108 | TypedList &subject() { return TypedList::overlay(TypedSubject); } | |
109 | const TypedList &subject() const { return TypedList::overlay(TypedSubject); } | |
110 | bool delegate() const { return Delegate; } | |
111 | void delegate(bool d) { Delegate = d; } | |
112 | }; | |
113 | ||
114 | class AclEntryInfo : public PodWrapper<AclEntryInfo, CSSM_ACL_ENTRY_INFO> { | |
115 | public: | |
116 | AclEntryInfo() { clearPod(); } | |
117 | AclEntryInfo(const AclEntryPrototype &prot, CSSM_ACL_HANDLE h = 0) | |
118 | { proto() = prot; handle() = h; } | |
119 | ||
120 | AclEntryPrototype &proto() { return AclEntryPrototype::overlay(EntryPublicInfo); } | |
121 | const AclEntryPrototype &proto() const | |
122 | { return AclEntryPrototype::overlay(EntryPublicInfo); } | |
123 | ||
124 | operator AclEntryPrototype &() { return proto(); } | |
125 | operator const AclEntryPrototype &() const { return proto(); } | |
126 | ||
127 | CSSM_ACL_HANDLE &handle() { return EntryHandle; } | |
128 | const CSSM_ACL_HANDLE &handle() const { return EntryHandle; } | |
129 | void handle(CSSM_ACL_HANDLE h) { EntryHandle = h; } | |
130 | }; | |
131 | ||
132 | class AclEntryInput : public PodWrapper<AclEntryInput, CSSM_ACL_ENTRY_INPUT> { | |
133 | public: | |
134 | AclEntryInput() { clearPod(); } | |
135 | AclEntryInput(const CSSM_ACL_ENTRY_PROTOTYPE &prot) | |
136 | { Prototype = prot; Callback = NULL; CallerContext = NULL; } | |
137 | ||
138 | AclEntryInput &operator = (const CSSM_ACL_ENTRY_PROTOTYPE &prot) | |
139 | { Prototype = prot; Callback = NULL; CallerContext = NULL; return *this; } | |
140 | ||
141 | AclEntryPrototype &proto() { return AclEntryPrototype::overlay(Prototype); } | |
142 | const AclEntryPrototype &proto() const { return AclEntryPrototype::overlay(Prototype); } | |
143 | //@@@ not supporting callback features (yet) | |
144 | }; | |
145 | ||
146 | class AclEdit : public PodWrapper<AclEdit, CSSM_ACL_EDIT> { | |
147 | public: | |
148 | AclEdit(CSSM_ACL_EDIT_MODE m, CSSM_ACL_HANDLE h, const AclEntryInput *data) | |
149 | { EditMode = m; OldEntryHandle = h; NewEntry = data; } | |
150 | AclEdit(const AclEntryInput &add) | |
151 | { EditMode = CSSM_ACL_EDIT_MODE_ADD; OldEntryHandle = CSSM_INVALID_HANDLE; NewEntry = &add; } | |
152 | AclEdit(CSSM_ACL_HANDLE h, const AclEntryInput &modify) | |
153 | { EditMode = CSSM_ACL_EDIT_MODE_REPLACE; OldEntryHandle = h; NewEntry = &modify; } | |
154 | AclEdit(CSSM_ACL_HANDLE h) | |
155 | { EditMode = CSSM_ACL_EDIT_MODE_DELETE; OldEntryHandle = h; NewEntry = NULL; } | |
156 | ||
157 | CSSM_ACL_EDIT_MODE mode() const { return EditMode; } | |
158 | CSSM_ACL_HANDLE handle() const { return OldEntryHandle; } | |
159 | const AclEntryInput *newEntry() const { return AclEntryInput::overlay(NewEntry); } | |
160 | }; | |
161 | ||
162 | ||
163 | // | |
164 | // Allocating versions of Acl structures | |
165 | // | |
166 | class AutoAclOwnerPrototype { | |
167 | NOCOPY(AutoAclOwnerPrototype) | |
168 | public: | |
169 | // allocator can be set after construction | |
170 | AutoAclOwnerPrototype(Allocator *allocator = NULL) | |
171 | : mAclOwnerPrototype(NULL), mAllocator(allocator) { } | |
172 | ~AutoAclOwnerPrototype(); | |
173 | ||
174 | operator bool () const { return mAllocator; } | |
175 | bool operator ! () const { return !mAllocator; } | |
176 | ||
177 | operator AclOwnerPrototype * () { return make(); } | |
178 | operator AclOwnerPrototype & () { return *make(); } | |
179 | AclOwnerPrototype &operator * () { return *make(); } | |
180 | ||
181 | TypedList &subject() { return make()->subject(); } | |
182 | TypedList &subject() const | |
183 | { assert(mAclOwnerPrototype); return mAclOwnerPrototype->subject(); } | |
184 | bool delegate() const | |
185 | { assert(mAclOwnerPrototype); return mAclOwnerPrototype->delegate(); } | |
186 | void delegate(bool d) { make()->delegate(d); } | |
187 | ||
188 | void allocator(Allocator &allocator); | |
189 | Allocator &allocator() const { assert(mAllocator); return *mAllocator; } | |
190 | ||
191 | AclOwnerPrototype &operator = (const TypedList &subj) | |
192 | { make()->subject() = subj; make()->delegate(false); return *mAclOwnerPrototype; } | |
193 | ||
194 | const AclOwnerPrototype *release() | |
195 | { AclOwnerPrototype *r = mAclOwnerPrototype; mAclOwnerPrototype = NULL; return r; } | |
196 | ||
197 | private: | |
198 | AclOwnerPrototype *mAclOwnerPrototype; | |
199 | Allocator *mAllocator; | |
200 | ||
201 | AclOwnerPrototype *make(); | |
202 | }; | |
203 | ||
204 | ||
205 | class AutoAclEntryInfoList { | |
206 | NOCOPY(AutoAclEntryInfoList) | |
207 | public: | |
208 | // allocator can be set after construction | |
209 | AutoAclEntryInfoList(Allocator *allocator = NULL) | |
210 | : mEntries(NULL), mCount(0), mAllocator(allocator) { } | |
211 | ~AutoAclEntryInfoList() { clear(); } | |
212 | ||
213 | operator bool () const { return mAllocator; } | |
214 | bool operator ! () const { return !mAllocator; } | |
215 | operator uint32 *() { return &mCount; } | |
216 | operator CSSM_ACL_ENTRY_INFO ** () { return reinterpret_cast<CSSM_ACL_ENTRY_INFO **>(&mEntries); } | |
217 | ||
218 | void allocator(Allocator &allocator); | |
219 | Allocator &allocator() const { assert(mAllocator); return *mAllocator; } | |
220 | ||
221 | const AclEntryInfo &at(uint32 ix) const | |
222 | { assert(ix < mCount); return mEntries[ix]; } | |
223 | const AclEntryInfo &operator [] (uint32 ix) const { return at(ix); } | |
224 | AclEntryInfo &at(uint32 ix); | |
225 | AclEntryInfo &operator[] (uint32 ix) { return at(ix); } | |
226 | ||
227 | uint32 size() const { return mCount; } | |
228 | uint32 count() const { return mCount; } | |
229 | AclEntryInfo *entries() const { return mEntries; } | |
230 | ||
231 | void clear(); | |
232 | void size(uint32 newSize); | |
233 | ||
234 | // structured adders. Inputs must be chunk-allocated with our Allocator | |
235 | void add(const TypedList &subj, const AclAuthorizationSet &auths, const char *tag = NULL); | |
236 | void addPin(const TypedList &subj, uint32 slot); | |
237 | void addPinState(uint32 slot, uint32 state); | |
238 | void addPinState(uint32 slot, uint32 state, uint32 count); | |
239 | ||
240 | void release() { mAllocator = NULL; } | |
241 | ||
242 | private: | |
243 | AclEntryInfo *mEntries; | |
244 | uint32 mCount; | |
245 | Allocator *mAllocator; | |
246 | }; | |
247 | ||
248 | // | |
249 | // Extract the pin number from a "PIN%d?" tag. | |
250 | // Returns 0 if the tag isn't of that form. | |
251 | // | |
252 | uint32 pinFromAclTag(const char *tag, const char *suffix = NULL); | |
253 | ||
254 | ||
255 | class AutoAuthorizationGroup : public AuthorizationGroup { | |
256 | public: | |
257 | AutoAuthorizationGroup(Allocator &alloc) : allocator(alloc) { } | |
258 | explicit AutoAuthorizationGroup(const AclAuthorizationSet &set, | |
259 | Allocator &alloc) : AuthorizationGroup(set, alloc), allocator(alloc) { } | |
260 | ~AutoAuthorizationGroup() { destroy(allocator); } | |
261 | ||
262 | Allocator &allocator; | |
263 | }; | |
264 | ||
265 | ||
266 | // | |
267 | // Walkers for the CSSM API structure types | |
268 | // | |
269 | namespace DataWalkers { | |
270 | ||
271 | // AclEntryInput | |
272 | template <class Action> | |
273 | AclEntryInput *walk(Action &operate, AclEntryInput * &input) | |
274 | { | |
275 | operate(input); | |
276 | walk(operate, input->proto()); | |
277 | return input; | |
278 | } | |
279 | ||
280 | template <class Action> | |
281 | void walk(Action &operate, AclEntryInput &input) | |
282 | { | |
283 | operate(input); | |
284 | walk(operate, input.proto()); | |
285 | } | |
286 | ||
287 | // AclEntryInfo | |
288 | template <class Action> | |
289 | void walk(Action &operate, AclEntryInfo &info) | |
290 | { | |
291 | operate(info); | |
292 | walk(operate, info.proto()); | |
293 | } | |
294 | ||
295 | // AuthorizationGroup | |
296 | template <class Action> | |
297 | void walk(Action &operate, AuthorizationGroup &auth) | |
298 | { | |
299 | operate(auth); | |
300 | uint32 count = auth.count(); | |
301 | operate.blob(auth.AuthTags, count * sizeof(auth.AuthTags[0])); | |
302 | for (uint32 n = 0; n < count; n++) | |
303 | operate(auth.AuthTags[n]); | |
304 | } | |
305 | ||
306 | template <class Action> | |
307 | void walk(Action &operate, CSSM_AUTHORIZATIONGROUP &auth) | |
308 | { walk(operate, static_cast<CSSM_AUTHORIZATIONGROUP &>(auth)); } | |
309 | ||
310 | // AclEntryPrototype | |
311 | template <class Action> | |
312 | void enumerate(Action &operate, AclEntryPrototype &proto) | |
313 | { | |
314 | walk(operate, proto.subject()); | |
315 | walk(operate, proto.authorization()); | |
316 | //@@@ ignoring validity period | |
317 | } | |
318 | ||
319 | template <class Action> | |
320 | void walk(Action &operate, AclEntryPrototype &proto) | |
321 | { | |
322 | operate(proto); | |
323 | enumerate(operate, proto); | |
324 | } | |
325 | ||
326 | template <class Action> | |
327 | AclEntryPrototype *walk(Action &operate, AclEntryPrototype * &proto) | |
328 | { | |
329 | operate(proto); | |
330 | enumerate(operate, *proto); | |
331 | return proto; | |
332 | } | |
333 | ||
334 | // AclOwnerPrototype | |
335 | template <class Action> | |
336 | void walk(Action &operate, AclOwnerPrototype &proto) | |
337 | { | |
338 | operate(proto); | |
339 | walk(operate, proto.subject()); | |
340 | } | |
341 | ||
342 | template <class Action> | |
343 | AclOwnerPrototype *walk(Action &operate, AclOwnerPrototype * &proto) | |
344 | { | |
345 | operate(proto); | |
346 | walk(operate, proto->subject()); | |
347 | return proto; | |
348 | } | |
349 | ||
350 | ||
351 | } // end namespace DataWalkers | |
352 | ||
353 | } // end namespace Security | |
354 | ||
355 | ||
356 | #endif //_CSSMACLPOD |