X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_keychain/lib/SecACL.cpp?ds=inline diff --git a/Security/libsecurity_keychain/lib/SecACL.cpp b/Security/libsecurity_keychain/lib/SecACL.cpp new file mode 100644 index 00000000..335c6cf9 --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecACL.cpp @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2002-2004,2011-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@ + */ + +#include +#include +#include +#include + +#include "SecBridge.h" + +// Forward reference +/*! + @function GetACLAuthorizationTagFromString + @abstract Get the CSSM ACL item from the CFString + @param aclStr The String name of the ACL + @result The CSSM ACL value +*/ +sint32 GetACLAuthorizationTagFromString(CFStringRef aclStr); + +CFStringRef GetAuthStringFromACLAuthorizationTag(sint32 tag); + +// +// Local functions +// +static void setApplications(ACL *acl, CFArrayRef applicationList); + +CFTypeID +SecACLGetTypeID(void) +{ + BEGIN_SECAPI + + return gTypes().ACL.typeID; + + END_SECAPI1(_kCFRuntimeNotATypeID) +} + + +/*! + */ +OSStatus SecACLCreateFromSimpleContents(SecAccessRef accessRef, + CFArrayRef applicationList, + CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector, + SecACLRef *newAcl) +{ + BEGIN_SECAPI + SecPointer access = Access::required(accessRef); + SecPointer acl = new ACL(*access, cfString(description), *promptSelector); + if (applicationList) { + // application-list + prompt + acl->form(ACL::appListForm); + setApplications(acl, applicationList); + } else { + // allow-any + acl->form(ACL::allowAllForm); + } + access->add(acl.get()); + Required(newAcl) = acl->handle(); + END_SECAPI +} + +OSStatus SecACLCreateWithSimpleContents(SecAccessRef access, + CFArrayRef applicationList, + CFStringRef description, + SecKeychainPromptSelector promptSelector, + SecACLRef *newAcl) +{ + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector; + cdsaPromptSelector.version = CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION; + cdsaPromptSelector.flags = promptSelector; + return SecACLCreateFromSimpleContents(access, applicationList, description, &cdsaPromptSelector, newAcl); +} + + +/*! + */ +OSStatus SecACLRemove(SecACLRef aclRef) +{ + BEGIN_SECAPI + ACL::required(aclRef)->remove(); + END_SECAPI +} + + +static SecTrustedApplicationRef +convert(const SecPointer &trustedApplication) +{ + return *trustedApplication; +} + +/*! + */ +OSStatus SecACLCopySimpleContents(SecACLRef aclRef, + CFArrayRef *applicationList, + CFStringRef *promptDescription, CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector) +{ + BEGIN_SECAPI + SecPointer acl = ACL::required(aclRef); + switch (acl->form()) { + case ACL::allowAllForm: + Required(applicationList) = NULL; + Required(promptDescription) = + acl->promptDescription().empty() ? NULL + : makeCFString(acl->promptDescription()); + Required(promptSelector) = acl->promptSelector(); + break; + case ACL::appListForm: + Required(applicationList) = + makeCFArray(convert, acl->applications()); + Required(promptDescription) = makeCFString(acl->promptDescription()); + Required(promptSelector) = acl->promptSelector(); + break; + default: + return errSecACLNotSimple; // custom or unknown + } + END_SECAPI +} + +OSStatus SecACLCopyContents(SecACLRef acl, + CFArrayRef *applicationList, + CFStringRef *description, + SecKeychainPromptSelector *promptSelector) +{ + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector; + memset(&cdsaPromptSelector, 0, sizeof(cdsaPromptSelector)); + OSStatus err = errSecSuccess; + + err = SecACLCopySimpleContents(acl, applicationList, description, &cdsaPromptSelector); + *promptSelector = cdsaPromptSelector.flags; + return err; +} + +OSStatus SecACLSetSimpleContents(SecACLRef aclRef, + CFArrayRef applicationList, + CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector) +{ + BEGIN_SECAPI + SecPointer acl = ACL::required(aclRef); + acl->promptDescription() = description ? cfString(description) : ""; + acl->promptSelector() = promptSelector ? *promptSelector : ACL::defaultSelector; + if (applicationList) { + // application-list + prompt + acl->form(ACL::appListForm); + setApplications(acl, applicationList); + } else { + // allow-any + acl->form(ACL::allowAllForm); + } + acl->modify(); + END_SECAPI +} + +OSStatus SecACLSetContents(SecACLRef acl, + CFArrayRef applicationList, + CFStringRef description, + SecKeychainPromptSelector promptSelector) +{ + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector; + cdsaPromptSelector.version = CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION; + cdsaPromptSelector.flags = promptSelector; + return SecACLSetSimpleContents(acl, applicationList, description, &cdsaPromptSelector); +} + +// +// Stuff a CFArray-of-SecTrustedApplications into an ACL object +// +static void setApplications(ACL *acl, CFArrayRef applicationList) +{ + ACL::ApplicationList &appList = acl->applications(); + appList.clear(); + //@@@ should really use STL iterator overlay on CFArray. By hand... + CFIndex count = CFArrayGetCount(applicationList); + for (CFIndex n = 0; n < count; n++) + appList.push_back(TrustedApplication::required( + SecTrustedApplicationRef(CFArrayGetValueAtIndex(applicationList, n)))); +} + + +// +// Set and get the authorization tags of an ACL entry +// +OSStatus SecACLGetAuthorizations(SecACLRef acl, + CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 *tagCount) +{ + BEGIN_SECAPI + AclAuthorizationSet auths = ACL::required(acl)->authorizations(); + if (Required(tagCount) < auths.size()) { // overflow + *tagCount = (uint32)auths.size(); // report size required + CssmError::throwMe(errSecParam); + } + *tagCount = (uint32)auths.size(); + copy(auths.begin(), auths.end(), tags); + END_SECAPI +} + +CFArrayRef SecACLCopyAuthorizations(SecACLRef acl) +{ + CFArrayRef result = NULL; + if (NULL == acl) + { + return result; + } + + AclAuthorizationSet auths = ACL::required(acl)->authorizations(); + uint32 numAuths = (uint32)auths.size(); + + CSSM_ACL_AUTHORIZATION_TAG* tags = new CSSM_ACL_AUTHORIZATION_TAG[numAuths]; + int i; + for (i = 0; i < numAuths; ++i) + { + tags[i] = NULL; + } + + OSStatus err = SecACLGetAuthorizations(acl, tags, &numAuths); + if (errSecSuccess != err) + { + + return result; + } + + CFTypeRef* strings = new CFTypeRef[numAuths]; + for (i = 0; i < numAuths; ++i) + { + strings[i] = NULL; + } + + for (size_t iCnt = 0; iCnt < numAuths; iCnt++) + { + strings[iCnt] = (CFTypeRef)GetAuthStringFromACLAuthorizationTag(tags[iCnt]); + } + + result = CFArrayCreate(kCFAllocatorDefault, (const void **)strings, numAuths, NULL); + + delete[] strings; + delete[] tags; + + return result; + +} + +OSStatus SecACLSetAuthorizations(SecACLRef aclRef, + CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 tagCount) +{ + BEGIN_SECAPI + SecPointer acl = ACL::required(aclRef); + if (acl->isOwner()) // can't change rights of the owner ACL + MacOSError::throwMe(errSecInvalidOwnerEdit); + AclAuthorizationSet &auths = acl->authorizations(); + auths.clear(); + copy(tags, tags + tagCount, insert_iterator(auths, auths.begin())); + acl->modify(); + END_SECAPI +} + +OSStatus SecACLUpdateAuthorizations(SecACLRef acl, CFArrayRef authorizations) +{ + if (NULL == acl || NULL == authorizations) + { + return errSecParam; + } + uint32 tagCount = (uint32)CFArrayGetCount(authorizations); + + size_t tagSize = (tagCount * sizeof(CSSM_ACL_AUTHORIZATION_TAG)); + + CSSM_ACL_AUTHORIZATION_TAG* tags = (CSSM_ACL_AUTHORIZATION_TAG*)malloc(tagSize); + memset(tags, 0, tagSize); + for (uint32 iCnt = 0; iCnt < tagCount; iCnt++) + { + tags[iCnt] = GetACLAuthorizationTagFromString((CFStringRef)CFArrayGetValueAtIndex(authorizations, iCnt)); + } + + OSStatus result = SecACLSetAuthorizations(acl, tags, tagCount); + free(tags); + return result; +}