]> git.saurik.com Git - apple/security.git/blame - cdsa/cdsa_utilities/cssmacl.h
Security-54.1.9.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / cssmacl.h
CommitLineData
bac41a7b
A
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//
29654253
A
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.
bac41a7b
A
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
bac41a7b 42
29654253 43namespace Security {
bac41a7b
A
44
45class 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//
53class AclSubject : public RefCount {
29654253 54public:
bac41a7b
A
55 typedef LowLevelMemoryUtilities::Writer Writer;
56 typedef LowLevelMemoryUtilities::Reader Reader;
29654253
A
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)); }
bac41a7b
A
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
29654253
A
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;
bac41a7b
A
82
83private:
84 CSSM_ACL_SUBJECT_TYPE mType;
29654253 85 Version mVersion;
bac41a7b
A
86
87public:
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;
29654253 95 virtual AclSubject *make(Version version, Reader &pub, Reader &priv) const = 0;
bac41a7b
A
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//
115class SimpleAclSubject : public AclSubject {
116public:
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//
135class AclValidationEnvironment {
136public:
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//
146class AclValidationContext {
147public:
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
168protected:
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//
185class ObjectAcl {
186 friend AclSubject::Maker::Maker(CSSM_ACL_SUBJECT_TYPE);
187
188public:
189 typedef RefPointer<AclSubject> AclSubjectPointer;
190
191 typedef LowLevelMemoryUtilities::Writer Writer;
192 typedef LowLevelMemoryUtilities::Reader Reader;
193
194public:
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
29654253
A
223 // debugging support (always there but stubbed out unless DEBUGDUMP)
224 virtual void debugDump(const char *what = NULL) const;
bac41a7b
A
225
226public:
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
29654253
A
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 }
bac41a7b
A
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:
29654253
A
274 std::string tag; // entry tag
275 AclAuthorizationSet authorizations; // set of authorizations
276 bool authorizesAnything; // has the _ANY authorization tag
bac41a7b 277 //@@@ time range not yet implemented
29654253 278 uint32 handle; // entry handle
bac41a7b 279
29654253 280 AclEntry() { } // invalid AclEntry
bac41a7b
A
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);
29654253 295 uint32 aa = authorizesAnything; pub(aa);
bac41a7b
A
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 };
29654253
A
309
310public:
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);
bac41a7b 321
29654253
A
322public:
323 typedef std::multimap<string, AclEntry> EntryMap;
bac41a7b
A
324 typedef EntryMap::iterator Iterator;
325 typedef EntryMap::const_iterator ConstIterator;
29654253 326
bac41a7b
A
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(); }
29654253 331
bac41a7b
A
332 unsigned int getRange(const char *tag, pair<ConstIterator, ConstIterator> &range) const;
333 Iterator findEntryHandle(CSSM_ACL_HANDLE handle);
29654253 334
bac41a7b
A
335 // construct an AclSubject through the Maker registry (by subject type)
336 static AclSubject *make(const TypedList &list); // make from CSSM form
29654253 337 static AclSubject *make(uint32 typeAndVersion,
bac41a7b
A
338 Reader &pub, Reader &priv); // make from export form
339
340private:
341 EntryMap entries; // ACL entries indexed by tag
342 OwnerEntry owner; // ACL owner entry
343 uint32 nextHandle; // next unused entry handle value
344
345private:
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//
357class ResourceControlContext : public PodWrapper<ResourceControlContext, CSSM_RESOURCE_CONTROL_CONTEXT> {
358public:
359 ResourceControlContext() { }
360 ResourceControlContext(const AclEntryInput &initial, AccessCredentials *cred = NULL)
361 { InitialAclEntry = initial; AccessCred = cred; }
362
29654253
A
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); }
bac41a7b
A
368};
369
370} // end namespace Security
371
bac41a7b
A
372
373#endif //_CSSMACL