2  * Copyright (c) 2000-2004,2006,2011-2012,2014 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 // objectacl - core implementation of an ACL-bearing object 
  31 #include <security_cdsa_utilities/aclsubject.h> 
  32 #include <security_utilities/globalizer.h> 
  42 // An in-memory ACL object. 
  43 // This class implements an ACL-for-a-protected-object. It is complete in that 
  44 // it provides full ACL management functionality. You still need to (globally) 
  45 // register makers for the ACL subject types you want to use. 
  46 // Note that ObjectAcl does no integrity checking. ObjectAcl objects need to be 
  47 // protected from hostile access (by e.g. address space separation), and exported 
  48 // ACLs need to be protected somehow (by hiding, signing, or whatever works in 
  52     friend AclSubject::Maker::Maker(CSSM_ACL_SUBJECT_TYPE
); 
  55     typedef RefPointer
<AclSubject
> AclSubjectPointer
; 
  57     typedef LowLevelMemoryUtilities::Writer Writer
; 
  58     typedef LowLevelMemoryUtilities::Reader Reader
; 
  61     ObjectAcl(Allocator 
&alloc
); 
  62     ObjectAcl(const AclEntryPrototype 
&proto
, Allocator 
&alloc
); 
  69     // access control validation (evaluation) 
  72         // validate(): succeed or throw exception 
  73     void validate(AclAuthorization auth
, const AccessCredentials 
*cred
, 
  74         AclValidationEnvironment 
*env 
= NULL
); 
  75         void validate(AclValidationContext 
&ctx
); 
  77         // validates(): return true or false (or throw on error) 
  78     bool validates(AclAuthorization auth
, const AccessCredentials 
*cred
, 
  79         AclValidationEnvironment 
*env 
= NULL
); 
  80         bool validates(AclValidationContext 
&ctx
); 
  82         // owner validation (simpler) 
  83     void validateOwner(AclAuthorization authorizationHint
, const AccessCredentials 
*cred
, 
  84                 AclValidationEnvironment 
*env 
= NULL
); 
  85         void validateOwner(AclValidationContext 
&ctx
); 
  87     // CSSM-style ACL access operations 
  88         // (Gets are not const because underlying implementations usually want them writable)  
  89     void cssmGetAcl(const char *tag
, uint32 
&count
, AclEntryInfo 
* &acls
); 
  90     void cssmChangeAcl(const AclEdit 
&edit
, const AccessCredentials 
*cred
, 
  91                 AclValidationEnvironment 
*env 
= NULL
); 
  92     void cssmGetOwner(AclOwnerPrototype 
&owner
); 
  93     void cssmChangeOwner(const AclOwnerPrototype 
&newOwner
, const AccessCredentials 
*cred
, 
  94                 AclValidationEnvironment 
*env 
= NULL
); 
  96     void cssmSetInitial(const AclEntryPrototype 
&proto
); 
  97     void cssmSetInitial(const AclSubjectPointer 
&subject
); 
  99     // Acl I/O (to/from memory blobs) 
 100     void exportBlob(CssmData 
&publicBlob
, CssmData 
&privateBlob
); 
 101     void importBlob(const void *publicBlob
, const void *privateBlob
); 
 103         // clear everything from this ACL (return it to un-initialized state) 
 106         // setup hooks (called to delayed-construct the contents before use) - empty defaults 
 107         virtual void instantiateAcl();  // called before ACL contents are used by external calls 
 108         virtual void changedAcl();              // called after an ACL has been (possibly) changed 
 110         // debug dump support (always there but stubbed out unless DEBUGDUMP) 
 111         virtual void debugDump(const char *what 
= NULL
) const; 
 116         AclSubjectPointer subject
;              // subject representation 
 117         bool delegate
;                                  // delegation flag 
 119         Entry() { }                                             // make invalid Entry 
 121         void toOwnerInfo(CSSM_ACL_OWNER_PROTOTYPE 
&info
, 
 122                         Allocator 
&alloc
) const; // encode copy in CSSM format 
 124         virtual bool authorizes(AclAuthorization auth
) const = 0; 
 125         virtual bool validate(const AclValidationContext 
&ctx
) const = 0; 
 127                 template <class Action
> 
 128                 void exportBlob(Action 
&pub
, Action 
&priv
) 
 130                         Endian
<uint32
> del 
= delegate
; pub(del
);        // 4 bytes delegate flag 
 131                         exportSubject(subject
, pub
, priv
);      // subject itself (polymorphic) 
 133         void importBlob(Reader 
&pub
, Reader 
&priv
); 
 135                 IFDUMP(virtual void debugDump() const); 
 138         void init(const AclSubjectPointer 
&subject
, bool delegate 
= false); 
 139         void init(const TypedList 
&subject
, bool delegate 
= false) { init(make(subject
), delegate
); } 
 142         Entry(const AclEntryPrototype 
&proto
) { init(proto
.subject(), proto
.delegate()); } 
 143         Entry(const AclOwnerPrototype 
&proto
) { init(proto
.subject()); } 
 144         Entry(const AclSubjectPointer 
&subject
) { init(subject
); } 
 148     class OwnerEntry 
