1/* 2 * Copyright (c) 2000-2004,2006,2011-2012,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// objectacl - core implementation of an ACL-bearing object 27// 28#ifndef _OBJECTACL 29#define _OBJECTACL 30 31#include <security_cdsa_utilities/aclsubject.h> 32#include <security_utilities/globalizer.h> 33#include <map> 34#include <set> 35#include <limits.h> 36 37 38namespace Security { 39 40 41// 42// An in-memory ACL object. 43// This class implements an ACL-for-a-protected-object. It is complete in that 44// it provides full ACL management functionality. You still need to (globally) 45// register makers for the ACL subject types you want to use. 46// Note that ObjectAcl does no integrity checking. ObjectAcl objects need to be 47// protected from hostile access (by e.g. address space separation), and exported 48// ACLs need to be protected somehow (by hiding, signing, or whatever works in 49// your situation). 50// 51class ObjectAcl { 52 friend AclSubject::Maker::Maker(CSSM_ACL_SUBJECT_TYPE); 53 54public: 55 typedef RefPointer<AclSubject> AclSubjectPointer; 56 57 typedef LowLevelMemoryUtilities::Writer Writer; 58 typedef LowLevelMemoryUtilities::Reader Reader; 59 60public: 61 ObjectAcl(Allocator &alloc); 62 ObjectAcl(const AclEntryPrototype &proto, Allocator &alloc); 63 virtual ~ObjectAcl(); 64 65 Allocator &allocator; 66 67 68 // 69 // access control validation (evaluation) 70 // 71 72 // validate(): succeed or throw exception 73 void validate(AclAuthorization auth, const AccessCredentials *cred, 74 AclValidationEnvironment *env = NULL); 75 void validate(AclValidationContext &ctx); 76 77 // validates(): return true or false (or throw on error) 78 bool validates(AclAuthorization auth, const AccessCredentials *cred, 79 AclValidationEnvironment *env = NULL); 80 bool validates(AclValidationContext &ctx); 81 82 // owner validation (simpler) 83 void validateOwner(AclAuthorization authorizationHint, const AccessCredentials *cred, 84 AclValidationEnvironment *env = NULL); 85 void validateOwner(AclValidationContext &ctx); 86 87 // CSSM-style ACL access operations 88 // (Gets are not const because underlying implementations usually want them writable) 89 void cssmGetAcl(const char *tag, uint32 &count, AclEntryInfo * &acls); 90 void cssmChangeAcl(const AclEdit &edit, const AccessCredentials *cred, 91 AclValidationEnvironment *env = NULL); 92 void cssmGetOwner(AclOwnerPrototype &owner); 93 void cssmChangeOwner(const AclOwnerPrototype &newOwner, const AccessCredentials *cred, 94 AclValidationEnvironment *env = NULL); 95 96 void cssmSetInitial(const AclEntryPrototype &proto); 97 void cssmSetInitial(const AclSubjectPointer &subject); 98 99 // Acl I/O (to/from memory blobs) 100 void exportBlob(CssmData &publicBlob, CssmData &privateBlob); 101 void importBlob(const void *publicBlob, const void *privateBlob); 102 103 // clear everything from this ACL (return it to un-initialized state) 104 void clear(); 105 106 // setup hooks (called to delayed-construct the contents before use) - empty defaults 107 virtual void instantiateAcl(); // called before ACL contents are used by external calls 108 virtual void changedAcl(); // called after an ACL has been (possibly) changed 109 110 // debug dump support (always there but stubbed out unless DEBUGDUMP) 111 virtual void debugDump(const char *what = NULL) const; 112 113public: 114 class Entry { 115 public: 116 AclSubjectPointer subject; // subject representation 117 bool delegate; // delegation flag 118 119 Entry() { } // make invalid Entry 120 121 void toOwnerInfo(CSSM_ACL_OWNER_PROTOTYPE &info, 122 Allocator &alloc) const; // encode copy in CSSM format 123 124 virtual bool authorizes(AclAuthorization auth) const = 0; 125 virtual bool validate(const AclValidationContext &ctx) const = 0; 126 127 template <class Action> 128 void exportBlob(Action &pub, Action &priv) 129 { 130 Endian<uint32> del = delegate; pub(del); // 4 bytes delegate flag 131 exportSubject(subject, pub, priv); // subject itself (polymorphic) 132 } 133 void importBlob(Reader &pub, Reader &priv); 134 135 IFDUMP(virtual void debugDump() const); 136 137 private: 138 void init(const AclSubjectPointer &subject, bool delegate = false); 139 void init(const TypedList &subject, bool delegate = false) { init(make(subject), delegate); } 140 141 protected: 142 Entry(const AclEntryPrototype &proto) { init(proto.subject(), proto.delegate()); } 143 Entry(const AclOwnerPrototype &proto) { init(proto.subject()); } 144 Entry(const AclSubjectPointer &subject) { init(subject); } 145 virtual ~Entry(); 146 }; 147 148 class OwnerEntry : public Entry { 149 public: 150 OwnerEntry() { } // invalid OwnerEntry 151 template <class Input> 152 OwnerEntry(const Input &owner) : Entry(owner) { } 153 154 bool authorizes(AclAuthorization auth) const; 155 bool validate(const AclValidationContext &ctx) const; 156 }; 157 158 class AclEntry : public Entry { 159 public: 160 std::string tag; // entry tag 161 AclAuthorizationSet authorizations; // set of authorizations 162 bool authorizesAnything; // has the _ANY authorization tag 163 //@@@ time range not yet implemented 164 CSSM_ACL_HANDLE handle; // entry handle 165 166 AclEntry() { } // invalid AclEntry 167 AclEntry(const AclSubjectPointer &subject); 168 AclEntry(const AclEntryPrototype &proto); 169 170 void toEntryInfo(CSSM_ACL_ENTRY_PROTOTYPE &info, 171 Allocator &alloc) const; // encode copy in CSSM format 172 173 bool authorizes(AclAuthorization auth) const; 174 bool validate(const AclValidationContext &ctx) const; 175 176 template <class Action> 177 void exportBlob(Action &pub, Action &priv) 178 { 179 Entry::exportBlob(pub, priv); 180 const char *s = tag.c_str(); pub(s); 181 uint32 aa = authorizesAnything; pub(aa); 182 if (!authorizesAnything) { 183 Endian<uint32> count = (uint32)authorizations.size(); pub(count); 184 for (AclAuthorizationSet::iterator it = authorizations.begin(); 185 it != authorizations.end(); it++) { 186 Endian<AclAuthorization> auth = *it; pub(auth); 187 } 188 } 189 //@@@ export time range 190 } 191 void importBlob(Reader &pub, Reader &priv); 192 193 IFDUMP(void debugDump() const); 194 }; 195 196public: 197 // These helpers deal with transferring one subject from/to reader/writer streams. 198 // You'd usually only call those from complex subject implementations (e.g. threshold) 199 template <class Action> 200 static void exportSubject(AclSubject *subject, Action &pub, Action &priv) 201 { 202 Endian<uint32> typeAndVersion = subject->type() | subject->version() << AclSubject::versionShift; 203 pub(typeAndVersion); 204 subject->exportBlob(pub, priv); 205 } 206 static AclSubject *importSubject(Reader &pub, Reader &priv); 207 208public: 209 typedef std::multimap<string, AclEntry> EntryMap; 210 211 EntryMap::iterator begin() { return mEntries.begin(); } 212 EntryMap::iterator end() { return mEntries.end(); } 213 EntryMap::const_iterator begin() const { return mEntries.begin(); } 214 EntryMap::const_iterator end() const { return mEntries.end(); } 215 216 unsigned int getRange(const std::string &tag, 217 pair<EntryMap::const_iterator, EntryMap::const_iterator> &range) const; 218 EntryMap::iterator findEntryHandle(CSSM_ACL_HANDLE handle); 219 220 // construct an AclSubject through the Maker registry (by subject type) 221 static AclSubject *make(const TypedList &list); // make from CSSM form 222 static AclSubject *make(uint32 typeAndVersion, 223 Reader &pub, Reader &priv); // make from export form 224 225protected: 226 template <class Input> 227 void owner(const Input &input); 228 void entries(uint32 count, const AclEntryInfo *infos); 229 230private: 231 void add(const std::string &tag, const AclEntry &newEntry); 232 void add(const std::string &tag, AclEntry newEntry, CSSM_ACL_HANDLE handle); 233 234private: 235 EntryMap mEntries; // ACL entries indexed by tag 236 OwnerEntry mOwner; // ACL owner entry 237 CSSM_ACL_HANDLE mNextHandle; // next unused entry handle value 238 239private: 240 typedef map<CSSM_ACL_SUBJECT_TYPE, AclSubject::Maker *> MakerMap; 241 static ModuleNexus<MakerMap> makers; // registered subject Makers 242 243 static AclSubject::Maker &makerFor(CSSM_ACL_SUBJECT_TYPE type); 244}; 245 246 247} // end namespace Security 248 249 250#endif //_OBJECTACL 251