]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cdsa_utilities/lib/objectacl.h
Security-59754.41.1.tar.gz
[apple/security.git] / OSX / libsecurity_cdsa_utilities / lib / objectacl.h
1 /*
2 * Copyright (c) 2000-2004,2006,2011-2012,2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 //
26 // objectacl - core implementation of an ACL-bearing object
27 //
28 #ifndef _OBJECTACL
29 #define _OBJECTACL
30
31 #include <security_cdsa_utilities/aclsubject.h>
32 #include <security_utilities/globalizer.h>
33 #include <security_utilities/threading.h>
34 #include <map>
35 #include <set>
36 #include <limits.h>
37
38
39 namespace Security {
40
41
42 //
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
50 // your situation).
51 //
52 class ObjectAcl {
53 friend AclSubject::Maker::Maker(CSSM_ACL_SUBJECT_TYPE);
54
55 public:
56 typedef RefPointer<AclSubject> AclSubjectPointer;
57
58 typedef LowLevelMemoryUtilities::Writer Writer;
59 typedef LowLevelMemoryUtilities::Reader Reader;
60
61 public:
62 ObjectAcl(Allocator &alloc);
63 ObjectAcl(const AclEntryPrototype &proto, Allocator &alloc);
64 virtual ~ObjectAcl();
65
66 Allocator &allocator;
67
68
69 //
70 // access control validation (evaluation)
71 //
72
73 // validate(): succeed or throw exception
74 void validate(AclAuthorization auth, const AccessCredentials *cred,
75 AclValidationEnvironment *env = NULL);
76 void validate(AclValidationContext &ctx);
77
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);
82
83 // owner validation (simpler)
84 void validateOwner(AclAuthorization authorizationHint, const AccessCredentials *cred,
85 AclValidationEnvironment *env = NULL);
86 void validateOwner(AclValidationContext &ctx);
87
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);
96
97 void cssmSetInitial(const AclEntryPrototype &proto);
98 void cssmSetInitial(const AclSubjectPointer &subject);
99
100 // Acl I/O (to/from memory blobs)
101 void exportBlob(CssmData &publicBlob, CssmData &privateBlob);
102 void importBlob(const void *publicBlob, const void *privateBlob);
103
104 // clear everything from this ACL (return it to un-initialized state)
105 void clear();
106
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
110
111 // debug dump support (always there but stubbed out unless DEBUGDUMP)
112 virtual void debugDump(const char *what = NULL) const;
113
114 public:
115 class Entry {
116 public:
117 AclSubjectPointer subject; // subject representation
118 bool delegate; // delegation flag
119
120 Entry() { } // make invalid Entry
121
122 void toOwnerInfo(CSSM_ACL_OWNER_PROTOTYPE &info,
123 Allocator &alloc) const; // encode copy in CSSM format
124
125 virtual bool authorizes(AclAuthorization auth) const = 0;
126 virtual bool validates(const AclValidationContext &ctx) const = 0;
127
128 template <class Action>
129 void exportBlob(Action &pub, Action &priv)
130 {
131 Endian<uint32> del = delegate; pub(del); // 4 bytes delegate flag
132 exportSubject(subject, pub, priv); // subject itself (polymorphic)
133 }
134 void importBlob(Reader &pub, Reader &priv);
135
136 IFDUMP(virtual void debugDump() const);
137
138 private:
139 void init(const AclSubjectPointer &subject, bool delegate = false);
140 void init(const TypedList &subject, bool delegate = false) { init(make(subject), delegate); }
141
142 protected:
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); }
146 virtual ~Entry();
147 };
148
149 class OwnerEntry : public Entry {
150 public:
151 OwnerEntry() { } // invalid OwnerEntry
152 template <class Input>
153 OwnerEntry(const Input &owner) : Entry(owner) { }
154
155 bool authorizes(AclAuthorization auth) const;
156 bool validates(const AclValidationContext &ctx) const;
157 };
158
159 class AclEntry : public Entry {
160 public:
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
166
167 AclEntry() { } // invalid AclEntry
168 AclEntry(const AclSubjectPointer &subject);
169 AclEntry(const AclEntryPrototype &proto);
170
171 void toEntryInfo(CSSM_ACL_ENTRY_PROTOTYPE &info,
172 Allocator &alloc) const; // encode copy in CSSM format
173
174 bool authorizes(AclAuthorization auth) const;
175 bool validates(const AclValidationContext &ctx) const;
176
177 void addAuthorization(AclAuthorization auth);
178
179 template <class Action>
180 void exportBlob(Action &pub, Action &priv)
181 {
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);
190 }
191 }
192 //@@@ export time range
193 }
194 void importBlob(Reader &pub, Reader &priv);
195
196 IFDUMP(void debugDump() const);
197 };
198
199 public:
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)
204 {
205 Endian<uint32> typeAndVersion = subject->type() | subject->version() << AclSubject::versionShift;
206 pub(typeAndVersion);
207 subject->exportBlob(pub, priv);
208 }
209 static AclSubject *importSubject(Reader &pub, Reader &priv);
210
211 public:
212 typedef std::multimap<string, AclEntry> EntryMap;
213
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(); }
218
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);
222
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
227
228 protected:
229 template <class Input>
230 void owner(const Input &input);
231 void entries(uint32 count, const AclEntryInfo *infos);
232
233 public:
234 void add(const std::string &tag, const AclEntry &newEntry);
235 void add(const std::string &tag, AclEntry newEntry, CSSM_ACL_HANDLE handle);
236
237 private:
238 EntryMap mEntries; // ACL entries indexed by tag
239 OwnerEntry mOwner; // ACL owner entry
240 CSSM_ACL_HANDLE mNextHandle; // next unused entry handle value
241
242 private:
243 typedef map<CSSM_ACL_SUBJECT_TYPE, AclSubject::Maker *> MakerMap;
244 static ModuleNexus<MakerMap> makers; // registered subject Makers
245 static ModuleNexus<NormalMutex> makersMutex;
246
247 static AclSubject::Maker &makerFor(CSSM_ACL_SUBJECT_TYPE type);
248 };
249
250
251 } // end namespace Security
252
253
254 #endif //_OBJECTACL