: public Entry 
{ 
 150         OwnerEntry() { }        // invalid OwnerEntry 
 151         template <class Input
> 
 152         OwnerEntry(const Input 
&owner
) : Entry(owner
) { } 
 154         bool authorizes(AclAuthorization auth
) const; 
 155         bool validate(const AclValidationContext 
&ctx
) const; 
 158     class AclEntry 
: public Entry 
{ 
 160         std::string tag
;                                                // entry tag 
 161                 AclAuthorizationSet authorizations
;             // set of authorizations 
 162         bool authorizesAnything
;                                // has the _ANY authorization tag 
 163         //@@@ time range not yet implemented 
 164         CSSM_ACL_HANDLE handle
;                                 // entry handle 
 166                 AclEntry() { }                                                  // invalid AclEntry 
 167         AclEntry(const AclSubjectPointer 
&subject
); 
 168         AclEntry(const AclEntryPrototype 
&proto
); 
 170         void toEntryInfo(CSSM_ACL_ENTRY_PROTOTYPE 
&info
, 
 171                         Allocator 
&alloc
) const; // encode copy in CSSM format 
 173         bool authorizes(AclAuthorization auth
) const; 
 174         bool validate(const AclValidationContext 
&ctx
) const; 
 176         template <class Action
> 
 177         void exportBlob(Action 
&pub
, Action 
&priv
) 
 179             Entry::exportBlob(pub
, priv
); 
 180             const char *s 
= tag
.c_str(); pub(s
); 
 181             uint32 aa 
= authorizesAnything
; pub(aa
); 
 182             if (!authorizesAnything
) { 
 183                 Endian
<uint32
> count 
= (uint32
)authorizations
.size(); pub(count
); 
 184                 for (AclAuthorizationSet::iterator it 
= authorizations
.begin(); 
 185                     it 
!= authorizations
.end(); it
++) { 
 186                     Endian
<AclAuthorization
> auth 
= *it
; pub(auth
); 
 189             //@@@ export time range 
 191         void importBlob(Reader 
&pub
, Reader 
&priv
); 
 193                 IFDUMP(void debugDump() const); 
 197         // These helpers deal with transferring one subject from/to reader/writer streams. 
 198         // You'd usually only call those from complex subject implementations (e.g. threshold) 
 199         template <class Action
> 
 200         static void exportSubject(AclSubject 
*subject
, Action 
&pub
, Action 
&priv
) 
 202                 Endian
<uint32
> typeAndVersion 
= subject
->type() | subject
->version() << AclSubject::versionShift
; 
 204                 subject
->exportBlob(pub
, priv
); 
 206         static AclSubject 
*importSubject(Reader 
&pub
, Reader 
&priv
); 
 209     typedef std::multimap
<string
, AclEntry
> EntryMap
; 
 211     EntryMap::iterator 
begin() { return mEntries
.begin(); } 
 212         EntryMap::iterator 
end() { return mEntries
.end(); } 
 213     EntryMap::const_iterator 
begin() const { return mEntries
.begin(); } 
 214     EntryMap::const_iterator 
end() const { return mEntries
.end(); } 
 216     unsigned int getRange(const std::string 
&tag
, 
 217                 pair
<EntryMap::const_iterator
, EntryMap::const_iterator
> &range
) const;  
 218     EntryMap::iterator 
findEntryHandle(CSSM_ACL_HANDLE handle
); 
 220     // construct an AclSubject through the Maker registry (by subject type) 
 221     static AclSubject 
*make(const TypedList 
&list
);     // make from CSSM form 
 222     static AclSubject 
*make(uint32 typeAndVersion
, 
 223                             Reader 
&pub
, Reader 
&priv
); // make from export form 
 226         template <class Input
> 
 227         void owner(const Input 
&input
); 
 228         void entries(uint32 count
, const AclEntryInfo 
*infos
); 
 231         void add(const std::string 
&tag
, const AclEntry 
&newEntry
); 
 232         void add(const std::string 
&tag
, AclEntry newEntry
, CSSM_ACL_HANDLE handle
); 
 235     EntryMap mEntries
;                          // ACL entries indexed by tag 
 236     OwnerEntry mOwner
;                          // ACL owner entry 
 237     CSSM_ACL_HANDLE mNextHandle
;        // next unused entry handle value 
 240     typedef map
<CSSM_ACL_SUBJECT_TYPE
, AclSubject::Maker 
*> MakerMap
; 
 241     static ModuleNexus
<MakerMap
> makers
;        // registered subject Makers 
 243     static AclSubject::Maker 
&makerFor(CSSM_ACL_SUBJECT_TYPE type
); 
 247 } // end namespace Security