]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/cssmacl.h
Security-177.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / cssmacl.h
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 //
20 // cssmacl - core ACL management interface.
21 //
22 // This file contains a set of C++ classes that implement ACLs in the local address space.
23 // ObjectAcl is the abstract interface to an implementation of a CSSM ACL. It supports
24 // the CSSM interfaces for ACL manipulation. AclSubject is the common parent of all
25 // types of ACL Subjects (in the CSSM sense); subclass this to implement a new subject type.
26 // AclValidationContext is an extensible, structured way of passing context information
27 // from the evaluation environment into particular subjects whose validation is context sensitive.
28 //
29 #ifndef _CSSMACL
30 #define _CSSMACL
31
32 #include <Security/cssmaclpod.h>
33 #include <Security/cssmcred.h>
34 #include <Security/refcount.h>
35 #include <Security/globalizer.h>
36 #include <Security/memutils.h>
37 #include <map>
38 #include <set>
39 #include <string>
40 #include <limits.h>
41
42
43 namespace Security {
44
45 class AclValidationContext;
46
47
48 //
49 // The AclSubject class models an ACL "subject" object.
50 // This is an abstract polymorphic class implementing various ACL subject types.
51 // Note that it does contain some common code to make everybody's life easier.
52 //
53 class AclSubject : public RefCount {
54 public:
55 typedef LowLevelMemoryUtilities::Writer Writer;
56 typedef LowLevelMemoryUtilities::Reader Reader;
57
58 typedef uint8 Version; // binary version marker
59 static const int versionShift = 24; // highest-order byte of type is version
60 static const uint32 versionMask = 0xff000000;
61
62 AclSubject(uint32 type) : mType(type), mVersion(0) { assert(!(type & versionMask)); }
63 virtual ~AclSubject();
64 uint32 type() const { return mType; }
65
66 virtual bool validate(const AclValidationContext &ctx) const = 0;
67
68 // export to CSSM interface
69 virtual CssmList toList(CssmAllocator &alloc) const = 0;
70
71 // export/import for save/restore interface
72 virtual void exportBlob(Writer::Counter &pub, Writer::Counter &priv);
73 virtual void exportBlob(Writer &pub, Writer &priv);
74 virtual void importBlob(Reader &pub, Reader &priv);
75
76 // binary compatibility version management. The version defaults to zero
77 Version version() const { return mVersion; }
78 void version(Version v) { mVersion = v; }
79
80 // debug suupport (dummied out but present for -UDEBUGDUMP)
81 virtual void debugDump() const;
82
83 private:
84 CSSM_ACL_SUBJECT_TYPE mType;
85 Version mVersion;
86
87 public:
88 class Maker {
89 public:
90 Maker(CSSM_ACL_SUBJECT_TYPE type);
91 virtual ~Maker();
92
93 uint32 type() const { return myType; }
94 virtual AclSubject *make(const TypedList &list) const = 0;
95 virtual AclSubject *make(Version version, Reader &pub, Reader &priv) const = 0;
96
97 protected:
98 // list parsing helpers
99 static void crack(const CssmList &list, uint32 count,
100 ListElement **array = NULL, ...);
101 static CSSM_WORDID_TYPE getWord(const ListElement &list,
102 int min = 0, int max = INT_MAX);
103
104 private:
105 CSSM_ACL_SUBJECT_TYPE myType;
106 };
107 };
108
109
110 //
111 // A SimpleAclSubject validates a credential by scanning its samples
112 // one at a time, without any interactions between them. Thus its validate()
113 // can be a lot simpler.
114 //
115 class SimpleAclSubject : public AclSubject {
116 public:
117 SimpleAclSubject(CSSM_ACL_SUBJECT_TYPE su, CSSM_SAMPLE_TYPE sa)
118 : AclSubject(su), acceptingSamples(sa) { }
119
120 bool validate(const AclValidationContext &ctx) const;
121 virtual bool validate(const AclValidationContext &baseCtx,
122 const TypedList &sample) const = 0;
123
124 const CSSM_SAMPLE_TYPE acceptingSamples;
125 };
126
127
128 //
129 // An AclValidationEnvironment can be subclassed to add context access to ACL subject
130 // validation. If you use ACL subject classes that need context beyond the credential
131 // structure itself, add that context to (a subclass of) AclValidationContext, pass that
132 // to ObjectAcl::validate() along with the credentials, and have the Subject implementation
133 // access validationContext.environment().
134 //
135 class AclValidationEnvironment {
136 public:
137 virtual ~AclValidationEnvironment(); // ensure virtual methods (need dynamic_cast)
138 };
139
140
141 //
142 // An AclValidationContext holds credential information in a semi-transparent
143 // form. It's designed to provide a uniform representation of credentials, plus
144 // any (trusted path and/or implicit) context information useful for ACL validation.
145 //
146 class AclValidationContext {
147 public:
148 AclValidationContext(const AccessCredentials *cred,
149 AclAuthorization auth, AclValidationEnvironment *env = NULL)
150 : mCred(cred), mAuth(auth), mEnv(env) { }
151 AclValidationContext(const AclValidationContext &ctx)
152 : mCred(ctx.mCred), mAuth(ctx.mAuth), mEnv(ctx.mEnv) { }
153 virtual ~AclValidationContext();
154
155 // access to (suitably focused) sample set
156 virtual uint32 count() const = 0; // number of samples
157 virtual const TypedList &sample(uint32 n) const = 0; // retrieve one sample
158 const TypedList &operator [] (uint32 n) const { return sample(n); }
159
160 // context access
161 AclAuthorization authorization() const { return mAuth; }
162 template <class Env>
163 Env *environment() const { return dynamic_cast<Env *>(mEnv); }
164
165 //@@@ add certificate access functions
166 //@@@ add callback management
167
168 protected:
169 const AccessCredentials *mCred; // original credentials
170 AclAuthorization mAuth; // action requested
171 AclValidationEnvironment *mEnv; // environmental context (if any)
172 };
173
174
175 //
176 // An in-memory ACL object.
177 // This class implements an ACL-for-a-protected-object. It is complete in that
178 // it provides full ACL management functionality. You still need to (globally)
179 // register makers for the ACL subject types you want to use.
180 // Note that ObjectAcl does no integrity checking. ObjectAcl objects need to be
181 // protected from hostile access (by e.g. address space separation), and exported
182 // ACLs need to be protected somehow (by hiding, signing, or whatever works in
183 // your situation).
184 //
185 class ObjectAcl {
186 friend AclSubject::Maker::Maker(CSSM_ACL_SUBJECT_TYPE);
187
188 public:
189 typedef RefPointer<AclSubject> AclSubjectPointer;
190
191 typedef LowLevelMemoryUtilities::Writer Writer;
192 typedef LowLevelMemoryUtilities::Reader Reader;
193
194 public:
195 ObjectAcl(CssmAllocator &alloc);
196 ObjectAcl(const AclEntryPrototype &proto, CssmAllocator &alloc);
197 virtual ~ObjectAcl();
198
199 CssmAllocator &allocator;
200
201 // access control validation: succeed or throw exception
202 void validate(AclAuthorization auth, const AccessCredentials *cred,
203 AclValidationEnvironment *env = NULL);
204 void validateOwner(AclAuthorization authorizationHint, const AccessCredentials *cred,
205 AclValidationEnvironment *env = NULL);
206
207 // CSSM-style ACL access operations
208 // (Gets are not const because underlying implementations usually want them writable)
209 void cssmGetAcl(const char *tag, uint32 &count, AclEntryInfo * &acls);
210 void cssmChangeAcl(const AclEdit &edit, const AccessCredentials *cred,
211 AclValidationEnvironment *env = NULL);
212 void cssmGetOwner(AclOwnerPrototype &owner);
213 void cssmChangeOwner(const AclOwnerPrototype &newOwner, const AccessCredentials *cred,
214 AclValidationEnvironment *env = NULL);
215
216 void cssmSetInitial(const AclEntryPrototype &proto);
217 void cssmSetInitial(const AclSubjectPointer &subject);
218
219 // Acl I/O (to/from memory blobs)
220 void exportBlob(CssmData &publicBlob, CssmData &privateBlob);
221 void importBlob(const void *publicBlob, const void *privateBlob);
222
223 // setup hooks (called to delayed-construct the contents before use) - empty defaults
224 virtual void instantiateAcl(); // called before ACL contents are used by external calls
225 virtual void changedAcl(); // called after an ACL has been (possibly) changed
226
227 // debug dump support (always there but stubbed out unless DEBUGDUMP)
228 virtual void debugDump(const char *what = NULL) const;
229
230 public:
231 class Entry {
232 public:
233 AclSubjectPointer subject; // subject representation
234 bool delegate; // delegation flag
235
236 Entry() { } // make invalid Entry
237
238 void toOwnerInfo(CSSM_ACL_OWNER_PROTOTYPE &info,
239 CssmAllocator &alloc) const; // encode copy in CSSM format
240
241 virtual bool authorizes(AclAuthorization auth) const = 0;
242 virtual bool validate(const AclValidationContext &ctx) const = 0;
243
244 template <class Action>
245 void ObjectAcl::Entry::exportBlob(Action &pub, Action &priv)
246 {
247 Endian<uint32> del = delegate; pub(del); // 4 bytes delegate flag
248 exportSubject(subject, pub, priv); // subject itself (polymorphic)
249 }
250 void importBlob(Reader &pub, Reader &priv);
251
252 IFDUMP(virtual void debugDump() const);
253
254 private:
255 void init(const AclSubjectPointer &subject, bool delegate = false);
256 void init(const TypedList &subject, bool delegate = false) { init(make(subject), delegate); }
257
258 protected:
259 Entry(const AclEntryPrototype &proto) { init(proto.subject(), proto.delegate()); }
260 Entry(const AclOwnerPrototype &proto) { init(proto.subject()); }
261 Entry(const AclSubjectPointer &subject) { init(subject); }
262 virtual ~Entry();
263 };
264
265 class OwnerEntry : public Entry {
266 public:
267 OwnerEntry() { } // invalid OwnerEntry
268 template <class Input>
269 OwnerEntry(const Input &owner) : Entry(owner) { }
270 OwnerEntry(const AclSubjectPointer &subject) : Entry(subject) { }
271
272 bool authorizes(AclAuthorization auth) const;
273 bool validate(const AclValidationContext &ctx) const;
274 };
275
276 class AclEntry : public Entry {
277 public:
278 std::string tag; // entry tag
279 AclAuthorizationSet authorizations; // set of authorizations
280 bool authorizesAnything; // has the _ANY authorization tag
281 //@@@ time range not yet implemented
282 uint32 handle; // entry handle
283
284 AclEntry() { } // invalid AclEntry
285 AclEntry(const AclSubjectPointer &subject);
286 AclEntry(const AclEntryPrototype &proto);
287
288 void toEntryInfo(CSSM_ACL_ENTRY_PROTOTYPE &info,
289 CssmAllocator &alloc) const; // encode copy in CSSM format
290
291 bool authorizes(AclAuthorization auth) const;
292 bool validate(const AclValidationContext &ctx) const;
293
294 template <class Action>
295 void exportBlob(Action &pub, Action &priv)
296 {
297 Entry::exportBlob(pub, priv);
298 const char *s = tag.c_str(); pub(s);
299 uint32 aa = authorizesAnything; pub(aa);
300 if (!authorizesAnything) {
301 Endian<uint32> count = authorizations.size(); pub(count);
302 for (AclAuthorizationSet::iterator it = authorizations.begin();
303 it != authorizations.end(); it++) {
304 Endian<AclAuthorization> auth = *it; pub(auth);
305 }
306 }
307 //@@@ export time range
308 }
309 void importBlob(Reader &pub, Reader &priv);
310
311 IFDUMP(void debugDump() const);
312 };
313
314 public:
315 // These helpers deal with transferring one subject from/to reader/writer streams.
316 // You'd usually only call those from complex subject implementations (e.g. threshold)
317 template <class Action>
318 static void ObjectAcl::exportSubject(AclSubject *subject, Action &pub, Action &priv)
319 {
320 Endian<uint32> typeAndVersion = subject->type() | subject->version() << AclSubject::versionShift;
321 pub(typeAndVersion);
322 subject->exportBlob(pub, priv);
323 }
324 static AclSubject *importSubject(Reader &pub, Reader &priv);
325
326 public:
327 typedef std::multimap<string, AclEntry> EntryMap;
328 typedef EntryMap::iterator Iterator;
329 typedef EntryMap::const_iterator ConstIterator;
330
331 Iterator begin() { return entries.begin(); }
332 Iterator end() { return entries.end(); }
333 ConstIterator begin() const { return entries.begin(); }
334 ConstIterator end() const { return entries.end(); }
335
336 unsigned int getRange(const char *tag, pair<ConstIterator, ConstIterator> &range) const;
337 Iterator findEntryHandle(CSSM_ACL_HANDLE handle);
338
339 // construct an AclSubject through the Maker registry (by subject type)
340 static AclSubject *make(const TypedList &list); // make from CSSM form
341 static AclSubject *make(uint32 typeAndVersion,
342 Reader &pub, Reader &priv); // make from export form
343
344 private:
345 EntryMap entries; // ACL entries indexed by tag
346 OwnerEntry owner; // ACL owner entry
347 uint32 nextHandle; // next unused entry handle value
348
349 private:
350 typedef map<CSSM_ACL_SUBJECT_TYPE, AclSubject::Maker *> MakerMap;
351 static ModuleNexus<MakerMap> makers; // registered subject Makers
352
353 static AclSubject::Maker &makerFor(CSSM_ACL_SUBJECT_TYPE type);
354 };
355
356
357 //
358 // This bastard child of two different data structure sets has no natural home.
359 // We'll take pity on it here.
360 //
361 class ResourceControlContext : public PodWrapper<ResourceControlContext, CSSM_RESOURCE_CONTROL_CONTEXT> {
362 public:
363 ResourceControlContext() { clearPod(); }
364 ResourceControlContext(const AclEntryInput &initial, AccessCredentials *cred = NULL)
365 { InitialAclEntry = initial; AccessCred = cred; }
366
367 AclEntryInput &input() { return AclEntryInput::overlay(InitialAclEntry); }
368 operator AclEntryInput &() { return input(); }
369 AccessCredentials *credentials() const { return AccessCredentials::overlay(AccessCred); }
370 void credentials(const CSSM_ACCESS_CREDENTIALS *creds)
371 { AccessCred = const_cast<CSSM_ACCESS_CREDENTIALS *>(creds); }
372 };
373
374 } // end namespace Security
375
376
377 #endif //_CSSMACL