2 * Copyright (c) 2000-2004,2006,2011,2013-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 // aclsubject - abstract ACL subject implementation
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 <security_utilities/debugging_internal.h>
47 class AclValidationContext
;
52 // An AclValidationEnvironment can be subclassed to add context access to ACL subject
53 // validation. If you use ACL subject classes that need context beyond the credential
54 // structure itself, add that context to (a virtual subclass of) AclValidationContext, pass that
55 // to ObjectAcl::validate() along with the credentials, and have the Subject implementation
56 // access validationContext.environment().
58 class AclValidationEnvironment
{
59 friend class AclValidationContext
;
61 virtual ~AclValidationEnvironment(); // ensure virtual methods (need dynamic_cast)
63 // provide an Adornable for a given subject to store data in, or throw if none available (default)
64 virtual Adornable
&store(const AclSubject
*subject
);
66 // special-purpose bypass (force validation to succeed)
67 bool forceSuccess
= false;
72 // An AclValidationContext holds all context for an ACL evaluation in one
73 // package. It's designed to provide a uniform representation of credentials, plus
74 // any (trusted path and/or implicit) context information useful for ACL validation.
76 // Contexts are immutable (constant) for validators; they do not change at all
77 // during a validation exercise. Anything that should be mutable must go into
78 // the environment (which is indirect and modifyable).
80 class AclValidationContext
{
81 friend class ObjectAcl
;
83 AclValidationContext(const AccessCredentials
*cred
,
84 AclAuthorization auth
, AclValidationEnvironment
*env
= NULL
)
85 : mAcl((ObjectAcl
*) 0xDEADDEADDEADDEAD), mSubject((AclSubject
*) 0xDEADDEADDEADDEAD), mCred(cred
),
86 mAuth(auth
), mEnv(env
), mEntryTag(NULL
) { }
87 AclValidationContext(const AclValidationContext
&ctx
)
88 : mAcl(ctx
.mAcl
), mSubject(ctx
.mSubject
), mCred(ctx
.mCred
),
89 mAuth(ctx
.mAuth
), mEnv(ctx
.mEnv
), mEntryTag(NULL
) { }
90 virtual ~AclValidationContext();
92 // access to (suitably focused) sample set
93 virtual uint32
count() const = 0; // number of samples
94 uint32
size() const { return count(); } // alias
95 virtual const TypedList
&sample(uint32 n
) const = 0; // retrieve one sample
96 const TypedList
&operator [] (uint32 n
) const { return sample(n
); }
99 AclAuthorization
authorization() const { return mAuth
; }
100 const AccessCredentials
*cred() const { return mCred
; }
101 AclValidationEnvironment
*environment() const { return mEnv
; }
102 template <class Env
> Env
*environment() const { return dynamic_cast<Env
*>(mEnv
); }
103 AclSubject
*subject() const { return mSubject
; }
104 ObjectAcl
*acl() const { return mAcl
; }
107 virtual const char *credTag() const;
108 virtual const char *entryTag() const;
109 std::string
s_credTag() const;
110 void entryTag(const char *tag
);
111 void entryTag(const std::string
&tag
);
113 // selective match support - not currently implemented
114 virtual void matched(const TypedList
*match
) const = 0;
115 void matched(const TypedList
&match
) const { return matched(&match
); }
118 void init(ObjectAcl
*acl
, AclSubject
*subject
);
121 ObjectAcl
*mAcl
; // underlying ObjectAcl
122 AclSubject
*mSubject
; // subject being validated
123 const AccessCredentials
*mCred
; // original credentials
124 AclAuthorization mAuth
; // action requested
125 AclValidationEnvironment
*mEnv
; // environmental context (if any)
126 const char *mEntryTag
; // entry tag
131 // An AclValidationContext that simply presents all top-level credentials
134 class BaseValidationContext
: public AclValidationContext
{
136 BaseValidationContext(const AccessCredentials
*cred
,
137 AclAuthorization auth
, AclValidationEnvironment
*env
)
138 : AclValidationContext(cred
, auth
, env
) { }
140 uint32
count() const { return cred() ? cred()->samples().length() : 0; }
141 uint32
size() const { return count(); }
142 const TypedList
&sample(uint32 n
) const
143 { assert(n
< count()); return cred()->samples()[n
]; }
145 void matched(const TypedList
*) const { } // ignore match info
150 // The AclSubject class models an ACL "subject" object. If you have a new ACL
151 // subject type or variant, you make a subclass of this (plus a suitable Maker).
153 // Note that AclSubjects can contain both configuration and state information.
154 // Configuration is set during AclSubject creation (passwords to check against,
155 // evaluation options, etc.) and are typically passed on in the externalized form;
157 // On the other hand, state is volatile and is lost when the AclSubject dies.
158 // This is stuff that accumulates during a particular lifetime, such as results
159 // of previous evaluations (for caching or more nefarious purposes).
160 // Be clear what each of your subclass members are, and document accordingly.
162 class AclSubject
: public RefCount
{
164 typedef LowLevelMemoryUtilities::Writer Writer
;
165 typedef LowLevelMemoryUtilities::Reader Reader
;
167 typedef uint8 Version
; // binary version marker
168 static const int versionShift
= 24; // highest-order byte of type is version
169 static const uint32 versionMask
= 0xff000000;
172 explicit AclSubject(uint32 type
, Version v
= 0);
173 virtual ~AclSubject();
174 CSSM_ACL_SUBJECT_TYPE
type() const { return mType
; }
176 // validation (evaluation) primitive
177 virtual bool validates(const AclValidationContext
&ctx
) const = 0;
179 // export to CSSM interface
180 virtual CssmList
toList(Allocator
&alloc
) const = 0;
182 // export/import for save/restore interface
183 virtual void exportBlob(Writer::Counter
&pub
, Writer::Counter
&priv
);
184 virtual void exportBlob(Writer
&pub
, Writer
&priv
);
185 virtual void importBlob(Reader
&pub
, Reader
&priv
);
187 // binary compatibility version management. The version defaults to zero
188 Version
version() const { return mVersion
; }
190 // forget any validation-related state you have acquired
191 virtual void reset();
193 // debug suupport (dummied out but present for -UDEBUGDUMP)
194 virtual void debugDump() const;
195 IFDUMP(void dump(const char *title
) const);
198 void version(Version v
) { mVersion
= v
; }
201 CSSM_ACL_SUBJECT_TYPE mType
;
207 Maker(CSSM_ACL_SUBJECT_TYPE type
);
210 uint32
type() const { return mType
; }
211 virtual AclSubject
*make(const TypedList
&list
) const = 0;
212 virtual AclSubject
*make(Version version
, Reader
&pub
, Reader
&priv
) const = 0;
215 // list parsing helpers
216 static void crack(const CssmList
&list
, uint32 count
,
217 ListElement
**array
= NULL
, ...);
218 static CSSM_WORDID_TYPE
getWord(const ListElement
&list
,
219 int min
= 0, int max
= INT_MAX
);
222 CSSM_ACL_SUBJECT_TYPE mType
;
228 // A SimpleAclSubject validates a credential by scanning its samples
229 // one at a time, without any interactions between them. Thus its validate()
230 // can be a lot simpler.
231 // Note that this layer assumes that subject and sample types have the same
232 // value, as is typical when both are derived from a WORDID.
234 class SimpleAclSubject
: public AclSubject
{
236 SimpleAclSubject(CSSM_ACL_SUBJECT_TYPE type
) : AclSubject(type
) { }
238 virtual bool validates(const AclValidationContext
&ctx
) const;
239 virtual bool validates(const AclValidationContext
&baseCtx
,
240 const TypedList
&sample
) const = 0;
244 } // end namespace Security