X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_cdsa_utilities/lib/objectacl.h diff --git a/Security/libsecurity_cdsa_utilities/lib/objectacl.h b/Security/libsecurity_cdsa_utilities/lib/objectacl.h new file mode 100644 index 00000000..c1d08253 --- /dev/null +++ b/Security/libsecurity_cdsa_utilities/lib/objectacl.h @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2000-2004,2006,2011-2012,2014 Apple 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@ + */ + + +// +// objectacl - core implementation of an ACL-bearing object +// +#ifndef _OBJECTACL +#define _OBJECTACL + +#include +#include +#include +#include +#include + + +namespace Security { + + +// +// An in-memory ACL object. +// This class implements an ACL-for-a-protected-object. It is complete in that +// it provides full ACL management functionality. You still need to (globally) +// register makers for the ACL subject types you want to use. +// Note that ObjectAcl does no integrity checking. ObjectAcl objects need to be +// protected from hostile access (by e.g. address space separation), and exported +// ACLs need to be protected somehow (by hiding, signing, or whatever works in +// your situation). +// +class ObjectAcl { + friend AclSubject::Maker::Maker(CSSM_ACL_SUBJECT_TYPE); + +public: + typedef RefPointer AclSubjectPointer; + + typedef LowLevelMemoryUtilities::Writer Writer; + typedef LowLevelMemoryUtilities::Reader Reader; + +public: + ObjectAcl(Allocator &alloc); + ObjectAcl(const AclEntryPrototype &proto, Allocator &alloc); + virtual ~ObjectAcl(); + + Allocator &allocator; + + + // + // access control validation (evaluation) + // + + // validate(): succeed or throw exception + void validate(AclAuthorization auth, const AccessCredentials *cred, + AclValidationEnvironment *env = NULL); + void validate(AclValidationContext &ctx); + + // validates(): return true or false (or throw on error) + bool validates(AclAuthorization auth, const AccessCredentials *cred, + AclValidationEnvironment *env = NULL); + bool validates(AclValidationContext &ctx); + + // owner validation (simpler) + void validateOwner(AclAuthorization authorizationHint, const AccessCredentials *cred, + AclValidationEnvironment *env = NULL); + void validateOwner(AclValidationContext &ctx); + + // CSSM-style ACL access operations + // (Gets are not const because underlying implementations usually want them writable) + void cssmGetAcl(const char *tag, uint32 &count, AclEntryInfo * &acls); + void cssmChangeAcl(const AclEdit &edit, const AccessCredentials *cred, + AclValidationEnvironment *env = NULL); + void cssmGetOwner(AclOwnerPrototype &owner); + void cssmChangeOwner(const AclOwnerPrototype &newOwner, const AccessCredentials *cred, + AclValidationEnvironment *env = NULL); + + void cssmSetInitial(const AclEntryPrototype &proto); + void cssmSetInitial(const AclSubjectPointer &subject); + + // Acl I/O (to/from memory blobs) + void exportBlob(CssmData &publicBlob, CssmData &privateBlob); + void importBlob(const void *publicBlob, const void *privateBlob); + + // clear everything from this ACL (return it to un-initialized state) + void clear(); + + // setup hooks (called to delayed-construct the contents before use) - empty defaults + virtual void instantiateAcl(); // called before ACL contents are used by external calls + virtual void changedAcl(); // called after an ACL has been (possibly) changed + + // debug dump support (always there but stubbed out unless DEBUGDUMP) + virtual void debugDump(const char *what = NULL) const; + +public: + class Entry { + public: + AclSubjectPointer subject; // subject representation + bool delegate; // delegation flag + + Entry() { } // make invalid Entry + + void toOwnerInfo(CSSM_ACL_OWNER_PROTOTYPE &info, + Allocator &alloc) const; // encode copy in CSSM format + + virtual bool authorizes(AclAuthorization auth) const = 0; + virtual bool validate(const AclValidationContext &ctx) const = 0; + + template + void exportBlob(Action &pub, Action &priv) + { + Endian del = delegate; pub(del); // 4 bytes delegate flag + exportSubject(subject, pub, priv); // subject itself (polymorphic) + } + void importBlob(Reader &pub, Reader &priv); + + IFDUMP(virtual void debugDump() const); + + private: + void init(const AclSubjectPointer &subject, bool delegate = false); + void init(const TypedList &subject, bool delegate = false) { init(make(subject), delegate); } + + protected: + Entry(const AclEntryPrototype &proto) { init(proto.subject(), proto.delegate()); } + Entry(const AclOwnerPrototype &proto) { init(proto.subject()); } + Entry(const AclSubjectPointer &subject) { init(subject); } + virtual ~Entry(); + }; + + class OwnerEntry : public Entry { + public: + OwnerEntry() { } // invalid OwnerEntry + template + OwnerEntry(const Input &owner) : Entry(owner) { } + + bool authorizes(AclAuthorization auth) const; + bool validate(const AclValidationContext &ctx) const; + }; + + class AclEntry : public Entry { + public: + std::string tag; // entry tag + AclAuthorizationSet authorizations; // set of authorizations + bool authorizesAnything; // has the _ANY authorization tag + //@@@ time range not yet implemented + CSSM_ACL_HANDLE handle; // entry handle + + AclEntry() { } // invalid AclEntry + AclEntry(const AclSubjectPointer &subject); + AclEntry(const AclEntryPrototype &proto); + + void toEntryInfo(CSSM_ACL_ENTRY_PROTOTYPE &info, + Allocator &alloc) const; // encode copy in CSSM format + + bool authorizes(AclAuthorization auth) const; + bool validate(const AclValidationContext &ctx) const; + + template + void exportBlob(Action &pub, Action &priv) + { + Entry::exportBlob(pub, priv); + const char *s = tag.c_str(); pub(s); + uint32 aa = authorizesAnything; pub(aa); + if (!authorizesAnything) { + Endian count = (uint32)authorizations.size(); pub(count); + for (AclAuthorizationSet::iterator it = authorizations.begin(); + it != authorizations.end(); it++) { + Endian auth = *it; pub(auth); + } + } + //@@@ export time range + } + void importBlob(Reader &pub, Reader &priv); + + IFDUMP(void debugDump() const); + }; + +public: + // These helpers deal with transferring one subject from/to reader/writer streams. + // You'd usually only call those from complex subject implementations (e.g. threshold) + template + static void exportSubject(AclSubject *subject, Action &pub, Action &priv) + { + Endian typeAndVersion = subject->type() | subject->version() << AclSubject::versionShift; + pub(typeAndVersion); + subject->exportBlob(pub, priv); + } + static AclSubject *importSubject(Reader &pub, Reader &priv); + +public: + typedef std::multimap EntryMap; + + EntryMap::iterator begin() { return mEntries.begin(); } + EntryMap::iterator end() { return mEntries.end(); } + EntryMap::const_iterator begin() const { return mEntries.begin(); } + EntryMap::const_iterator end() const { return mEntries.end(); } + + unsigned int getRange(const std::string &tag, + pair &range) const; + EntryMap::iterator findEntryHandle(CSSM_ACL_HANDLE handle); + + // construct an AclSubject through the Maker registry (by subject type) + static AclSubject *make(const TypedList &list); // make from CSSM form + static AclSubject *make(uint32 typeAndVersion, + Reader &pub, Reader &priv); // make from export form + +protected: + template + void owner(const Input &input); + void entries(uint32 count, const AclEntryInfo *infos); + +private: + void add(const std::string &tag, const AclEntry &newEntry); + void add(const std::string &tag, AclEntry newEntry, CSSM_ACL_HANDLE handle); + +private: + EntryMap mEntries; // ACL entries indexed by tag + OwnerEntry mOwner; // ACL owner entry + CSSM_ACL_HANDLE mNextHandle; // next unused entry handle value + +private: + typedef map MakerMap; + static ModuleNexus makers; // registered subject Makers + + static AclSubject::Maker &makerFor(CSSM_ACL_SUBJECT_TYPE type); +}; + + +} // end namespace Security + + +#endif //_OBJECTACL