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