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>
33 #include <security_utilities/threading.h>
43 // An in-memory ACL object.
44 // This class implements an ACL-for-a-protected-object. It is complete in that
45 // it provides full ACL management functionality. You still need to (globally)
46 // register makers for the ACL subject types you want to use.
47 // Note that ObjectAcl does no integrity checking. ObjectAcl objects need to be
48 // protected from hostile access (by e.g. address space separation), and exported
49 // ACLs need to be protected somehow (by hiding, signing, or whatever works in
53 friend AclSubject::Maker::Maker(CSSM_ACL_SUBJECT_TYPE
);
56 typedef RefPointer
<AclSubject
> AclSubjectPointer
;
58 typedef LowLevelMemoryUtilities::Writer Writer
;
59 typedef LowLevelMemoryUtilities::Reader Reader
;
62 ObjectAcl(Allocator
&alloc
);
63 ObjectAcl(const AclEntryPrototype
&proto
, Allocator
&alloc
);
70 // access control validation (evaluation)
73 // validate(): succeed or throw exception
74 void validate(AclAuthorization auth
, const AccessCredentials
*cred
,
75 AclValidationEnvironment
*env
= NULL
);
76 void validate(AclValidationContext
&ctx
);
78 // validates(): return true or false (or throw on error)
79 bool validates(AclAuthorization auth
, const AccessCredentials
*cred
,
80 AclValidationEnvironment
*env
= NULL
);
81 bool validates(AclValidationContext
&ctx
);
83 // owner validation (simpler)
84 void validateOwner(AclAuthorization authorizationHint
, const AccessCredentials
*cred
,
85 AclValidationEnvironment
*env
= NULL
);
86 void validateOwner(AclValidationContext
&ctx
);
88 // CSSM-style ACL access operations
89 // (Gets are not const because underlying implementations usually want them writable)
90 void cssmGetAcl(const char *tag
, uint32
&count
, AclEntryInfo
* &acls
);
91 void cssmChangeAcl(const AclEdit
&edit
, const AccessCredentials
*cred
,
92 AclValidationEnvironment
*env
= NULL
, const char *preserveTag
= NULL
);
93 void cssmGetOwner(AclOwnerPrototype
&owner
);
94 void cssmChangeOwner(const AclOwnerPrototype
&newOwner
, const AccessCredentials
*cred
,
95 AclValidationEnvironment
*env
= NULL
);
97 void cssmSetInitial(const AclEntryPrototype
&proto
);
98 void cssmSetInitial(const AclSubjectPointer
&subject
);
100 // Acl I/O (to/from memory blobs)
101 void exportBlob(CssmData
&publicBlob
, CssmData
&privateBlob
);
102 void importBlob(const void *publicBlob
, const void *privateBlob
);
104 // clear everything from this ACL (return it to un-initialized state)
107 // setup hooks (called to delayed-construct the contents before use) - empty defaults
108 virtual void instantiateAcl(); // called before ACL contents are used by external calls
109 virtual void changedAcl(); // called after an ACL has been (possibly) changed
111 // debug dump support (always there but stubbed out unless DEBUGDUMP)
112 virtual void debugDump(const char *what
= NULL
) const;
117 AclSubjectPointer subject
; // subject representation
118 bool delegate
; // delegation flag
120 Entry() { } // make invalid Entry
122 void toOwnerInfo(CSSM_ACL_OWNER_PROTOTYPE
&info
,
123 Allocator
&alloc
) const; // encode copy in CSSM format
125 virtual bool authorizes(AclAuthorization auth
) const = 0;
126 virtual bool validates(const AclValidationContext
&ctx
) const = 0;
128 template <class Action
>
129 void exportBlob(Action
&pub
, Action
&priv
)
131 Endian
<uint32
> del
= delegate
; pub(del
); // 4 bytes delegate flag
132 exportSubject(subject
, pub
, priv
); // subject itself (polymorphic)
134 void importBlob(Reader
&pub
, Reader
&priv
);
136 IFDUMP(virtual void debugDump() const);
139 void init(const AclSubjectPointer
&subject
, bool delegate
= false);
140 void init(const TypedList
&subject
, bool delegate
= false) { init(make(subject
), delegate
); }
143 Entry(const AclEntryPrototype
&proto
) { init(proto
.subject(), proto
.delegate()); }
144 Entry(const AclOwnerPrototype
&proto
) { init(proto
.subject()); }
145 Entry(const AclSubjectPointer
&subject
) { init(subject
); }
149 class OwnerEntry
: public Entry
{
151 OwnerEntry() { } // invalid OwnerEntry
152 template <class Input
>
153 OwnerEntry(const Input
&owner
) : Entry(owner
) { }
155 bool authorizes(AclAuthorization auth
) const;
156 bool validates(const AclValidationContext
&ctx
) const;
159 class AclEntry
: public Entry
{
161 std::string tag
; // entry tag
162 AclAuthorizationSet authorizations
; // set of authorizations
163 bool authorizesAnything
; // has the _ANY authorization tag
164 //@@@ time range not yet implemented
165 CSSM_ACL_HANDLE handle
; // entry handle
167 AclEntry() { } // invalid AclEntry
168 AclEntry(const AclSubjectPointer
&subject
);
169 AclEntry(const AclEntryPrototype
&proto
);
171 void toEntryInfo(CSSM_ACL_ENTRY_PROTOTYPE
&info
,
172 Allocator
&alloc
) const; // encode copy in CSSM format
174 bool authorizes(AclAuthorization auth
) const;
175 bool validates(const AclValidationContext
&ctx
) const;
177 void addAuthorization(AclAuthorization auth
);
179 template <class Action
>
180 void exportBlob(Action
&pub
, Action
&priv
)
182 Entry::exportBlob(pub
, priv
);
183 const char *s
= tag
.c_str(); pub(s
);
184 uint32 aa
= authorizesAnything
; pub(aa
);
185 if (!authorizesAnything
) {
186 Endian
<uint32
> count
= (uint32
)authorizations
.size(); pub(count
);
187 for (AclAuthorizationSet::iterator it
= authorizations
.begin();
188 it
!= authorizations
.end(); it
++) {
189 Endian
<AclAuthorization
> auth
= *it
; pub(auth
);
192 //@@@ export time range
194 void importBlob(Reader
&pub
, Reader
&priv
);
196 IFDUMP(void debugDump() const);
200 // These helpers deal with transferring one subject from/to reader/writer streams.
201 // You'd usually only call those from complex subject implementations (e.g. threshold)
202 template <class Action
>
203 static void exportSubject(AclSubject
*subject
, Action
&pub
, Action
&priv
)
205 Endian
<uint32
> typeAndVersion
= subject
->type() | subject
->version() << AclSubject::versionShift
;
207 subject
->exportBlob(pub
, priv
);
209 static AclSubject
*importSubject(Reader
&pub
, Reader
&priv
);
212 typedef std::multimap
<string
, AclEntry
> EntryMap
;
214 EntryMap::iterator
begin() { return mEntries
.begin(); }
215 EntryMap::iterator
end() { return mEntries
.end(); }
216 EntryMap::const_iterator
begin() const { return mEntries
.begin(); }
217 EntryMap::const_iterator
end() const { return mEntries
.end(); }
219 unsigned int getRange(const std::string
&tag
,
220 pair
<EntryMap::const_iterator
, EntryMap::const_iterator
> &range
, bool tolerant
= false) const;
221 EntryMap::iterator
findEntryHandle(CSSM_ACL_HANDLE handle
);
223 // construct an AclSubject through the Maker registry (by subject type)
224 static AclSubject
*make(const TypedList
&list
); // make from CSSM form
225 static AclSubject
*make(uint32 typeAndVersion
,
226 Reader
&pub
, Reader
&priv
); // make from export form
229 template <class Input
>
230 void owner(const Input
&input
);
231 void entries(uint32 count
, const AclEntryInfo
*infos
);
234 void add(const std::string
&tag
, const AclEntry
&newEntry
);
235 void add(const std::string
&tag
, AclEntry newEntry
, CSSM_ACL_HANDLE handle
);
238 EntryMap mEntries
; // ACL entries indexed by tag
239 OwnerEntry mOwner
; // ACL owner entry
240 CSSM_ACL_HANDLE mNextHandle
; // next unused entry handle value
243 typedef map
<CSSM_ACL_SUBJECT_TYPE
, AclSubject::Maker
*> MakerMap
;
244 static ModuleNexus
<MakerMap
> makers
; // registered subject Makers
245 static ModuleNexus
<NormalMutex
> makersMutex
;
247 static AclSubject::Maker
&makerFor(CSSM_ACL_SUBJECT_TYPE type
);
251 } // end namespace Security