2 * Copyright (c) 2000-2007,2011 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 // cssmaclpod - enhanced PodWrappers for ACL-related CSSM data structures
31 #include <security_utilities/utilities.h>
32 #include <security_cdsa_utilities/cssmlist.h>
33 #include <security_cdsa_utilities/cssmalloc.h>
37 // a nicer name for an authorization tag
38 typedef CSSM_ACL_AUTHORIZATION_TAG AclAuthorization
;
42 // An STL set of authorization tags, with some convenience features
44 class AclAuthorizationSet
: public std::set
<AclAuthorization
> {
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
55 // Enhanced POD Wrappers for the public ACL-related CSSM structures
57 class AuthorizationGroup
: public PodWrapper
<AuthorizationGroup
, CSSM_AUTHORIZATIONGROUP
> {
59 AuthorizationGroup() { NumberOfAuthTags
= 0; }
60 AuthorizationGroup(const AclAuthorizationSet
&, Allocator
&alloc
);
61 AuthorizationGroup(AclAuthorization tag
, Allocator
&alloc
);
62 void destroy(Allocator
&alloc
);
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
]; }
70 bool contains(CSSM_ACL_AUTHORIZATION_TAG tag
) const;
71 bool containsOnly(CSSM_ACL_AUTHORIZATION_TAG tag
) const;
72 operator AclAuthorizationSet () const;
75 class AclOwnerPrototype
;
77 class AclEntryPrototype
: public PodWrapper
<AclEntryPrototype
, CSSM_ACL_ENTRY_PROTOTYPE
> {
79 AclEntryPrototype() { clearPod(); }
80 explicit AclEntryPrototype(const AclOwnerPrototype
&proto
);
81 AclEntryPrototype(const CSSM_LIST
&subj
, bool delegate
= false)
82 { clearPod(); TypedSubject
= subj
; Delegate
= delegate
; }
84 TypedList
&subject() { return TypedList::overlay(TypedSubject
); }
85 const TypedList
&subject() const { return TypedList::overlay(TypedSubject
); }
87 bool delegate() const { return Delegate
; }
88 void delegate(bool d
) { Delegate
= d
; }
90 char *tag() { return EntryTag
[0] ? EntryTag
: NULL
; }
91 void tag(const char *tagString
);
92 void tag(const std::string
&tagString
);
93 const char *tag() const { return EntryTag
[0] ? EntryTag
: NULL
; }
94 std::string
s_tag() const { return EntryTag
; }
96 AuthorizationGroup
&authorization() { return AuthorizationGroup::overlay(Authorization
); }
97 const AuthorizationGroup
&authorization() const
98 { return AuthorizationGroup::overlay(Authorization
); }
101 class AclOwnerPrototype
: public PodWrapper
<AclOwnerPrototype
, CSSM_ACL_OWNER_PROTOTYPE
> {
103 AclOwnerPrototype() { clearPod(); }
104 explicit AclOwnerPrototype(const AclEntryPrototype
&proto
)
105 { TypedSubject
= proto
.subject(); delegate(proto
.delegate()); }
106 AclOwnerPrototype(const CSSM_LIST
&subj
, bool del
= false)
107 { TypedSubject
= subj
; delegate(del
); }
109 TypedList
&subject() { return TypedList::overlay(TypedSubject
); }
110 const TypedList
&subject() const { return TypedList::overlay(TypedSubject
); }
111 bool delegate() const { return Delegate
; }
112 void delegate(bool d
) { Delegate
= d
; }
115 class AclEntryInfo
: public PodWrapper
<AclEntryInfo
, CSSM_ACL_ENTRY_INFO
> {
117 AclEntryInfo() { clearPod(); }
118 AclEntryInfo(const AclEntryPrototype
&prot
, CSSM_ACL_HANDLE h
= 0)
119 { proto() = prot
; handle() = h
; }
121 AclEntryPrototype
&proto() { return AclEntryPrototype::overlay(EntryPublicInfo
); }
122 const AclEntryPrototype
&proto() const
123 { return AclEntryPrototype::overlay(EntryPublicInfo
); }
125 operator AclEntryPrototype
&() { return proto(); }
126 operator const AclEntryPrototype
&() const { return proto(); }
128 CSSM_ACL_HANDLE
&handle() { return EntryHandle
; }
129 const CSSM_ACL_HANDLE
&handle() const { return EntryHandle
; }
130 void handle(CSSM_ACL_HANDLE h
) { EntryHandle
= h
; }
133 class AclEntryInput
: public PodWrapper
<AclEntryInput
, CSSM_ACL_ENTRY_INPUT
> {
135 AclEntryInput() { clearPod(); }
136 AclEntryInput(const CSSM_ACL_ENTRY_PROTOTYPE
&prot
)
137 { Prototype
= prot
; Callback
= NULL
; CallerContext
= NULL
; }
139 AclEntryInput
&operator = (const CSSM_ACL_ENTRY_PROTOTYPE
&prot
)
140 { Prototype
= prot
; Callback
= NULL
; CallerContext
= NULL
; return *this; }
142 AclEntryPrototype
&proto() { return AclEntryPrototype::overlay(Prototype
); }
143 const AclEntryPrototype
&proto() const { return AclEntryPrototype::overlay(Prototype
); }
144 //@@@ not supporting callback features (yet)
147 class AclEdit
: public PodWrapper
<AclEdit
, CSSM_ACL_EDIT
> {
149 AclEdit(CSSM_ACL_EDIT_MODE m
, CSSM_ACL_HANDLE h
, const AclEntryInput
*data
)
150 { EditMode
= m
; OldEntryHandle
= h
; NewEntry
= data
; }
151 AclEdit(const AclEntryInput
&add
)
152 { EditMode
= CSSM_ACL_EDIT_MODE_ADD
; OldEntryHandle
= CSSM_INVALID_HANDLE
; NewEntry
= &add
; }
153 AclEdit(CSSM_ACL_HANDLE h
, const AclEntryInput
&modify
)
154 { EditMode
= CSSM_ACL_EDIT_MODE_REPLACE
; OldEntryHandle
= h
; NewEntry
= &modify
; }
155 AclEdit(CSSM_ACL_HANDLE h
)
156 { EditMode
= CSSM_ACL_EDIT_MODE_DELETE
; OldEntryHandle
= h
; NewEntry
= NULL
; }
158 CSSM_ACL_EDIT_MODE
mode() const { return EditMode
; }
159 CSSM_ACL_HANDLE
handle() const { return OldEntryHandle
; }
160 const AclEntryInput
*newEntry() const { return AclEntryInput::overlay(NewEntry
); }
165 // Allocating versions of Acl structures
167 class AutoAclOwnerPrototype
{
168 NOCOPY(AutoAclOwnerPrototype
)
170 // allocator can be set after construction
171 AutoAclOwnerPrototype(Allocator
*allocator
= NULL
)
172 : mAclOwnerPrototype(NULL
), mAllocator(allocator
) { }
173 ~AutoAclOwnerPrototype();
175 operator bool () const { return mAllocator
; }
176 bool operator ! () const { return !mAllocator
; }
178 operator AclOwnerPrototype
* () { return make(); }
179 operator AclOwnerPrototype
& () { return *make(); }
180 AclOwnerPrototype
&operator * () { return *make(); }
182 TypedList
&subject() { return make()->subject(); }
183 TypedList
&subject() const
184 { assert(mAclOwnerPrototype
); return mAclOwnerPrototype
->subject(); }
185 bool delegate() const
186 { assert(mAclOwnerPrototype
); return mAclOwnerPrototype
->delegate(); }
187 void delegate(bool d
) { make()->delegate(d
); }
189 void allocator(Allocator
&allocator
);
190 Allocator
&allocator() const { assert(mAllocator
); return *mAllocator
; }
192 AclOwnerPrototype
&operator = (const TypedList
&subj
)
193 { make()->subject() = subj
; make()->delegate(false); return *mAclOwnerPrototype
; }
195 const AclOwnerPrototype
*release()
196 { AclOwnerPrototype
*r
= mAclOwnerPrototype
; mAclOwnerPrototype
= NULL
; return r
; }
199 AclOwnerPrototype
*mAclOwnerPrototype
;
200 Allocator
*mAllocator
;
202 AclOwnerPrototype
*make();
206 class AutoAclEntryInfoList
{
207 NOCOPY(AutoAclEntryInfoList
)
209 // allocator can be set after construction
210 AutoAclEntryInfoList(Allocator
*allocator
= NULL
)
211 : mEntries(NULL
), mCount(0), mAllocator(allocator
) { }
212 ~AutoAclEntryInfoList() { clear(); }
214 operator bool () const { return mAllocator
; }
215 bool operator ! () const { return !mAllocator
; }
216 operator uint32
*() { return &mCount
; }
217 operator CSSM_ACL_ENTRY_INFO
** () { return reinterpret_cast<CSSM_ACL_ENTRY_INFO
**>(&mEntries
); }
219 void allocator(Allocator
&allocator
);
220 Allocator
&allocator() const { assert(mAllocator
); return *mAllocator
; }
222 const AclEntryInfo
&at(uint32 ix
) const
223 { assert(ix
< mCount
); return mEntries
[ix
]; }
224 const AclEntryInfo
&operator [] (uint32 ix
) const { return at(ix
); }
225 AclEntryInfo
&at(uint32 ix
);
226 AclEntryInfo
&operator[] (uint32 ix
) { return at(ix
); }
228 uint32
size() const { return mCount
; }
229 uint32
count() const { return mCount
; }
230 AclEntryInfo
*entries() const { return mEntries
; }
233 void size(uint32 newSize
);
235 // structured adders. Inputs must be chunk-allocated with our Allocator
236 void add(const TypedList
&subj
, const AclAuthorizationSet
&auths
, const char *tag
= NULL
);
237 void addPin(const TypedList
&subj
, uint32 slot
);
238 void addPinState(uint32 slot
, uint32 state
);
239 void addPinState(uint32 slot
, uint32 state
, uint32 count
);
241 void release() { mAllocator
= NULL
; }
244 AclEntryInfo
*mEntries
;
246 Allocator
*mAllocator
;
250 // Extract the pin number from a "PIN%d?" tag.
251 // Returns 0 if the tag isn't of that form.
253 uint32
pinFromAclTag(const char *tag
, const char *suffix
= NULL
);
256 class AutoAuthorizationGroup
: public AuthorizationGroup
{
258 AutoAuthorizationGroup(Allocator
&alloc
) : allocator(alloc
) { }
259 explicit AutoAuthorizationGroup(const AclAuthorizationSet
&set
,
260 Allocator
&alloc
) : AuthorizationGroup(set
, alloc
), allocator(alloc
) { }
261 ~AutoAuthorizationGroup() { destroy(allocator
); }
263 Allocator
&allocator
;
268 // Walkers for the CSSM API structure types
270 namespace DataWalkers
{
273 template <class Action
>
274 AclEntryInput
*walk(Action
&operate
, AclEntryInput
* &input
)
277 walk(operate
, input
->proto());
281 template <class Action
>
282 void walk(Action
&operate
, AclEntryInput
&input
)
285 walk(operate
, input
.proto());
289 template <class Action
>
290 void walk(Action
&operate
, AclEntryInfo
&info
)
293 walk(operate
, info
.proto());
296 // AuthorizationGroup
297 template <class Action
>
298 void walk(Action
&operate
, AuthorizationGroup
&auth
)
301 uint32 count
= auth
.count();
302 operate
.blob(auth
.AuthTags
, count
* sizeof(auth
.AuthTags
[0]));
303 for (uint32 n
= 0; n
< count
; n
++)
304 operate(auth
.AuthTags
[n
]);
307 template <class Action
>
308 void walk(Action
&operate
, CSSM_AUTHORIZATIONGROUP
&auth
)
309 { walk(operate
, static_cast<CSSM_AUTHORIZATIONGROUP
&>(auth
)); }
312 template <class Action
>
313 void enumerate(Action
&operate
, AclEntryPrototype
&proto
)
315 walk(operate
, proto
.subject());
316 walk(operate
, proto
.authorization());
317 //@@@ ignoring validity period
320 template <class Action
>
321 void walk(Action
&operate
, AclEntryPrototype
&proto
)
324 enumerate(operate
, proto
);
327 template <class Action
>
328 AclEntryPrototype
*walk(Action
&operate
, AclEntryPrototype
* &proto
)
331 enumerate(operate
, *proto
);
336 template <class Action
>
337 void walk(Action
&operate
, AclOwnerPrototype
&proto
)
340 walk(operate
, proto
.subject());
343 template <class Action
>
344 AclOwnerPrototype
*walk(Action
&operate
, AclOwnerPrototype
* &proto
)
347 walk(operate
, proto
->subject());
352 } // end namespace DataWalkers
354 } // end namespace Security