X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp new file mode 100644 index 00000000..96a32b50 --- /dev/null +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2000-2004,2006-2007,2011-2012 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@ + */ + + +// +// cssmaclpod - enhanced PodWrappers for ACL-related CSSM data structures +// +#include +#include +#include + + +namespace Security { + + +// +// AclAuthorizationSets +// +AclAuthorizationSet::AclAuthorizationSet(AclAuthorization auth0, AclAuthorization auth, ...) +{ + insert(auth0); + + va_list args; + va_start(args, auth); + while (auth) { + insert(auth); + auth = va_arg(args, AclAuthorization); + } + va_end(args); +} + + +// +// AclAuthorizationGroups +// +AuthorizationGroup::AuthorizationGroup(const AclAuthorizationSet &auths, Allocator &alloc) +{ + NumberOfAuthTags = (uint32)auths.size(); + AuthTags = alloc.alloc(NumberOfAuthTags); + copy(auths.begin(), auths.end(), AuthTags); // happens to be sorted +} + +AuthorizationGroup::AuthorizationGroup(CSSM_ACL_AUTHORIZATION_TAG tag, Allocator &alloc) +{ + AuthTags = alloc.alloc(1); + AuthTags[0] = tag; + NumberOfAuthTags = 1; +} + +void AuthorizationGroup::destroy(Allocator &alloc) +{ + alloc.free(AuthTags); +} + +bool AuthorizationGroup::contains(CSSM_ACL_AUTHORIZATION_TAG tag) const +{ + return find(AuthTags, &AuthTags[NumberOfAuthTags], tag) != &AuthTags[NumberOfAuthTags]; +} + + +AuthorizationGroup::operator AclAuthorizationSet() const +{ + return AclAuthorizationSet(AuthTags, &AuthTags[NumberOfAuthTags]); +} + +AclEntryPrototype::AclEntryPrototype(const AclOwnerPrototype &proto) +{ + memset(this, 0, sizeof(*this)); + TypedSubject = proto.subject(); Delegate = proto.delegate(); + //@@@ set authorization to "is owner" pseudo-auth? See cssmacl.h +} + +void AclEntryPrototype::tag(const char *tagString) +{ + if (tagString == NULL) + EntryTag[0] = '\0'; + else if (strlen(tagString) > CSSM_MODULE_STRING_SIZE) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_ENTRY_TAG); + else + strcpy(EntryTag, tagString); +} + +void AclEntryPrototype::tag(const string &tagString) +{ + if (tagString.length() > CSSM_MODULE_STRING_SIZE) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_ENTRY_TAG); + else + memcpy(EntryTag, tagString.c_str(), tagString.length() + 1); +} + + +AclOwnerPrototype *AutoAclOwnerPrototype::make() +{ + if (!mAclOwnerPrototype) { + mAclOwnerPrototype = (AclOwnerPrototype*) mAllocator->malloc(sizeof(AclOwnerPrototype)); + new (mAclOwnerPrototype) AclOwnerPrototype; + mAclOwnerPrototype->clearPod(); + } + return mAclOwnerPrototype; +} + +AutoAclOwnerPrototype::~AutoAclOwnerPrototype() +{ + if (mAllocator) + DataWalkers::chunkFree(mAclOwnerPrototype, *mAllocator); +} + +void +AutoAclOwnerPrototype::allocator(Allocator &allocator) +{ + mAllocator = &allocator; +} + + +void AutoAclEntryInfoList::size(uint32 newSize) +{ + assert(mAllocator); + mEntries = mAllocator->alloc(mEntries, newSize); + for (uint32 n = mCount; n < newSize; n++) + mEntries[n].clearPod(); + mCount = newSize; +} + + +AclEntryInfo &AutoAclEntryInfoList::at(uint32 ix) +{ + if (ix >= mCount) + size(ix + 1); // expand vector + return mEntries[ix]; +} + + +void AutoAclEntryInfoList::clear() +{ + if (mAllocator) + { + DataWalkers::ChunkFreeWalker w(*mAllocator); + for (uint32 ix = 0; ix < mCount; ix++) + walk(w, mEntries[ix]); + mAllocator->free(mEntries); + mEntries = NULL; + mCount = 0; + } +} + +void AutoAclEntryInfoList::allocator(Allocator &allocator) +{ + mAllocator = &allocator; +} + + +void AutoAclEntryInfoList::add(const TypedList &subj, const AclAuthorizationSet &auths, const char *tag /* = NULL */) +{ + AclEntryInfo &info = at(size()); + info.proto() = AclEntryPrototype(subj); + info.proto().authorization() = AuthorizationGroup(auths, allocator()); + info.proto().tag(tag); + info.handle(size()); +} + +void AutoAclEntryInfoList::addPin(const TypedList &subj, uint32 slot) +{ + char tag[20]; + snprintf(tag, sizeof(tag), "PIN%d", slot); + add(subj, CSSM_ACL_AUTHORIZATION_PREAUTH(slot), tag); +} + +void AutoAclEntryInfoList::addPinState(uint32 slot, uint32 status) +{ + char tag[20]; + snprintf(tag, sizeof(tag), "PIN%d?", slot); + TypedList subj(allocator(), CSSM_WORDID_PIN, + new(allocator()) ListElement(slot), + new(allocator()) ListElement(status)); + add(subj, CSSM_WORDID_PIN, tag); +} + +void AutoAclEntryInfoList::addPinState(uint32 slot, uint32 status, uint32 count) +{ + char tag[20]; + snprintf(tag, sizeof(tag), "PIN%d?", slot); + TypedList subj(allocator(), CSSM_WORDID_PIN, + new(allocator()) ListElement(slot), + new(allocator()) ListElement(status), + new(allocator()) ListElement(count)); + add(subj, CSSM_WORDID_PIN, tag); +} + +uint32 pinFromAclTag(const char *tag, const char *suffix /* = NULL */) +{ + if (tag) { + char format[20]; + snprintf(format, sizeof(format), "PIN%%d%s%%n", suffix ? suffix : ""); + uint32 pin; + unsigned consumed; + sscanf(tag, format, &pin, &consumed); + if (consumed == strlen(tag)) // complete and sufficient + return pin; + } + return 0; +} + +} // namespace Security