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 operator AclAuthorizationSet () const;
74 class AclOwnerPrototype
;
76 class AclEntryPrototype
: public PodWrapper
<AclEntryPrototype
, CSSM_ACL_ENTRY_PROTOTYPE
> {
78 AclEntryPrototype() { clearPod(); }
79 explicit AclEntryPrototype(const AclOwnerPrototype
&proto
);
80 AclEntryPrototype(const CSSM_LIST
&subj
, bool delegate
= false)
81 { clearPod(); TypedSubject
= subj
; Delegate
= delegate
; }
83 TypedList
&subject() { return TypedList::overlay(TypedSubject
); }
84 const TypedList
&subject() const { return TypedList::overlay(TypedSubject
); }
86 bool delegate() const { return Delegate
; }
87 void delegate(bool d
) { Delegate
= d
; }
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
; }
95 AuthorizationGroup
&authorization() { return AuthorizationGroup::overlay(Authorization
); }
96 const AuthorizationGroup
&authorization() const
97 { return AuthorizationGroup::overlay(Authorization
); }
100 class AclOwnerPrototype
: public PodWrapper
<AclOwnerPrototype
, CSSM_ACL_OWNER_PROTOTYPE
> {
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
); }
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
; }
114 class AclEntryInfo
: public PodWrapper
<AclEntryInfo
, CSSM_ACL_ENTRY_INFO
> {
116 AclEntryInfo() { clearPod(); }
117 AclEntryInfo(const AclEntryPrototype
&prot
, CSSM_ACL_HANDLE h
= 0)
118 { proto() = prot
; handle() = h
; }
120 AclEntryPrototype
&proto() { return AclEntryPrototype::overlay(EntryPublicInfo
); }
121 const AclEntryPrototype
&proto() const
122 { return AclEntryPrototype::overlay(EntryPublicInfo
); }
124 operator AclEntryPrototype
&() { return proto(); }
125 operator const AclEntryPrototype
&() const { return proto(); }
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
; }
132 class AclEntryInput
: public PodWrapper
<AclEntryInput
, CSSM_ACL_ENTRY_INPUT
> {
134 AclEntryInput() { clearPod(); }
135 AclEntryInput(const CSSM_ACL_ENTRY_PROTOTYPE
&prot
)
136 { Prototype
= prot
; Callback
= NULL
; CallerContext
= NULL
; }
138 AclEntryInput
&operator = (const CSSM_ACL_ENTRY_PROTOTYPE
&prot
)
139 { Prototype
= prot
; Callback
= NULL
; CallerContext
= NULL
; return *this; }
141 AclEntryPrototype
&proto() { return AclEntryPrototype::overlay(Prototype
); }
142 const AclEntryPrototype
&proto() const { return AclEntryPrototype::overlay(Prototype
); }
143 //@@@ not supporting callback features (yet)
146 class AclEdit
: public PodWrapper
<AclEdit
, CSSM_ACL_EDIT
> {
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
; }
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
); }
164 // Allocating versions of Acl structures
166 class AutoAclOwnerPrototype
{
167 NOCOPY(AutoAclOwnerPrototype
)
169 // allocator can be set after construction
170 AutoAclOwnerPrototype(Allocator
*allocator
= NULL
)
171 : mAclOwnerPrototype(NULL
), mAllocator(allocator
) { }
172 ~AutoAclOwnerPrototype();
174 operator bool () const { return mAllocator
; }
175 bool operator ! () const { return !mAllocator
; }
177 operator AclOwnerPrototype
* () { return make(); }
178 operator AclOwnerPrototype
& () { return *make(); }
179 AclOwnerPrototype
&operator * () { return *make(); }
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
); }
188 void allocator(Allocator
&allocator
);
189 Allocator
&allocator() const { assert(mAllocator
); return *mAllocator
; }
191 AclOwnerPrototype
&operator = (const TypedList
&subj
)
192 { make()->subject() = subj
; make()->delegate(false); return *mAclOwnerPrototype
; }
194 const AclOwnerPrototype
*release()
195 { AclOwnerPrototype
*r
= mAclOwnerPrototype
; mAclOwnerPrototype
= NULL
; return r
; }
198 AclOwnerPrototype
*mAclOwnerPrototype
;
199 Allocator
*mAllocator
;
201 AclOwnerPrototype
*make();
205 class AutoAclEntryInfoList
{
206 NOCOPY(AutoAclEntryInfoList
)
208 // allocator can be set after construction
209 AutoAclEntryInfoList(Allocator
*allocator
= NULL
)
210 : mEntries(NULL
), mCount(0), mAllocator(allocator
) { }
211 ~AutoAclEntryInfoList() { clear(); }
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
); }
218 void allocator(Allocator
&allocator
);
219 Allocator
&allocator() const { assert(mAllocator
); return *mAllocator
; }
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
); }
227 uint32
size() const { return mCount
; }
228 uint32
count() const { return mCount
; }
229 AclEntryInfo
*entries() const { return mEntries
; }
232 void size(uint32 newSize
);
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
);
240 void release() { mAllocator
= NULL
; }
243 AclEntryInfo
*mEntries
;
245 Allocator
*mAllocator
;
249 // Extract the pin number from a "PIN%d?" tag.
250 // Returns 0 if the tag isn't of that form.
252 uint32
pinFromAclTag(const char *tag
, const char *suffix
= NULL
);
255 class AutoAuthorizationGroup
: public AuthorizationGroup
{
257 AutoAuthorizationGroup(Allocator
&alloc
) : allocator(alloc
) { }
258 explicit AutoAuthorizationGroup(const AclAuthorizationSet
&set
,
259 Allocator
&alloc
) : AuthorizationGroup(set
, alloc
), allocator(alloc
) { }
260 ~AutoAuthorizationGroup() { destroy(allocator
); }
262 Allocator
&allocator
;
267 // Walkers for the CSSM API structure types
269 namespace DataWalkers
{
272 template <class Action
>
273 AclEntryInput
*walk(Action
&operate
, AclEntryInput
* &input
)
276 walk(operate
, input
->proto());
280 template <class Action
>
281 void walk(Action
&operate
, AclEntryInput
&input
)
284 walk(operate
, input
.proto());
288 template <class Action
>
289 void walk(Action
&operate
, AclEntryInfo
&info
)
292 walk(operate
, info
.proto());
295 // AuthorizationGroup
296 template <class Action
>
297 void walk(Action
&operate
, AuthorizationGroup
&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
]);
306 template <class Action
>
307 void walk(Action
&operate
, CSSM_AUTHORIZATIONGROUP
&auth
)
308 { walk(operate
, static_cast<CSSM_AUTHORIZATIONGROUP
&>(auth
)); }
311 template <class Action
>
312 void enumerate(Action
&operate
, AclEntryPrototype
&proto
)
314 walk(operate
, proto
.subject());
315 walk(operate
, proto
.authorization());
316 //@@@ ignoring validity period
319 template <class Action
>
320 void walk(Action
&operate
, AclEntryPrototype
&proto
)
323 enumerate(operate
, proto
);
326 template <class Action
>
327 AclEntryPrototype
*walk(Action
&operate
, AclEntryPrototype
* &proto
)
330 enumerate(operate
, *proto
);
335 template <class Action
>
336 void walk(Action
&operate
, AclOwnerPrototype
&proto
)
339 walk(operate
, proto
.subject());
342 template <class Action
>
343 AclOwnerPrototype
*walk(Action
&operate
, AclOwnerPrototype
* &proto
)
346 walk(operate
, proto
->subject());
351 } // end namespace DataWalkers
353 } // end namespace Security