--- /dev/null
+/*
+ * 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 <security_cdsa_utilities/aclsubject.h>
+#include <security_utilities/globalizer.h>
+#include <map>
+#include <set>
+#include <limits.h>
+
+
+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<AclSubject> 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 <class Action>
+ void exportBlob(Action &pub, Action &priv)
+ {
+ Endian<uint32> 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 <class Input>
+ 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 <class Action>
+ 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<uint32> count = (uint32)authorizations.size(); pub(count);
+ for (AclAuthorizationSet::iterator it = authorizations.begin();
+ it != authorizations.end(); it++) {
+ Endian<AclAuthorization> 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 <class Action>
+ static void exportSubject(AclSubject *subject, Action &pub, Action &priv)
+ {
+ Endian<uint32> typeAndVersion = subject->type() | subject->version() << AclSubject::versionShift;
+ pub(typeAndVersion);
+ subject->exportBlob(pub, priv);
+ }
+ static AclSubject *importSubject(Reader &pub, Reader &priv);
+
+public:
+ typedef std::multimap<string, AclEntry> 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<EntryMap::const_iterator, EntryMap::const_iterator> &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 <class Input>
+ 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<CSSM_ACL_SUBJECT_TYPE, AclSubject::Maker *> MakerMap;
+ static ModuleNexus<MakerMap> makers; // registered subject Makers
+
+ static AclSubject::Maker &makerFor(CSSM_ACL_SUBJECT_TYPE type);
+};
+
+
+} // end namespace Security
+
+
+#endif //_OBJECTACL