X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/72a12576750f52947eb043106ba5c12c0d07decf..b1ab9ed8d0e0f1c3b66d7daa8fd5564444c56195:/libsecurity_cdsa_utilities/lib/aclsubject.h diff --git a/libsecurity_cdsa_utilities/lib/aclsubject.h b/libsecurity_cdsa_utilities/lib/aclsubject.h new file mode 100644 index 00000000..b62e3325 --- /dev/null +++ b/libsecurity_cdsa_utilities/lib/aclsubject.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// +// aclsubject - abstract ACL subject implementation +// +#ifndef _ACLSUBJECT +#define _ACLSUBJECT + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace Security { + +class ObjectAcl; +class AclValidationContext; +class AclSubject; + + +// +// An AclValidationEnvironment can be subclassed to add context access to ACL subject +// validation. If you use ACL subject classes that need context beyond the credential +// structure itself, add that context to (a virtual subclass of) AclValidationContext, pass that +// to ObjectAcl::validate() along with the credentials, and have the Subject implementation +// access validationContext.environment(). +// +class AclValidationEnvironment { + friend class AclValidationContext; +public: + virtual ~AclValidationEnvironment(); // ensure virtual methods (need dynamic_cast) + + // provide an Adornable for a given subject to store data in, or throw if none available (default) + virtual Adornable &store(const AclSubject *subject); +}; + + +// +// An AclValidationContext holds all context for an ACL evaluation in one +// package. It's designed to provide a uniform representation of credentials, plus +// any (trusted path and/or implicit) context information useful for ACL validation. +// +// Contexts are immutable (constant) for validators; they do not change at all +// during a validation exercise. Anything that should be mutable must go into +// the environment (which is indirect and modifyable). +// +class AclValidationContext { + friend class ObjectAcl; +public: + AclValidationContext(const AccessCredentials *cred, + AclAuthorization auth, AclValidationEnvironment *env = NULL) + : mCred(cred), mAuth(auth), mEnv(env), mEntryTag(NULL) { } + AclValidationContext(const AclValidationContext &ctx) + : mAcl(ctx.mAcl), mSubject(ctx.mSubject), mCred(ctx.mCred), + mAuth(ctx.mAuth), mEnv(ctx.mEnv), mEntryTag(NULL) { } + virtual ~AclValidationContext(); + + // access to (suitably focused) sample set + virtual uint32 count() const = 0; // number of samples + uint32 size() const { return count(); } // alias + virtual const TypedList &sample(uint32 n) const = 0; // retrieve one sample + const TypedList &operator [] (uint32 n) const { return sample(n); } + + // context access + AclAuthorization authorization() const { return mAuth; } + const AccessCredentials *cred() const { return mCred; } + AclValidationEnvironment *environment() const { return mEnv; } + template Env *environment() const { return dynamic_cast(mEnv); } + AclSubject *subject() const { return mSubject; } + ObjectAcl *acl() const { return mAcl; } + + // tag manipulation + virtual const char *credTag() const; + virtual const char *entryTag() const; + std::string s_credTag() const; + void entryTag(const char *tag); + void entryTag(const std::string &tag); + + // selective match support - not currently implemented + virtual void matched(const TypedList *match) const = 0; + void matched(const TypedList &match) const { return matched(&match); } + +private: + void init(ObjectAcl *acl, AclSubject *subject); + +private: + ObjectAcl *mAcl; // underlying ObjectAcl + AclSubject *mSubject; // subject being validated + const AccessCredentials *mCred; // original credentials + AclAuthorization mAuth; // action requested + AclValidationEnvironment *mEnv; // environmental context (if any) + const char *mEntryTag; // entry tag +}; + + +// +// The AclSubject class models an ACL "subject" object. If you have a new ACL +// subject type or variant, you make a subclass of this (plus a suitable Maker). +// +// Note that AclSubjects can contain both configuration and state information. +// Configuration is set during AclSubject creation (passwords to check against, +// evaluation options, etc.) and are typically passed on in the externalized form; +// it is persistent. +// On the other hand, state is volatile and is lost when the AclSubject dies. +// This is stuff that accumulates during a particular lifetime, such as results +// of previous evaluations (for caching or more nefarious purposes). +// Be clear what each of your subclass members are, and document accordingly. +// +class AclSubject : public RefCount { +public: + typedef LowLevelMemoryUtilities::Writer Writer; + typedef LowLevelMemoryUtilities::Reader Reader; + + typedef uint8 Version; // binary version marker + static const int versionShift = 24; // highest-order byte of type is version + static const uint32 versionMask = 0xff000000; + +public: + explicit AclSubject(uint32 type, Version v = 0); + virtual ~AclSubject(); + CSSM_ACL_SUBJECT_TYPE type() const { return mType; } + + // validation (evaluation) primitive + virtual bool validate(const AclValidationContext &ctx) const = 0; + + // export to CSSM interface + virtual CssmList toList(Allocator &alloc) const = 0; + + // export/import for save/restore interface + virtual void exportBlob(Writer::Counter &pub, Writer::Counter &priv); + virtual void exportBlob(Writer &pub, Writer &priv); + virtual void importBlob(Reader &pub, Reader &priv); + + // binary compatibility version management. The version defaults to zero + Version version() const { return mVersion; } + + // forget any validation-related state you have acquired + virtual void reset(); + + // debug suupport (dummied out but present for -UDEBUGDUMP) + virtual void debugDump() const; + IFDUMP(void dump(const char *title) const); + +protected: + void version(Version v) { mVersion = v; } + +private: + CSSM_ACL_SUBJECT_TYPE mType; + Version mVersion; + +public: + class Maker { + public: + Maker(CSSM_ACL_SUBJECT_TYPE type); + virtual ~Maker(); + + uint32 type() const { return mType; } + virtual AclSubject *make(const TypedList &list) const = 0; + virtual AclSubject *make(Version version, Reader &pub, Reader &priv) const = 0; + + protected: + // list parsing helpers + static void crack(const CssmList &list, uint32 count, + ListElement **array = NULL, ...); + static CSSM_WORDID_TYPE getWord(const ListElement &list, + int min = 0, int max = INT_MAX); + + private: + CSSM_ACL_SUBJECT_TYPE mType; + }; +}; + + +// +// A SimpleAclSubject validates a credential by scanning its samples +// one at a time, without any interactions between them. Thus its validate() +// can be a lot simpler. +// Note that this layer assumes that subject and sample types have the same +// value, as is typical when both are derived from a WORDID. +// +class SimpleAclSubject : public AclSubject { +public: + SimpleAclSubject(CSSM_ACL_SUBJECT_TYPE type) : AclSubject(type) { } + + bool validate(const AclValidationContext &ctx) const; + virtual bool validate(const AclValidationContext &baseCtx, + const TypedList &sample) const = 0; +}; + + +} // end namespace Security + + +#endif //_ACLSUBJECT