1/*
2 * Copyright (c) 2000-2004,2006,2011,2013-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// aclsubject - abstract ACL subject implementation
27//
28#ifndef _ACLSUBJECT
29#define _ACLSUBJECT
30
31#include <security_cdsa_utilities/cssmaclpod.h>
32#include <security_cdsa_utilities/cssmcred.h>
33#include <security_utilities/refcount.h>
34#include <security_utilities/globalizer.h>
35#include <security_utilities/memutils.h>
36#include <security_utilities/adornments.h>
37#include <map>
38#include <set>
39#include <string>
40#include <limits.h>
41
42
43namespace Security {
44
45class ObjectAcl;
46class AclValidationContext;
47class AclSubject;
48
49
50//
51// An AclValidationEnvironment can be subclassed to add context access to ACL subject
52// validation. If you use ACL subject classes that need context beyond the credential
53// structure itself, add that context to (a virtual subclass of) AclValidationContext, pass that
54// to ObjectAcl::validate() along with the credentials, and have the Subject implementation
55// access validationContext.environment().
56//
57class AclValidationEnvironment {
58	friend class AclValidationContext;
59public:
60    virtual ~AclValidationEnvironment();	// ensure virtual methods (need dynamic_cast)
61
62	// provide an Adornable for a given subject to store data in, or throw if none available (default)
63	virtual Adornable &store(const AclSubject *subject);
64};
65
66
67//
68// An AclValidationContext holds all context for an ACL evaluation in one
69// package. It's designed to provide a uniform representation of credentials, plus
70// any (trusted path and/or implicit) context information useful for ACL validation.
71//
72// Contexts are immutable (constant) for validators; they do not change at all
73// during a validation exercise. Anything that should be mutable must go into
74// the environment (which is indirect and modifyable).
75//
76class AclValidationContext {
77	friend class ObjectAcl;
78public:
79    AclValidationContext(const AccessCredentials *cred,
80        AclAuthorization auth, AclValidationEnvironment *env = NULL)
81    : mAcl((ObjectAcl*) 0xDEADDEADDEADDEAD), mSubject((AclSubject*) 0xDEADDEADDEADDEAD), mCred(cred),
82        mAuth(auth), mEnv(env), mEntryTag(NULL) { }
83    AclValidationContext(const AclValidationContext &ctx)
84    : mAcl(ctx.mAcl), mSubject(ctx.mSubject), mCred(ctx.mCred),
85	  mAuth(ctx.mAuth), mEnv(ctx.mEnv), mEntryTag(NULL) { }
86	virtual ~AclValidationContext();
87
88    // access to (suitably focused) sample set
89    virtual uint32 count() const = 0;	// number of samples
90	uint32 size() const { return count(); } // alias
91    virtual const TypedList &sample(uint32 n) const = 0;	// retrieve one sample
92    const TypedList &operator [] (uint32 n) const { return sample(n); }
93
94    // context access
95    AclAuthorization authorization() const	{ return mAuth; }
96	const AccessCredentials *cred() const	{ return mCred; }
97	AclValidationEnvironment *environment() const { return mEnv; }
98    template <class Env> Env *environment() const { return dynamic_cast<Env *>(mEnv); }
99	AclSubject *subject() const				{ return mSubject; }
100	ObjectAcl *acl() const					{ return mAcl; }
101
102	// tag manipulation
103	virtual const char *credTag() const;
104	virtual const char *entryTag() const;
105	std::string s_credTag() const;
106	void entryTag(const char *tag);
107	void entryTag(const std::string &tag);
108
109	// selective match support - not currently implemented
110	virtual void matched(const TypedList *match) const = 0;
111	void matched(const TypedList &match) const { return matched(&match); }
112
113private:
114	void init(ObjectAcl *acl, AclSubject *subject);
115
116private:
117	ObjectAcl *mAcl;					// underlying ObjectAcl
118	AclSubject *mSubject;				// subject being validated
119    const AccessCredentials *mCred;		// original credentials
120    AclAuthorization mAuth;				// action requested
121    AclValidationEnvironment *mEnv;		// environmental context (if any)
122	const char *mEntryTag;				// entry tag
123};
124
125
126//
127// The AclSubject class models an ACL "subject" object. If you have a new ACL
128// subject type or variant, you make a subclass of this (plus a suitable Maker).
129//
130// Note that AclSubjects can contain both configuration and state information.
131// Configuration is set during AclSubject creation (passwords to check against,
132// evaluation options, etc.) and are typically passed on in the externalized form;
133// it is persistent.
134// On the other hand, state is volatile and is lost when the AclSubject dies.
135// This is stuff that accumulates during a particular lifetime, such as results
136// of previous evaluations (for caching or more nefarious purposes).
137// Be clear what each of your subclass members are, and document accordingly.
138//
139class AclSubject : public RefCount {
140public:
141    typedef LowLevelMemoryUtilities::Writer Writer;
142    typedef LowLevelMemoryUtilities::Reader Reader;
143
144	typedef uint8 Version;		// binary version marker
145	static const int versionShift = 24;	// highest-order byte of type is version
146	static const uint32 versionMask = 0xff000000;
147
148public:
149	explicit AclSubject(uint32 type, Version v = 0);
150    virtual ~AclSubject();
151    CSSM_ACL_SUBJECT_TYPE type() const { return mType; }
152
153	// validation (evaluation) primitive
154    virtual bool validate(const AclValidationContext &ctx) const = 0;
155
156    // export to CSSM interface
157    virtual CssmList toList(Allocator &alloc) const = 0;
158
159    // export/import for save/restore interface
160    virtual void exportBlob(Writer::Counter &pub, Writer::Counter &priv);
161    virtual void exportBlob(Writer &pub, Writer &priv);
162    virtual void importBlob(Reader &pub, Reader &priv);
163
164	// binary compatibility version management. The version defaults to zero
165	Version version() const	{ return mVersion; }
166
167	// forget any validation-related state you have acquired
168	virtual void reset();
169
170	// debug suupport (dummied out but present for -UDEBUGDUMP)
171	virtual void debugDump() const;
172	IFDUMP(void dump(const char *title) const);
173
174protected:
175	void version(Version v)	{ mVersion = v; }
176
177private:
178    CSSM_ACL_SUBJECT_TYPE mType;
179	Version mVersion;
180
181public:
182    class Maker {
183    public:
184        Maker(CSSM_ACL_SUBJECT_TYPE type);
185		virtual ~Maker();
186
187        uint32 type() const { return mType; }
188        virtual AclSubject *make(const TypedList &list) const = 0;
189        virtual AclSubject *make(Version version, Reader &pub, Reader &priv) const = 0;
190
191    protected:
192        // list parsing helpers
193        static void crack(const CssmList &list, uint32 count,
194            ListElement **array = NULL, ...);
195        static CSSM_WORDID_TYPE getWord(const ListElement &list,
196            int min = 0, int max = INT_MAX);
197
198    private:
199        CSSM_ACL_SUBJECT_TYPE mType;
200    };
201};
202
203
204//
205// A SimpleAclSubject validates a credential by scanning its samples
206// one at a time, without any interactions between them. Thus its validate()
207// can be a lot simpler.
208// Note that this layer assumes that subject and sample types have the same
209// value, as is typical when both are derived from a WORDID.
210//
211class SimpleAclSubject : public AclSubject {
212public:
213    SimpleAclSubject(CSSM_ACL_SUBJECT_TYPE type) : AclSubject(type) { }
214
215    bool validate(const AclValidationContext &ctx) const;
216    virtual bool validate(const AclValidationContext &baseCtx,
217        const TypedList &sample) const = 0;
218};
219
220
221} // end namespace Security
222
223
224#endif //_ACLSUBJECT
225