]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/cssmacl.h
Security-29.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 // Statement of strategy:
23 // Beyond the enhanced POD Wrappers for the various CSSM types, we find pure C++ classes
24 // that implement ACLs in the local address space. ObjectAcl is the abstract interface
25 // to an implementation of a CSSM ACL. It supports the CSSM interfaces for ACL manipulation.
26 // @@@ TBA @@@
27 //
28 #ifndef _CSSMACL
29 #define _CSSMACL
30
31 #include <Security/cssmaclpod.h>
32 #include <Security/cssmcred.h>
33 #include <Security/refcount.h>
34 #include <Security/globalizer.h>
35 #include <Security/memutils.h>
36 #include <map>
37 #include <set>
38 #include <string>
39 #include <limits.h>
40
41 #ifdef _CPP_CSSMACL
42 #pragma export on
43 #endif
44
45 namespace Security
46 {
47
48 class AclValidationContext;
49
50
51 //
52 // The AclSubject class models an ACL "subject" object.
53 // This is an abstract polymorphic class implementing various ACL subject types.
54 // Note that it does contain some common code to make everybody's life easier.
55 //
56 class AclSubject : public RefCount {
57 typedef LowLevelMemoryUtilities::Writer Writer;
58 typedef LowLevelMemoryUtilities::Reader Reader;
59 public:
60 AclSubject(uint32 type) : mType(type) { }
61 virtual ~AclSubject();
62 uint32 type() const { return mType; }
63
64 virtual bool validate(const AclValidationContext &ctx) const = 0;
65
66 // export to CSSM interface
67 virtual CssmList toList(CssmAllocator &alloc) const = 0;
68
69 // export/import for save/restore interface
70 virtual void exportBlob(Writer::Counter &pub, Writer::Counter &priv);
71 virtual void exportBlob(Writer &pub, Writer &priv);
72 virtual void importBlob(Reader &pub, Reader &priv);
73
74 // debug suupport
75 IFDUMP(virtual void debugDump() const);
76
77 private:
78 CSSM_ACL_SUBJECT_TYPE mType;
79
80 public:
81 class Maker {
82 public:
83 Maker(CSSM_ACL_SUBJECT_TYPE type);
84 virtual ~Maker();
85
86 uint32 type() const { return myType; }
87 virtual AclSubject *make(const TypedList &list) const = 0;
88 virtual AclSubject *make(Reader &pub, Reader &priv) const = 0;
89
90 protected:
91 // list parsing helpers
92 static void crack(const CssmList &list, uint32 count,
93 ListElement **array = NULL, ...);
94 static CSSM_WORDID_TYPE getWord(const ListElement &list,
95 int min = 0, int max = INT_MAX);
96
97 private:
98 CSSM_ACL_SUBJECT_TYPE myType;
99 };
100 };
101
102
103 //
104 // A SimpleAclSubject validates a credential by scanning its samples
105 // one at a time, without any interactions between them. Thus its validate()
106 // can be a lot simpler.
107 //
108 class SimpleAclSubject : public AclSubject {
109 public:
110 SimpleAclSubject(CSSM_ACL_SUBJECT_TYPE su, CSSM_SAMPLE_TYPE sa)
111 : AclSubject(su), acceptingSamples(sa) { }
112
113 bool validate(const AclValidationContext &ctx) const;
114 virtual bool validate(const AclValidationContext &baseCtx,
115 const TypedList &sample) const = 0;
116
117 const CSSM_SAMPLE_TYPE acceptingSamples;
118 };
119
120
121 //
122 // An AclValidationEnvironment can be subclassed to add context access to ACL subject
123 // validation. If you use ACL subject classes that need context beyond the credential
124 // structure itself, add that context to (a subclass of) CredentialsContext, pass that
125 // to ObjectAcl::validate() along with the credentials, and have the Subject implementation
126 // access validationContext.environment().
127 //
128 class AclValidationEnvironment {
129 public:
130 virtual ~AclValidationEnvironment(); // ensure virtual methods (need dynamic_cast)
131 };
132
133
134 //
135 // An AclValidationContext holds credential information in a semi-transparent
136 // form. It's designed to provide a uniform representation of credentials, plus
137 // any (trusted path and/or implicit) context information useful for ACL validation.
138 //
139 class AclValidationContext {
140 public:
141 AclValidationContext(const AccessCredentials *cred,
142 AclAuthorization auth, AclValidationEnvironment *env = NULL)
143 : mCred(cred), mAuth(auth), mEnv(env) { }
144 AclValidationContext(const AclValidationContext &ctx)
145 : mCred(ctx.mCred), mAuth(ctx.mAuth), mEnv(ctx.mEnv) { }
146 virtual ~AclValidationContext();
147
148 // access to (suitably focused) sample set
149 virtual uint32 count() const = 0; // number of samples
150 virtual const TypedList &sample(uint32 n) const = 0; // retrieve one sample
151 const TypedList &operator [] (uint32 n) const { return sample(n); }
152
153 // context access
154 AclAuthorization authorization() const { return mAuth; }
155 template <class Env>
156 Env *environment() const { return dynamic_cast<Env *>(mEnv); }
157
158 //@@@ add certificate access functions
159 //@@@ add callback management
160
161 protected:
162 const AccessCredentials *mCred; // original credentials
163 AclAuthorization mAuth; // action requested
164 AclValidationEnvironment *mEnv; // environmental context (if any)
165 };
166
167
168 //
169 // An in-memory ACL object.
170 // This class implements an ACL-for-a-protected-object. It is complete in that
171 // it provides full ACL management functionality. You still need to (globally)
172 // register makers for the ACL subject types you want to use.
173 // Note that ObjectAcl does no integrity checking. ObjectAcl objects need to be
174 // protected from hostile access (by e.g. address space separation), and exported
175 // ACLs need to be protected somehow (by hiding, signing, or whatever works in
176 // your situation).
177 //
178 class ObjectAcl {
179 friend AclSubject::Maker::Maker(CSSM_ACL_SUBJECT_TYPE);
180
181 public:
182 typedef RefPointer<AclSubject> AclSubjectPointer;
183
184 typedef LowLevelMemoryUtilities::Writer Writer;
185 typedef LowLevelMemoryUtilities::Reader Reader;
186
187 public:
188 ObjectAcl(CssmAllocator &alloc);
189 ObjectAcl(const AclEntryPrototype &proto, CssmAllocator &alloc);
190 virtual ~ObjectAcl();
191
192 CssmAllocator &allocator;
193
194 // access control validation: succeed or throw exception
195 void validate(AclAuthorization auth, const AccessCredentials *cred,
196 AclValidationEnvironment *env = NULL) const;
197 void validateOwner(AclAuthorization authorizationHint, const AccessCredentials *cred,
198 AclValidationEnvironment *env = NULL) const;
199
200 // CSSM-style ACL access operations
201 // (Gets are not const because underlying implementations usually want them writable)
202 void cssmGetAcl(const char *tag, uint32 &count, AclEntryInfo * &acls);
203 void cssmChangeAcl(const AclEdit &edit, const AccessCredentials *cred,
204 AclValidationEnvironment *env = NULL);
205 void cssmGetOwner(AclOwnerPrototype &owner);
206 void cssmChangeOwner(const AclOwnerPrototype &newOwner, const AccessCredentials *cred,
207 AclValidationEnvironment *env = NULL);
208
209 void cssmSetInitial(const AclEntryPrototype &proto);
210 void cssmSetInitial(const AclSubjectPointer &subject);
211
212 // Acl I/O (to/from memory blobs)
213 void exportBlob(CssmData &publicBlob, CssmData &privateBlob);
214 void importBlob(const void *publicBlob, const void *privateBlob);
215
216 // debugging support
217 IFDUMP(virtual void debugDump(const char *what = NULL) const);
218
219 public:
220 class Entry {
221 public:
222 AclSubjectPointer subject; // subject representation
223 bool delegate; // delegation flag
224
225 Entry() { } // make invalid Entry
226
227 void toOwnerInfo(CSSM_ACL_OWNER_PROTOTYPE &info,
228 CssmAllocator &alloc) const; // encode copy in CSSM format
229
230 virtual bool authorizes(AclAuthorization auth) const = 0;
231 virtual bool validate(const AclValidationContext &ctx) const = 0;
232
233 template <class Action>
234 void exportBlob(Action &pub, Action &priv)
235 {
236 pub(delegate);
237 CSSM_ACL_SUBJECT_TYPE type = subject->type(); pub(type);
238 subject->exportBlob(pub, priv);
239 }
240 void importBlob(Reader &pub, Reader &priv);
241
242 IFDUMP(virtual void debugDump() const);
243
244 private:
245 void init(const AclSubjectPointer &subject, bool delegate = false);
246 void init(const TypedList &subject, bool delegate = false) { init(make(subject), delegate); }
247
248 protected:
249 Entry(const AclEntryPrototype &proto) { init(proto.subject(), proto.delegate()); }
250 Entry(const AclOwnerPrototype &proto) { init(proto.subject()); }
251 Entry(const AclSubjectPointer &subject) { init(subject); }
252 virtual ~Entry();
253 };
254
255 class OwnerEntry : public Entry {
256 public:
257 OwnerEntry() { } // invalid OwnerEntry
258 template <class Input>
259 OwnerEntry(const Input &owner) : Entry(owner) { }
260 OwnerEntry(const AclSubjectPointer &subject) : Entry(subject) { }
261
262 bool authorizes(AclAuthorization auth) const;
263 bool validate(const AclValidationContext &ctx) const;
264 };
265
266 class AclEntry : public Entry {
267 public:
268 string tag; // entry tag
269 AclAuthorizationSet authorizations; // set of authorizations
270 bool authorizesAnything; // has the _ANY authorization tag
271 //@@@ time range not yet implemented
272 uint32 handle; // entry handle
273
274 AclEntry() { } // invalid AclEntry
275 AclEntry(const AclSubjectPointer &subject);
276 AclEntry(const AclEntryPrototype &proto);
277
278 void toEntryInfo(CSSM_ACL_ENTRY_PROTOTYPE &info,
279 CssmAllocator &alloc) const; // encode copy in CSSM format
280
281 bool authorizes(AclAuthorization auth) const;
282 bool validate(const AclValidationContext &ctx) const;
283
284 template <class Action>
285 void exportBlob(Action &pub, Action &priv)
286 {
287 Entry::exportBlob(pub, priv);
288 const char *s = tag.c_str(); pub(s);
289 pub(authorizesAnything);
290 if (!authorizesAnything) {
291 uint32 count = authorizations.size(); pub(count);
292 for (AclAuthorizationSet::iterator it = authorizations.begin();
293 it != authorizations.end(); it++) {
294 AclAuthorization auth = *it; pub(auth);
295 }
296 }
297 //@@@ export time range
298 }
299 void importBlob(Reader &pub, Reader &priv);
300
301 IFDUMP(void debugDump() const);
302 };
303
304 typedef multimap<string, AclEntry> EntryMap;
305 typedef EntryMap::iterator Iterator;
306 typedef EntryMap::const_iterator ConstIterator;
307
308 Iterator begin() { return entries.begin(); }
309 Iterator end() { return entries.end(); }
310 ConstIterator begin() const { return entries.begin(); }
311 ConstIterator end() const { return entries.end(); }
312
313 unsigned int getRange(const char *tag, pair<ConstIterator, ConstIterator> &range) const;
314 Iterator findEntryHandle(CSSM_ACL_HANDLE handle);
315
316 // construct an AclSubject through the Maker registry (by subject type)
317 static AclSubject *make(const TypedList &list); // make from CSSM form
318 static AclSubject *make(CSSM_ACL_SUBJECT_TYPE type,
319 Reader &pub, Reader &priv); // make from export form
320
321 private:
322 EntryMap entries; // ACL entries indexed by tag
323 OwnerEntry owner; // ACL owner entry
324 uint32 nextHandle; // next unused entry handle value
325
326 private:
327 typedef map<CSSM_ACL_SUBJECT_TYPE, AclSubject::Maker *> MakerMap;
328 static ModuleNexus<MakerMap> makers; // registered subject Makers
329
330 static AclSubject::Maker &makerFor(CSSM_ACL_SUBJECT_TYPE type);
331 };
332
333
334 //
335 // This bastard child of two different data structure sets has no natural home.
336 // We'll take pity on it here.
337 //
338 class ResourceControlContext : public PodWrapper<ResourceControlContext, CSSM_RESOURCE_CONTROL_CONTEXT> {
339 public:
340 ResourceControlContext() { }
341 ResourceControlContext(const AclEntryInput &initial, AccessCredentials *cred = NULL)
342 { InitialAclEntry = initial; AccessCred = cred; }
343
344 operator AclEntryInput &() { return AclEntryInput::overlay(InitialAclEntry); }
345 AccessCredentials *credentials() { return AccessCredentials::overlay(AccessCred); }
346 };
347
348 } // end namespace Security
349
350 #ifdef _CPP_CSSMACL
351 #pragma export off
352 #endif
353
354
355 #endif //_CSSMACL