1/* 2 * Copyright (c) 2000-2007,2011 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// cssmaclpod - enhanced PodWrappers for ACL-related CSSM data structures 27// 28#ifndef _CSSMACLPOD 29#define _CSSMACLPOD 30 31#include <security_utilities/utilities.h> 32#include <security_cdsa_utilities/cssmlist.h> 33#include <security_cdsa_utilities/cssmalloc.h> 34 35namespace Security { 36 37// a nicer name for an authorization tag 38typedef CSSM_ACL_AUTHORIZATION_TAG AclAuthorization; 39 40 41// 42// An STL set of authorization tags, with some convenience features 43// 44class AclAuthorizationSet : public std::set<AclAuthorization> { 45public: 46 AclAuthorizationSet() { } 47 AclAuthorizationSet(AclAuthorization auth) { insert(auth); } 48 AclAuthorizationSet(AclAuthorization *authBegin, AclAuthorization *authEnd) 49 : set<AclAuthorization>(authBegin, authEnd) { } 50 AclAuthorizationSet(AclAuthorization a1, AclAuthorization a2, ...); // list of auths, end with zero 51}; 52 53 54// 55// Enhanced POD Wrappers for the public ACL-related CSSM structures 56// 57class AuthorizationGroup : public PodWrapper<AuthorizationGroup, CSSM_AUTHORIZATIONGROUP> { 58public: 59 AuthorizationGroup() { NumberOfAuthTags = 0; } 60 AuthorizationGroup(const AclAuthorizationSet &, Allocator &alloc); 61 AuthorizationGroup(AclAuthorization tag, Allocator &alloc); 62 void destroy(Allocator &alloc); 63 64 bool empty() const { return NumberOfAuthTags == 0; } 65 unsigned int size() const { return NumberOfAuthTags; } 66 unsigned int count() const { return NumberOfAuthTags; } 67 CSSM_ACL_AUTHORIZATION_TAG operator [] (unsigned ix) const 68 { assert(ix < size()); return AuthTags[ix]; } 69 70 bool contains(CSSM_ACL_AUTHORIZATION_TAG tag) const; 71 operator AclAuthorizationSet () const; 72}; 73 74class AclOwnerPrototype; 75 76class AclEntryPrototype : public PodWrapper<AclEntryPrototype, CSSM_ACL_ENTRY_PROTOTYPE> { 77public: 78 AclEntryPrototype() { clearPod(); } 79 explicit AclEntryPrototype(const AclOwnerPrototype &proto); 80 AclEntryPrototype(const CSSM_LIST &subj, bool delegate = false) 81 { clearPod(); TypedSubject = subj; Delegate = delegate; } 82 83 TypedList &subject() { return TypedList::overlay(TypedSubject); } 84 const TypedList &subject() const { return TypedList::overlay(TypedSubject); } 85 86 bool delegate() const { return Delegate; } 87 void delegate(bool d) { Delegate = d; } 88 89 char *tag() { return EntryTag[0] ? EntryTag : NULL; } 90 void tag(const char *tagString); 91 void tag(const std::string &tagString); 92 const char *tag() const { return EntryTag[0] ? EntryTag : NULL; } 93 std::string s_tag() const { return EntryTag; } 94 95 AuthorizationGroup &authorization() { return AuthorizationGroup::overlay(Authorization); } 96 const AuthorizationGroup &authorization() const 97 { return AuthorizationGroup::overlay(Authorization); } 98}; 99 100class AclOwnerPrototype : public PodWrapper<AclOwnerPrototype, CSSM_ACL_OWNER_PROTOTYPE> { 101public: 102 AclOwnerPrototype() { clearPod(); } 103 explicit AclOwnerPrototype(const AclEntryPrototype &proto) 104 { TypedSubject = proto.subject(); delegate(proto.delegate()); } 105 AclOwnerPrototype(const CSSM_LIST &subj, bool del = false) 106 { TypedSubject = subj; delegate(del); } 107 108 TypedList &subject() { return TypedList::overlay(TypedSubject); } 109 const TypedList &subject() const { return TypedList::overlay(TypedSubject); } 110 bool delegate() const { return Delegate; } 111 void delegate(bool d) { Delegate = d; } 112}; 113 114class AclEntryInfo : public PodWrapper<AclEntryInfo, CSSM_ACL_ENTRY_INFO> { 115public: 116 AclEntryInfo() { clearPod(); } 117 AclEntryInfo(const AclEntryPrototype &prot, CSSM_ACL_HANDLE h = 0) 118 { proto() = prot; handle() = h; } 119 120 AclEntryPrototype &proto() { return AclEntryPrototype::overlay(EntryPublicInfo); } 121 const AclEntryPrototype &proto() const 122 { return AclEntryPrototype::overlay(EntryPublicInfo); } 123 124 operator AclEntryPrototype &() { return proto(); } 125 operator const AclEntryPrototype &() const { return proto(); } 126 127 CSSM_ACL_HANDLE &handle() { return EntryHandle; } 128 const CSSM_ACL_HANDLE &handle() const { return EntryHandle; } 129 void handle(CSSM_ACL_HANDLE h) { EntryHandle = h; } 130}; 131 132class AclEntryInput : public PodWrapper<AclEntryInput, CSSM_ACL_ENTRY_INPUT> { 133public: 134 AclEntryInput() { clearPod(); } 135 AclEntryInput(const CSSM_ACL_ENTRY_PROTOTYPE &prot) 136 { Prototype = prot; Callback = NULL; CallerContext = NULL; } 137 138 AclEntryInput &operator = (const CSSM_ACL_ENTRY_PROTOTYPE &prot) 139 { Prototype = prot; Callback = NULL; CallerContext = NULL; return *this; } 140 141 AclEntryPrototype &proto() { return AclEntryPrototype::overlay(Prototype); } 142 const AclEntryPrototype &proto() const { return AclEntryPrototype::overlay(Prototype); } 143 //@@@ not supporting callback features (yet) 144}; 145 146class AclEdit : public PodWrapper<AclEdit, CSSM_ACL_EDIT> { 147public: 148 AclEdit(CSSM_ACL_EDIT_MODE m, CSSM_ACL_HANDLE h, const AclEntryInput *data) 149 { EditMode = m; OldEntryHandle = h; NewEntry = data; } 150 AclEdit(const AclEntryInput &add) 151 { EditMode = CSSM_ACL_EDIT_MODE_ADD; OldEntryHandle = CSSM_INVALID_HANDLE; NewEntry = &add; } 152 AclEdit(CSSM_ACL_HANDLE h, const AclEntryInput &modify) 153 { EditMode = CSSM_ACL_EDIT_MODE_REPLACE; OldEntryHandle = h; NewEntry = &modify; } 154 AclEdit(CSSM_ACL_HANDLE h) 155 { EditMode = CSSM_ACL_EDIT_MODE_DELETE; OldEntryHandle = h; NewEntry = NULL; } 156 157 CSSM_ACL_EDIT_MODE mode() const { return EditMode; } 158 CSSM_ACL_HANDLE handle() const { return OldEntryHandle; } 159 const AclEntryInput *newEntry() const { return AclEntryInput::overlay(NewEntry); } 160}; 161 162 163// 164// Allocating versions of Acl structures 165// 166class AutoAclOwnerPrototype { 167 NOCOPY(AutoAclOwnerPrototype) 168public: 169 // allocator can be set after construction 170 AutoAclOwnerPrototype(Allocator *allocator = NULL) 171 : mAclOwnerPrototype(NULL), mAllocator(allocator) { } 172 ~AutoAclOwnerPrototype(); 173 174 operator bool () const { return mAllocator; } 175 bool operator ! () const { return !mAllocator; } 176 177 operator AclOwnerPrototype * () { return make(); } 178 operator AclOwnerPrototype & () { return *make(); } 179 AclOwnerPrototype &operator * () { return *make(); } 180 181 TypedList &subject() { return make()->subject(); } 182 TypedList &subject() const 183 { assert(mAclOwnerPrototype); return mAclOwnerPrototype->subject(); } 184 bool delegate() const 185 { assert(mAclOwnerPrototype); return mAclOwnerPrototype->delegate(); } 186 void delegate(bool d) { make()->delegate(d); } 187 188 void allocator(Allocator &allocator); 189 Allocator &allocator() const { assert(mAllocator); return *mAllocator; } 190 191 AclOwnerPrototype &operator = (const TypedList &subj) 192 { make()->subject() = subj; make()->delegate(false); return *mAclOwnerPrototype; } 193 194 const AclOwnerPrototype *release() 195 { AclOwnerPrototype *r = mAclOwnerPrototype; mAclOwnerPrototype = NULL; return r; } 196 197private: 198 AclOwnerPrototype *mAclOwnerPrototype; 199 Allocator *mAllocator; 200 201 AclOwnerPrototype *make(); 202}; 203 204 205class AutoAclEntryInfoList { 206 NOCOPY(AutoAclEntryInfoList) 207public: 208 // allocator can be set after construction 209 AutoAclEntryInfoList(Allocator *allocator = NULL) 210 : mEntries(NULL), mCount(0), mAllocator(allocator) { } 211 ~AutoAclEntryInfoList() { clear(); } 212 213 operator bool () const { return mAllocator; } 214 bool operator ! () const { return !mAllocator; } 215 operator uint32 *() { return &mCount; } 216 operator CSSM_ACL_ENTRY_INFO ** () { return reinterpret_cast<CSSM_ACL_ENTRY_INFO **>(&mEntries); } 217 218 void allocator(Allocator &allocator); 219 Allocator &allocator() const { assert(mAllocator); return *mAllocator; } 220 221 const AclEntryInfo &at(uint32 ix) const 222 { assert(ix < mCount); return mEntries[ix]; } 223 const AclEntryInfo &operator [] (uint32 ix) const { return at(ix); } 224 AclEntryInfo &at(uint32 ix); 225 AclEntryInfo &operator[] (uint32 ix) { return at(ix); } 226 227 uint32 size() const { return mCount; } 228 uint32 count() const { return mCount; } 229 AclEntryInfo *entries() const { return mEntries; } 230 231 void clear(); 232 void size(uint32 newSize); 233 234 // structured adders. Inputs must be chunk-allocated with our Allocator 235 void add(const TypedList &subj, const AclAuthorizationSet &auths, const char *tag = NULL); 236 void addPin(const TypedList &subj, uint32 slot); 237 void addPinState(uint32 slot, uint32 state); 238 void addPinState(uint32 slot, uint32 state, uint32 count); 239 240 void release() { mAllocator = NULL; } 241 242private: 243 AclEntryInfo *mEntries; 244 uint32 mCount; 245 Allocator *mAllocator; 246}; 247 248// 249// Extract the pin number from a "PIN%d?" tag. 250// Returns 0 if the tag isn't of that form. 251// 252uint32 pinFromAclTag(const char *tag, const char *suffix = NULL); 253 254 255class AutoAuthorizationGroup : public AuthorizationGroup { 256public: 257 AutoAuthorizationGroup(Allocator &alloc) : allocator(alloc) { } 258 explicit AutoAuthorizationGroup(const AclAuthorizationSet &set, 259 Allocator &alloc) : AuthorizationGroup(set, alloc), allocator(alloc) { } 260 ~AutoAuthorizationGroup() { destroy(allocator); } 261 262 Allocator &allocator; 263}; 264 265 266// 267// Walkers for the CSSM API structure types 268// 269namespace DataWalkers { 270 271// AclEntryInput 272template <class Action> 273AclEntryInput *walk(Action &operate, AclEntryInput * &input) 274{ 275 operate(input); 276 walk(operate, input->proto()); 277 return input; 278} 279 280template <class Action> 281void walk(Action &operate, AclEntryInput &input) 282{ 283 operate(input); 284 walk(operate, input.proto()); 285} 286 287// AclEntryInfo 288template <class Action> 289void walk(Action &operate, AclEntryInfo &info) 290{ 291 operate(info); 292 walk(operate, info.proto()); 293} 294 295// AuthorizationGroup 296template <class Action> 297void walk(Action &operate, AuthorizationGroup &auth) 298{ 299 operate(auth); 300 uint32 count = auth.count(); 301 operate.blob(auth.AuthTags, count * sizeof(auth.AuthTags[0])); 302 for (uint32 n = 0; n < count; n++) 303 operate(auth.AuthTags[n]); 304} 305 306template <class Action> 307void walk(Action &operate, CSSM_AUTHORIZATIONGROUP &auth) 308{ walk(operate, static_cast<CSSM_AUTHORIZATIONGROUP &>(auth)); } 309 310// AclEntryPrototype 311template <class Action> 312void enumerate(Action &operate, AclEntryPrototype &proto) 313{ 314 walk(operate, proto.subject()); 315 walk(operate, proto.authorization()); 316 //@@@ ignoring validity period 317} 318 319template <class Action> 320void walk(Action &operate, AclEntryPrototype &proto) 321{ 322 operate(proto); 323 enumerate(operate, proto); 324} 325 326template <class Action> 327AclEntryPrototype *walk(Action &operate, AclEntryPrototype * &proto) 328{ 329 operate(proto); 330 enumerate(operate, *proto); 331 return proto; 332} 333 334// AclOwnerPrototype 335template <class Action> 336void walk(Action &operate, AclOwnerPrototype &proto) 337{ 338 operate(proto); 339 walk(operate, proto.subject()); 340} 341 342template <class Action> 343AclOwnerPrototype *walk(Action &operate, AclOwnerPrototype * &proto) 344{ 345 operate(proto); 346 walk(operate, proto->subject()); 347 return proto; 348} 349 350 351} // end namespace DataWalkers 352 353} // end namespace Security 354 355 356#endif //_CSSMACLPOD 357