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