]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/cssmacl.h
Security-54.1.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) CredentialsContext, 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) const;
204 void validateOwner(AclAuthorization authorizationHint, const AccessCredentials *cred,
205 AclValidationEnvironment *env = NULL) const;
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 // debugging support (always there but stubbed out unless DEBUGDUMP)
224 virtual void debugDump(const char *what = NULL) const;
225
226 public:
227 class Entry {
228 public:
229 AclSubjectPointer subject; // subject representation
230 bool delegate; // delegation flag
231
232 Entry() { } // make invalid Entry
233
234 void toOwnerInfo(CSSM_ACL_OWNER_PROTOTYPE &info,
235 CssmAllocator &alloc) const; // encode copy in CSSM format
236
237 virtual bool authorizes(AclAuthorization auth) const = 0;
238 virtual bool validate(const AclValidationContext &ctx) const = 0;
239
240 template <class Action>
241 void ObjectAcl::Entry::exportBlob(Action &pub, Action &priv)
242 {
243 uint32 del = delegate; pub(del); // 4 bytes delegate flag
244 exportSubject(subject, pub, priv); // subject itself (polymorphic)
245 }
246 void importBlob(Reader &pub, Reader &priv);
247
248 IFDUMP(virtual void debugDump() const);
249
250 private:
251 void init(const AclSubjectPointer &subject, bool delegate = false);
252 void init(const TypedList &subject, bool delegate = false) { init(make(subject), delegate); }
253
254 protected:
255 Entry(const AclEntryPrototype &proto) { init(proto.subject(), proto.delegate()); }
256 Entry(const AclOwnerPrototype &proto) { init(proto.subject()); }
257 Entry(const AclSubjectPointer &subject) { init(subject); }
258 virtual ~Entry();
259 };
260
261 class OwnerEntry : public Entry {
262 public:
263 OwnerEntry() { } // invalid OwnerEntry
264 template <class Input>
265 OwnerEntry(const Input &owner) : Entry(owner) { }
266 OwnerEntry(const AclSubjectPointer &subject) : Entry(subject) { }
267
268 bool authorizes(AclAuthorization auth) const;
269 bool validate(const AclValidationContext &ctx) const;
270 };
271
272 class AclEntry : public Entry {
273 public:
274 std::string tag; // entry tag
275 AclAuthorizationSet authorizations; // set of authorizations
276 bool authorizesAnything; // has the _ANY authorization tag
277 //@@@ time range not yet implemented
278 uint32 handle; // entry handle
279
280 AclEntry() { } // invalid AclEntry
281 AclEntry(const AclSubjectPointer &subject);
282 AclEntry(const AclEntryPrototype &proto);
283
284 void toEntryInfo(CSSM_ACL_ENTRY_PROTOTYPE &info,
285 CssmAllocator &alloc) const; // encode copy in CSSM format
286
287 bool authorizes(AclAuthorization auth) const;
288 bool validate(const AclValidationContext &ctx) const;
289
290 template <class Action>
291 void exportBlob(Action &pub, Action &priv)
292 {
293 Entry::exportBlob(pub, priv);
294 const char *s = tag.c_str(); pub(s);
295 uint32 aa = authorizesAnything; pub(aa);
296 if (!authorizesAnything) {
297 uint32 count = authorizations.size(); pub(count);
298 for (AclAuthorizationSet::iterator it = authorizations.begin();
299 it != authorizations.end(); it++) {
300 AclAuthorization auth = *it; pub(auth);
301 }
302 }
303 //@@@ export time range
304 }
305 void importBlob(Reader &pub, Reader &priv);
306
307 IFDUMP(void debugDump() const);
308 };
309
310 public:
311 // These helpers deal with transferring one subject from/to reader/writer streams.
312 // You'd usually only call those from complex subject implementations (e.g. threshold)
313 template <class Action>
314 static void ObjectAcl::exportSubject(AclSubject *subject, Action &pub, Action &priv)
315 {
316 uint32 typeAndVersion = subject->type() | subject->version() << AclSubject::versionShift;
317 pub(typeAndVersion);
318 subject->exportBlob(pub, priv);
319 }
320 static AclSubject *importSubject(Reader &pub, Reader &priv);
321
322 public:
323 typedef std::multimap<string, AclEntry> EntryMap;
324 typedef EntryMap::iterator Iterator;
325 typedef EntryMap::const_iterator ConstIterator;
326
327 Iterator begin() { return entries.begin(); }
328 Iterator end() { return entries.end(); }
329 ConstIterator begin() const { return entries.begin(); }
330 ConstIterator end() const { return entries.end(); }
331
332 unsigned int getRange(const char *tag, pair<ConstIterator, ConstIterator> &range) const;
333 Iterator findEntryHandle(CSSM_ACL_HANDLE handle);
334
335 // construct an AclSubject through the Maker registry (by subject type)
336 static AclSubject *make(const TypedList &list); // make from CSSM form
337 static AclSubject *make(uint32 typeAndVersion,
338 Reader &pub, Reader &priv); // make from export form
339
340 private:
341 EntryMap entries; // ACL entries indexed by tag
342 OwnerEntry owner; // ACL owner entry
343 uint32 nextHandle; // next unused entry handle value
344
345 private:
346 typedef map<CSSM_ACL_SUBJECT_TYPE, AclSubject::Maker *> MakerMap;
347 static ModuleNexus<MakerMap> makers; // registered subject Makers
348
349 static AclSubject::Maker &makerFor(CSSM_ACL_SUBJECT_TYPE type);
350 };
351
352
353 //
354 // This bastard child of two different data structure sets has no natural home.
355 // We'll take pity on it here.
356 //
357 class ResourceControlContext : public PodWrapper<ResourceControlContext, CSSM_RESOURCE_CONTROL_CONTEXT> {
358 public:
359 ResourceControlContext() { }
360 ResourceControlContext(const AclEntryInput &initial, AccessCredentials *cred = NULL)
361 { InitialAclEntry = initial; AccessCred = cred; }
362
363 AclEntryInput &input() { return AclEntryInput::overlay(InitialAclEntry); }
364 operator AclEntryInput &() { return input(); }
365 AccessCredentials *credentials() const { return AccessCredentials::overlay(AccessCred); }
366 void credentials(const CSSM_ACCESS_CREDENTIALS *creds)
367 { AccessCred = const_cast<CSSM_ACCESS_CREDENTIALS *>(creds); }
368 };
369
370 } // end namespace Security
371
372
373 #endif //_CSSMACL