1/* 2 * Copyright (c) 2002-2004 Apple Computer, 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#include <Security/SecACL.h> 25#include <security_keychain/ACL.h> 26#include <security_keychain/Access.h> 27#include <security_keychain/SecAccessPriv.h> 28 29#include "SecBridge.h" 30 31// Forward reference 32/*! 33 @function GetACLAuthorizationTagFromString 34 @abstract Get the CSSM ACL item from the CFString 35 @param aclStr The String name of the ACL 36 @result The CSSM ACL value 37*/ 38sint32 GetACLAuthorizationTagFromString(CFStringRef aclStr); 39 40CFStringRef GetAuthStringFromACLAuthorizationTag(sint32 tag); 41 42// 43// Local functions 44// 45static void setApplications(ACL *acl, CFArrayRef applicationList); 46 47CFTypeID 48SecACLGetTypeID(void) 49{ 50 BEGIN_SECAPI 51 52 return gTypes().ACL.typeID; 53 54 END_SECAPI1(_kCFRuntimeNotATypeID) 55} 56 57 58/*! 59 */ 60OSStatus SecACLCreateFromSimpleContents(SecAccessRef accessRef, 61 CFArrayRef applicationList, 62 CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector, 63 SecACLRef *newAcl) 64{ 65 BEGIN_SECAPI 66 SecPointer<Access> access = Access::required(accessRef); 67 SecPointer<ACL> acl = new ACL(*access, cfString(description), *promptSelector); 68 if (applicationList) { 69 // application-list + prompt 70 acl->form(ACL::appListForm); 71 setApplications(acl, applicationList); 72 } else { 73 // allow-any 74 acl->form(ACL::allowAllForm); 75 } 76 access->add(acl.get()); 77 Required(newAcl) = acl->handle(); 78 END_SECAPI 79} 80 81OSStatus SecACLCreateWithSimpleContents(SecAccessRef access, 82 CFArrayRef applicationList, 83 CFStringRef description, 84 SecKeychainPromptSelector promptSelector, 85 SecACLRef *newAcl) 86{ 87 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector; 88 cdsaPromptSelector.version = CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION; 89 cdsaPromptSelector.flags = promptSelector; 90 return SecACLCreateFromSimpleContents(access, applicationList, description, &cdsaPromptSelector, newAcl); 91} 92 93 94/*! 95 */ 96OSStatus SecACLRemove(SecACLRef aclRef) 97{ 98 BEGIN_SECAPI 99 ACL::required(aclRef)->remove(); 100 END_SECAPI 101} 102 103 104static SecTrustedApplicationRef 105convert(const SecPointer<TrustedApplication> &trustedApplication) 106{ 107 return *trustedApplication; 108} 109 110/*! 111 */ 112OSStatus SecACLCopySimpleContents(SecACLRef aclRef, 113 CFArrayRef *applicationList, 114 CFStringRef *promptDescription, CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector) 115{ 116 BEGIN_SECAPI 117 SecPointer<ACL> acl = ACL::required(aclRef); 118 switch (acl->form()) { 119 case ACL::allowAllForm: 120 Required(applicationList) = NULL; 121 Required(promptDescription) = 122 acl->promptDescription().empty() ? NULL 123 : makeCFString(acl->promptDescription()); 124 Required(promptSelector) = acl->promptSelector(); 125 break; 126 case ACL::appListForm: 127 Required(applicationList) = 128 makeCFArray(convert, acl->applications()); 129 Required(promptDescription) = makeCFString(acl->promptDescription()); 130 Required(promptSelector) = acl->promptSelector(); 131 break; 132 default: 133 return errSecACLNotSimple; // custom or unknown 134 } 135 END_SECAPI 136} 137 138OSStatus SecACLCopyContents(SecACLRef acl, 139 CFArrayRef *applicationList, 140 CFStringRef *description, 141 SecKeychainPromptSelector *promptSelector) 142{ 143 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector; 144 memset(&cdsaPromptSelector, 0, sizeof(cdsaPromptSelector)); 145 OSStatus err = errSecSuccess; 146 147 err = SecACLCopySimpleContents(acl, applicationList, description, &cdsaPromptSelector); 148 *promptSelector = cdsaPromptSelector.flags; 149 return err; 150} 151 152OSStatus SecACLSetSimpleContents(SecACLRef aclRef, 153 CFArrayRef applicationList, 154 CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector) 155{ 156 BEGIN_SECAPI 157 SecPointer<ACL> acl = ACL::required(aclRef); 158 acl->promptDescription() = description ? cfString(description) : ""; 159 acl->promptSelector() = promptSelector ? *promptSelector : ACL::defaultSelector; 160 if (applicationList) { 161 // application-list + prompt 162 acl->form(ACL::appListForm); 163 setApplications(acl, applicationList); 164 } else { 165 // allow-any 166 acl->form(ACL::allowAllForm); 167 } 168 acl->modify(); 169 END_SECAPI 170} 171 172OSStatus SecACLSetContents(SecACLRef acl, 173 CFArrayRef applicationList, 174 CFStringRef description, 175 SecKeychainPromptSelector promptSelector) 176{ 177 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector; 178 cdsaPromptSelector.version = CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION; 179 cdsaPromptSelector.flags = promptSelector; 180 return SecACLSetSimpleContents(acl, applicationList, description, &cdsaPromptSelector); 181} 182 183// 184// Stuff a CFArray-of-SecTrustedApplications into an ACL object 185// 186static void setApplications(ACL *acl, CFArrayRef applicationList) 187{ 188 ACL::ApplicationList &appList = acl->applications(); 189 appList.clear(); 190 //@@@ should really use STL iterator overlay on CFArray. By hand... 191 CFIndex count = CFArrayGetCount(applicationList); 192 for (CFIndex n = 0; n < count; n++) 193 appList.push_back(TrustedApplication::required( 194 SecTrustedApplicationRef(CFArrayGetValueAtIndex(applicationList, n)))); 195} 196 197 198// 199// Set and get the authorization tags of an ACL entry 200// 201OSStatus SecACLGetAuthorizations(SecACLRef acl, 202 CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 *tagCount) 203{ 204 BEGIN_SECAPI 205 AclAuthorizationSet auths = ACL::required(acl)->authorizations(); 206 if (Required(tagCount) < auths.size()) { // overflow 207 *tagCount = (uint32)auths.size(); // report size required 208 CssmError::throwMe(errSecParam); 209 } 210 *tagCount = (uint32)auths.size(); 211 copy(auths.begin(), auths.end(), tags); 212 END_SECAPI 213} 214 215CFArrayRef SecACLCopyAuthorizations(SecACLRef acl) 216{ 217 CFArrayRef result = NULL; 218 if (NULL == acl) 219 { 220 return result; 221 } 222 223 AclAuthorizationSet auths = ACL::required(acl)->authorizations(); 224 uint32 numAuths = (uint32)auths.size(); 225 226 CSSM_ACL_AUTHORIZATION_TAG* tags = new CSSM_ACL_AUTHORIZATION_TAG[numAuths]; 227 int i; 228 for (i = 0; i < numAuths; ++i) 229 { 230 tags[i] = NULL; 231 } 232 233 OSStatus err = SecACLGetAuthorizations(acl, tags, &numAuths); 234 if (errSecSuccess != err) 235 { 236 237 return result; 238 } 239 240 CFTypeRef* strings = new CFTypeRef[numAuths]; 241 for (i = 0; i < numAuths; ++i) 242 { 243 strings[i] = NULL; 244 } 245 246 for (size_t iCnt = 0; iCnt < numAuths; iCnt++) 247 { 248 strings[iCnt] = (CFTypeRef)GetAuthStringFromACLAuthorizationTag(tags[iCnt]); 249 } 250 251 result = CFArrayCreate(kCFAllocatorDefault, (const void **)strings, numAuths, NULL); 252 253 delete[] strings; 254 delete[] tags; 255 256 return result; 257 258} 259 260OSStatus SecACLSetAuthorizations(SecACLRef aclRef, 261 CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 tagCount) 262{ 263 BEGIN_SECAPI 264 SecPointer<ACL> acl = ACL::required(aclRef); 265 if (acl->isOwner()) // can't change rights of the owner ACL 266 MacOSError::throwMe(errSecInvalidOwnerEdit); 267 AclAuthorizationSet &auths = acl->authorizations(); 268 auths.clear(); 269 copy(tags, tags + tagCount, insert_iterator<AclAuthorizationSet>(auths, auths.begin())); 270 acl->modify(); 271 END_SECAPI 272} 273 274OSStatus SecACLUpdateAuthorizations(SecACLRef acl, CFArrayRef authorizations) 275{ 276 if (NULL == acl || NULL == authorizations) 277 { 278 return errSecParam; 279 } 280 uint32 tagCount = (uint32)CFArrayGetCount(authorizations); 281 282 size_t tagSize = (tagCount * sizeof(CSSM_ACL_AUTHORIZATION_TAG)); 283 284 CSSM_ACL_AUTHORIZATION_TAG* tags = (CSSM_ACL_AUTHORIZATION_TAG*)malloc(tagSize); 285 memset(tags, 0, tagSize); 286 for (uint32 iCnt = 0; iCnt < tagCount; iCnt++) 287 { 288 tags[iCnt] = GetACLAuthorizationTagFromString((CFStringRef)CFArrayGetValueAtIndex(authorizations, iCnt)); 289 } 290 291 OSStatus result = SecACLSetAuthorizations(acl, tags, tagCount); 292 free(tags); 293 return result; 294} 295