]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_cdsa_utilities/lib/objectacl.h
Security-57031.1.35.tar.gz
[apple/security.git] / 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 (file)
index 0000000..c1d0825
--- /dev/null
@@ -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 <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