1/* 2 * Copyright (c) 2002-2004,2013 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#include <SecBase.h> 25#include <Security/SecAccess.h> 26#include <Security/SecAccessPriv.h> 27#include <Security/SecTrustedApplication.h> 28#include <Security/SecTrustedApplicationPriv.h> 29#include <security_keychain/Access.h> 30#include "SecBridge.h" 31#include <sys/param.h> 32 33#undef secdebug 34#include <utilities/SecCFWrappers.h> 35 36 37/* No restrictions. Permission to perform all operations on 38 the resource or available to an ACL owner. */ 39 40 41CFTypeRef kSecACLAuthorizationAny = (CFTypeRef)(CFSTR("ACLAuthorizationAny")); 42 43CFTypeRef kSecACLAuthorizationLogin = (CFTypeRef)(CFSTR("ACLAuthorizationLogin")); 44CFTypeRef kSecACLAuthorizationGenKey = (CFTypeRef)(CFSTR("ACLAuthorizationGenKey")); 45CFTypeRef kSecACLAuthorizationDelete = (CFTypeRef)(CFSTR("ACLAuthorizationDelete")); 46CFTypeRef kSecACLAuthorizationExportWrapped = (CFTypeRef)(CFSTR("ACLAuthorizationExportWrapped")); 47CFTypeRef kSecACLAuthorizationExportClear = (CFTypeRef)(CFSTR("ACLAuthorizationExportClear")); 48CFTypeRef kSecACLAuthorizationImportWrapped = (CFTypeRef)(CFSTR("ACLAuthorizationImportWrapped")); 49CFTypeRef kSecACLAuthorizationImportClear = (CFTypeRef)(CFSTR("ACLAuthorizationImportClear")); 50CFTypeRef kSecACLAuthorizationSign = (CFTypeRef)(CFSTR("ACLAuthorizationSign")); 51CFTypeRef kSecACLAuthorizationEncrypt = (CFTypeRef)(CFSTR("ACLAuthorizationEncrypt")); 52CFTypeRef kSecACLAuthorizationDecrypt = (CFTypeRef)(CFSTR("ACLAuthorizationDecrypt")); 53CFTypeRef kSecACLAuthorizationMAC = (CFTypeRef)(CFSTR("ACLAuthorizationMAC")); 54CFTypeRef kSecACLAuthorizationDerive = (CFTypeRef)(CFSTR("ACLAuthorizationDerive")); 55 56/* Defined authorization tag values for Keychain */ 57 58 59 60CFTypeRef kSecACLAuthorizationKeychainCreate = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainCreate")); 61CFTypeRef kSecACLAuthorizationKeychainDelete = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainDelete")); 62CFTypeRef kSecACLAuthorizationKeychainItemRead = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainItemRead")); 63CFTypeRef kSecACLAuthorizationKeychainItemInsert = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainItemInsert")); 64CFTypeRef kSecACLAuthorizationKeychainItemModify = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainItemModify")); 65CFTypeRef kSecACLAuthorizationKeychainItemDelete = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainItemDelete")); 66 67CFTypeRef kSecACLAuthorizationChangeACL = (CFTypeRef)(CFSTR("ACLAuthorizationChangeACL")); 68CFTypeRef kSecACLAuthorizationChangeOwner = (CFTypeRef)(CFSTR("ACLAuthorizationChangeOwner")); 69 70 71static CFArrayRef copyTrustedAppListFromBundle(CFStringRef bundlePath, CFStringRef trustedAppListFileName); 72 73static CFStringRef gKeys[] = 74{ 75 (CFStringRef)kSecACLAuthorizationAny, 76 (CFStringRef)kSecACLAuthorizationLogin, 77 (CFStringRef)kSecACLAuthorizationGenKey, 78 (CFStringRef)kSecACLAuthorizationDelete, 79 (CFStringRef)kSecACLAuthorizationExportWrapped, 80 (CFStringRef)kSecACLAuthorizationExportClear, 81 (CFStringRef)kSecACLAuthorizationImportWrapped, 82 (CFStringRef)kSecACLAuthorizationImportClear, 83 (CFStringRef)kSecACLAuthorizationSign, 84 (CFStringRef)kSecACLAuthorizationEncrypt, 85 (CFStringRef)kSecACLAuthorizationDecrypt, 86 (CFStringRef)kSecACLAuthorizationMAC, 87 (CFStringRef)kSecACLAuthorizationDerive, 88 89 /* Defined authorization tag values for Keychain */ 90 (CFStringRef)kSecACLAuthorizationKeychainCreate, 91 (CFStringRef)kSecACLAuthorizationKeychainDelete, 92 (CFStringRef)kSecACLAuthorizationKeychainItemRead, 93 (CFStringRef)kSecACLAuthorizationKeychainItemInsert, 94 (CFStringRef)kSecACLAuthorizationKeychainItemModify, 95 (CFStringRef)kSecACLAuthorizationKeychainItemDelete, 96 97 (CFStringRef)kSecACLAuthorizationChangeACL, 98 (CFStringRef)kSecACLAuthorizationChangeOwner 99 100}; 101 102static sint32 gValues[] = 103{ 104 CSSM_ACL_AUTHORIZATION_ANY, 105 CSSM_ACL_AUTHORIZATION_LOGIN, 106 CSSM_ACL_AUTHORIZATION_GENKEY, 107 CSSM_ACL_AUTHORIZATION_DELETE, 108 CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED, 109 CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR, 110 CSSM_ACL_AUTHORIZATION_IMPORT_WRAPPED, 111 CSSM_ACL_AUTHORIZATION_IMPORT_CLEAR, 112 CSSM_ACL_AUTHORIZATION_SIGN, 113 CSSM_ACL_AUTHORIZATION_ENCRYPT, 114 CSSM_ACL_AUTHORIZATION_DECRYPT, 115 CSSM_ACL_AUTHORIZATION_MAC, 116 CSSM_ACL_AUTHORIZATION_DERIVE, 117 CSSM_ACL_AUTHORIZATION_DBS_CREATE, 118 CSSM_ACL_AUTHORIZATION_DBS_DELETE, 119 CSSM_ACL_AUTHORIZATION_DB_READ, 120 CSSM_ACL_AUTHORIZATION_DB_INSERT, 121 CSSM_ACL_AUTHORIZATION_DB_MODIFY, 122 CSSM_ACL_AUTHORIZATION_DB_DELETE, 123 CSSM_ACL_AUTHORIZATION_CHANGE_ACL, 124 CSSM_ACL_AUTHORIZATION_CHANGE_OWNER 125}; 126 127static 128CFDictionaryRef CreateStringToNumDictionary() 129{ 130 int numItems = (sizeof(gValues) / sizeof(sint32)); 131 CFMutableDictionaryRef tempDict = CFDictionaryCreateMutable(kCFAllocatorDefault, numItems, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 132 133 for (int iCnt = 0; iCnt < numItems; iCnt++) 134 { 135 sint32 aNumber = gValues[iCnt]; 136 CFNumberRef aNum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &aNumber); 137 138 CFStringRef aString = gKeys[iCnt]; 139 CFDictionaryAddValue(tempDict, aString, aNum); 140 CFRelease(aNum); 141 } 142 143 CFDictionaryRef result = CFDictionaryCreateCopy(kCFAllocatorDefault, tempDict); 144 CFRelease(tempDict); 145 return result; 146 147} 148 149static 150CFDictionaryRef CreateNumToStringDictionary() 151{ 152 int numItems = (sizeof(gValues) / sizeof(sint32)); 153 154 CFMutableDictionaryRef tempDict = CFDictionaryCreateMutable(kCFAllocatorDefault, numItems, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 155 156 for (int iCnt = 0; iCnt < numItems; iCnt++) 157 { 158 sint32 aNumber = gValues[iCnt]; 159 CFNumberRef aNum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &aNumber); 160 161 CFStringRef aString = gKeys[iCnt]; 162 CFDictionaryAddValue(tempDict, aNum, aString); 163 CFRelease(aNum); 164 165 } 166 167 CFDictionaryRef result = CFDictionaryCreateCopy(kCFAllocatorDefault, tempDict); 168 CFRelease(tempDict); 169 return result; 170} 171 172 173/* TODO: This should be in some header */ 174sint32 GetACLAuthorizationTagFromString(CFStringRef aclStr); 175sint32 GetACLAuthorizationTagFromString(CFStringRef aclStr) 176{ 177 if (NULL == aclStr) 178 { 179#ifndef NDEBUG 180 CFShow(CFSTR("GetACLAuthorizationTagFromString aclStr is NULL")); 181#endif 182 return 0; 183 } 184 185 static CFDictionaryRef gACLMapping = NULL; 186 187 if (NULL == gACLMapping) 188 { 189 gACLMapping = CreateStringToNumDictionary(); 190 } 191 192 sint32 result = 0; 193 CFNumberRef valueResult = (CFNumberRef)CFDictionaryGetValue(gACLMapping, aclStr); 194 if (NULL != valueResult) 195 { 196 if (!CFNumberGetValue(valueResult, kCFNumberSInt32Type, &result)) 197 { 198 return 0; 199 } 200 201 } 202 else 203 { 204 return 0; 205 } 206 207 return result; 208 209} 210 211/* TODO: This should be in some header */ 212CFStringRef GetAuthStringFromACLAuthorizationTag(sint32 tag); 213CFStringRef GetAuthStringFromACLAuthorizationTag(sint32 tag) 214{ 215 static CFDictionaryRef gTagMapping = NULL; 216 CFNumberRef aNum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &tag); 217 218 if (NULL == gTagMapping) 219 { 220 gTagMapping = CreateNumToStringDictionary(); 221 } 222 223 CFStringRef result = (CFStringRef)kSecACLAuthorizationAny; 224 225 if (NULL != gTagMapping && CFDictionaryContainsKey(gTagMapping, aNum)) 226 { 227 result = (CFStringRef)CFDictionaryGetValue(gTagMapping, aNum); 228 } 229 return result; 230} 231 232// 233// CF boilerplate 234// 235CFTypeID SecAccessGetTypeID(void) 236{ 237 BEGIN_SECAPI 238 return gTypes().Access.typeID; 239 END_SECAPI1(_kCFRuntimeNotATypeID) 240} 241 242 243// 244// API bridge calls 245// 246/*! 247 * Create a new SecAccessRef that is set to the default configuration 248 * of a (newly created) security object. 249 */ 250OSStatus SecAccessCreate(CFStringRef descriptor, CFArrayRef trustedList, SecAccessRef *accessRef) 251{ 252 BEGIN_SECAPI 253 Required(descriptor); 254 SecPointer<Access> access; 255 if (trustedList) { 256 CFIndex length = CFArrayGetCount(trustedList); 257 ACL::ApplicationList trusted; 258 for (CFIndex n = 0; n < length; n++) 259 trusted.push_back(TrustedApplication::required( 260 SecTrustedApplicationRef(CFArrayGetValueAtIndex(trustedList, n)))); 261 access = new Access(cfString(descriptor), trusted); 262 } else { 263 access = new Access(cfString(descriptor)); 264 } 265 Required(accessRef) = access->handle(); 266 END_SECAPI 267} 268 269 270/*! 271 */ 272OSStatus SecAccessCreateFromOwnerAndACL(const CSSM_ACL_OWNER_PROTOTYPE *owner, 273 uint32 aclCount, const CSSM_ACL_ENTRY_INFO *acls, 274 SecAccessRef *accessRef) 275{ 276 BEGIN_SECAPI 277 Required(accessRef); // preflight 278 SecPointer<Access> access = new Access(Required(owner), aclCount, &Required(acls)); 279 *accessRef = access->handle(); 280 END_SECAPI 281} 282 283SecAccessRef SecAccessCreateWithOwnerAndACL(uid_t userId, gid_t groupId, SecAccessOwnerType ownerType, CFArrayRef acls, CFErrorRef *error) 284{ 285 SecAccessRef result = NULL; 286 287 CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector = 288 { 289 CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION, // selector version 290 ownerType, 291 userId, 292 groupId 293 }; 294 295 CSSM_LIST_ELEMENT subject2 = { NULL, 0 }; 296 subject2.Element.Word.Data = (UInt8 *)&selector; 297 subject2.Element.Word.Length = sizeof(selector); 298 CSSM_LIST_ELEMENT subject1 = 299 { 300 &subject2, CSSM_ACL_SUBJECT_TYPE_PROCESS, CSSM_LIST_ELEMENT_WORDID 301 }; 302 303 CFIndex numAcls = 0; 304 305 if (NULL != acls) 306 { 307 numAcls = CFArrayGetCount(acls); 308 } 309 310#ifndef NDEBUG 311 CFStringRef debugStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, 312 CFSTR("SecAccessCreateWithOwnerAndACL: processing %d acls"), (int)numAcls); 313 CFShow(debugStr); 314 CFRelease(debugStr); 315#endif 316 317 CSSM_ACL_AUTHORIZATION_TAG rights[numAcls]; 318 memset(rights, 0, sizeof(rights)); 319 320 for (CFIndex iCnt = 0; iCnt < numAcls; iCnt++) 321 { 322 CFStringRef aclStr = (CFStringRef)CFArrayGetValueAtIndex(acls, iCnt); 323 324#ifndef NDEBUG 325 debugStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, 326 CFSTR("SecAccessCreateWithOwnerAndACL: acls[%d] = %@"), (int)iCnt, aclStr); 327 328 CFShow(debugStr); 329 CFRelease(debugStr); 330#endif 331 332 CSSM_ACL_AUTHORIZATION_TAG aTag = GetACLAuthorizationTagFromString(aclStr); 333 334#ifndef NDEBUG 335 debugStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, 336 CFSTR("SecAccessCreateWithOwnerAndACL: rights[%d] = %d"), (int)iCnt, aTag); 337 338 CFShow(debugStr); 339 CFRelease(debugStr); 340#endif 341 342 rights[iCnt] = aTag; 343 } 344 345 346 for (CFIndex iCnt = 0; iCnt < numAcls; iCnt++) 347 { 348#ifndef NDEBUG 349 debugStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, 350 CFSTR("SecAccessCreateWithOwnerAndACL: rights[%d] = %d"), (int)iCnt, rights[iCnt]); 351 352 CFShow(debugStr); 353 CFRelease(debugStr); 354#endif 355 356 357 } 358 359 CSSM_ACL_OWNER_PROTOTYPE owner = 360 { 361 // TypedSubject 362 { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 }, 363 // Delegate 364 false 365 }; 366 367 368 // ACL entries (any number, just one here) 369 CSSM_ACL_ENTRY_INFO acl_rights[] = 370 { 371 { 372 // prototype 373 { 374 // TypedSubject 375 { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 }, 376 false, // Delegate 377 // rights for this entry 378 { (uint32)(sizeof(rights) / sizeof(rights[0])), rights }, 379 // rest is defaulted 380 } 381 } 382 }; 383 384 OSStatus err = SecAccessCreateFromOwnerAndACL(&owner, 385 sizeof(acl_rights) / sizeof(acl_rights[0]), acl_rights, &result); 386 387 if (errSecSuccess != err) 388 { 389 result = NULL; 390 if (NULL != error) 391 { 392 *error = CFErrorCreate(kCFAllocatorDefault, CFSTR("FIX ME"), err, NULL); 393 } 394 } 395 return result; 396} 397 398 399/*! 400 */ 401OSStatus SecAccessGetOwnerAndACL(SecAccessRef accessRef, 402 CSSM_ACL_OWNER_PROTOTYPE_PTR *owner, 403 uint32 *aclCount, CSSM_ACL_ENTRY_INFO_PTR *acls) 404{ 405 BEGIN_SECAPI 406 Access::required(accessRef)->copyOwnerAndAcl( 407 Required(owner), Required(aclCount), Required(acls)); 408 END_SECAPI 409} 410 411OSStatus SecAccessCopyOwnerAndACL(SecAccessRef accessRef, uid_t* userId, gid_t* groupId, SecAccessOwnerType* ownerType, CFArrayRef* aclList) 412{ 413 CSSM_ACL_OWNER_PROTOTYPE_PTR owner = NULL; 414 CSSM_ACL_ENTRY_INFO_PTR acls = NULL; 415 uint32 aclCount = 0; 416 OSStatus result = SecAccessGetOwnerAndACL(accessRef, &owner, &aclCount, &acls); 417 if (errSecSuccess != result ) 418 { 419 return result; 420 } 421 422 if (NULL != owner) 423 { 424 CSSM_LIST_ELEMENT_PTR listHead = owner->TypedSubject.Head; 425 if (listHead != NULL && listHead->ElementType == CSSM_LIST_ELEMENT_WORDID) 426 { 427 CSSM_LIST_ELEMENT_PTR nextElement = listHead->NextElement; 428 if (listHead->WordID == CSSM_ACL_SUBJECT_TYPE_PROCESS && listHead->ElementType == CSSM_LIST_ELEMENT_WORDID) 429 { 430 // nextElement contains the required data 431 CSSM_ACL_PROCESS_SUBJECT_SELECTOR* selectorPtr = (CSSM_ACL_PROCESS_SUBJECT_SELECTOR*)nextElement->Element.Word.Data; 432 if (NULL != selectorPtr) 433 { 434 if (NULL != userId) 435 { 436 *userId = (uid_t)selectorPtr->uid; 437 } 438 439 if (NULL != groupId) 440 { 441 *groupId = (gid_t)selectorPtr->gid; 442 } 443 444 if (NULL != ownerType) 445 { 446 *ownerType = (SecAccessOwnerType)selectorPtr->mask; 447 } 448 } 449 } 450 451 } 452 453 } 454 455 if (NULL != aclList) 456 { 457#ifndef NDEBUG 458 CFShow(CFSTR("SecAccessCopyOwnerAndACL: processing the ACL list")); 459#endif 460 461 CFMutableArrayRef stringArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 462 CSSM_ACL_OWNER_PROTOTYPE_PTR protoPtr = NULL; 463 uint32 numAcls = 0L; 464 CSSM_ACL_ENTRY_INFO_PTR aclEntry = NULL; 465 466 result = SecAccessGetOwnerAndACL(accessRef, &protoPtr, &numAcls, &aclEntry); 467 if (errSecSuccess == result) 468 { 469#ifndef NDEBUG 470 CFStringRef tempStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("SecAccessCopyOwnerAndACL: numAcls = %d"), numAcls); 471 CFShow(tempStr); 472 CFRelease(tempStr); 473#endif 474 475 for (uint32 iCnt = 0; iCnt < numAcls; iCnt++) 476 { 477 CSSM_ACL_ENTRY_PROTOTYPE prototype = aclEntry[iCnt].EntryPublicInfo; 478 CSSM_AUTHORIZATIONGROUP authGroup = prototype.Authorization; 479 int numAuthTags = (int)authGroup.NumberOfAuthTags; 480 481 for (int jCnt = 0; jCnt < numAuthTags; jCnt++) 482 { 483 484 sint32 aTag = authGroup.AuthTags[jCnt]; 485 CFStringRef aString = GetAuthStringFromACLAuthorizationTag(aTag); 486 487 CFArrayAppendValue(stringArray, aString); 488 } 489 } 490 } 491 492 if (NULL != stringArray) 493 { 494 if (0 < CFArrayGetCount(stringArray)) 495 { 496 *aclList = CFArrayCreateCopy(kCFAllocatorDefault, stringArray); 497 } 498 CFRelease(stringArray); 499 } 500 } 501 502 return result; 503} 504 505/*! 506 */ 507OSStatus SecAccessCopyACLList(SecAccessRef accessRef, 508 CFArrayRef *aclList) 509{ 510 BEGIN_SECAPI 511 Required(aclList) = Access::required(accessRef)->copySecACLs(); 512 END_SECAPI 513} 514 515 516/*! 517 */ 518OSStatus SecAccessCopySelectedACLList(SecAccessRef accessRef, 519 CSSM_ACL_AUTHORIZATION_TAG action, 520 CFArrayRef *aclList) 521{ 522 BEGIN_SECAPI 523 Required(aclList) = Access::required(accessRef)->copySecACLs(action); 524 END_SECAPI 525} 526 527CFArrayRef SecAccessCopyMatchingACLList(SecAccessRef accessRef, CFTypeRef authorizationTag) 528{ 529 CFArrayRef result = NULL; 530 CSSM_ACL_AUTHORIZATION_TAG tag = GetACLAuthorizationTagFromString((CFStringRef)authorizationTag); 531 OSStatus err = SecAccessCopySelectedACLList(accessRef, tag, &result); 532 if (errSecSuccess != err) 533 { 534 result = NULL; 535 } 536 return result; 537} 538 539CFArrayRef copyTrustedAppListFromBundle(CFStringRef bundlePath, CFStringRef trustedAppListFileName) 540{ 541 CFStringRef errorString = nil; 542 CFURLRef bundleURL,trustedAppsURL = NULL; 543 CFBundleRef secBundle = NULL; 544 CFPropertyListRef trustedAppsPlist = NULL; 545 CFDataRef xmlDataRef = NULL; 546 SInt32 errorCode; 547 CFArrayRef trustedAppList = NULL; 548 CFMutableStringRef trustedAppListFileNameWithoutExtension = NULL; 549 550 // Make a CFURLRef from the CFString representation of the bundle�s path. 551 bundleURL = CFURLCreateWithFileSystemPath( 552 kCFAllocatorDefault,bundlePath,kCFURLPOSIXPathStyle,true); 553 554 CFRange wholeStrRange; 555 556 if (!bundleURL) 557 goto xit; 558 559 // Make a bundle instance using the URLRef. 560 secBundle = CFBundleCreate(kCFAllocatorDefault,bundleURL); 561 if (!secBundle) 562 goto xit; 563 564 trustedAppListFileNameWithoutExtension = 565 CFStringCreateMutableCopy(NULL,CFStringGetLength(trustedAppListFileName),trustedAppListFileName); 566 wholeStrRange = CFStringFind(trustedAppListFileName,CFSTR(".plist"),0); 567 568 CFStringDelete(trustedAppListFileNameWithoutExtension,wholeStrRange); 569 570 // Look for a resource in the bundle by name and type 571 trustedAppsURL = CFBundleCopyResourceURL(secBundle,trustedAppListFileNameWithoutExtension,CFSTR("plist"),NULL); 572 if (!trustedAppsURL) 573 goto xit; 574 575 if ( trustedAppListFileNameWithoutExtension ) 576 CFRelease(trustedAppListFileNameWithoutExtension); 577 578 if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,trustedAppsURL,&xmlDataRef,NULL,NULL,&errorCode)) 579 goto xit; 580 581 trustedAppsPlist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault,xmlDataRef,kCFPropertyListImmutable,&errorString); 582 trustedAppList = (CFArrayRef)trustedAppsPlist; 583 584xit: 585 if (bundleURL) 586 CFRelease(bundleURL); 587 if (secBundle) 588 CFRelease(secBundle); 589 if (trustedAppsURL) 590 CFRelease(trustedAppsURL); 591 if (xmlDataRef) 592 CFRelease(xmlDataRef); 593 if (errorString) 594 CFRelease(errorString); 595 596 return trustedAppList; 597} 598 599OSStatus SecAccessCreateWithTrustedApplications(CFStringRef trustedApplicationsPListPath, CFStringRef accessLabel, Boolean allowAny, SecAccessRef* returnedAccess) 600{ 601 OSStatus err = errSecSuccess; 602 SecAccessRef accessToReturn=nil; 603 CFMutableArrayRef trustedApplications=nil; 604 605 if (!allowAny) // use default access ("confirm access") 606 { 607 // make an exception list of applications you want to trust, 608 // which are allowed to access the item without requiring user confirmation 609 SecTrustedApplicationRef myself=NULL, someOther=NULL; 610 CFArrayRef trustedAppListFromBundle=NULL; 611 612 trustedApplications=CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks); 613 err = SecTrustedApplicationCreateFromPath(NULL, &myself); 614 if (!err) 615 CFArrayAppendValue(trustedApplications,myself); 616 617 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, trustedApplicationsPListPath, kCFURLPOSIXPathStyle, 0); 618 CFStringRef leafStr = NULL; 619 leafStr = CFURLCopyLastPathComponent(url); 620 621 CFURLRef bndlPathURL = NULL; 622 bndlPathURL = CFURLCreateCopyDeletingLastPathComponent(NULL, url); 623 CFStringRef bndlPath = NULL; 624 bndlPath = CFURLCopyFileSystemPath(bndlPathURL, kCFURLPOSIXPathStyle); 625 trustedAppListFromBundle=copyTrustedAppListFromBundle(bndlPath, leafStr); 626 if ( leafStr ) 627 CFRelease(leafStr); 628 if ( bndlPath ) 629 CFRelease(bndlPath); 630 if ( url ) 631 CFRelease(url); 632 if ( bndlPathURL ) 633 CFRelease(bndlPathURL); 634 if (trustedAppListFromBundle) 635 { 636 CFIndex ix,top; 637 char buffer[MAXPATHLEN]; 638 top = CFArrayGetCount(trustedAppListFromBundle); 639 for (ix=0;ix<top;ix++) 640 { 641 CFStringRef filename = (CFStringRef)CFArrayGetValueAtIndex(trustedAppListFromBundle,ix); 642 CFIndex stringLength = CFStringGetLength(filename); 643 CFIndex usedBufLen; 644 645 if (stringLength != CFStringGetBytes(filename,CFRangeMake(0,stringLength),kCFStringEncodingUTF8,0, 646 false,(UInt8 *)&buffer,MAXPATHLEN, &usedBufLen)) 647 break; 648 buffer[usedBufLen] = 0; 649 // 650 // Support specification of trusted applications by either 651 // a full pathname or a code requirement string. 652 // 653 if (buffer[0]=='/') 654 { 655 err = SecTrustedApplicationCreateFromPath(buffer,&someOther); 656 } 657 else 658 { 659 char *buf = NULL; 660 CFStringRef reqStr = filename; 661 CFArrayRef descArray = CFStringCreateArrayBySeparatingStrings(NULL, reqStr, CFSTR("\"")); 662 if (descArray && (CFArrayGetCount(descArray) > 1)) 663 { 664 CFStringRef descStr = (CFStringRef) CFArrayGetValueAtIndex(descArray, 1); 665 if (descStr) 666 buf = CFStringToCString(descStr); 667 } 668 SecRequirementRef reqRef = NULL; 669 err = SecRequirementCreateWithString(reqStr, kSecCSDefaultFlags, &reqRef); 670 if (!err) 671 err = SecTrustedApplicationCreateFromRequirement((const char *)buf, reqRef, &someOther); 672 if (buf) 673 free(buf); 674 CFReleaseSafe(reqRef); 675 CFReleaseSafe(descArray); 676 } 677 if (!err) 678 CFArrayAppendValue(trustedApplications,someOther); 679 680 if (someOther) 681 CFReleaseNull(someOther); 682 } 683 CFRelease(trustedAppListFromBundle); 684 } 685 } 686 687 err = SecAccessCreate((CFStringRef)accessLabel, (CFArrayRef)trustedApplications, &accessToReturn); 688 if (!err) 689 { 690 if (allowAny) // change access to be wide-open for decryption ("always allow access") 691 { 692 // get the access control list for decryption operations 693 CFArrayRef aclList=nil; 694 err = SecAccessCopySelectedACLList(accessToReturn, CSSM_ACL_AUTHORIZATION_DECRYPT, &aclList); 695 if (!err) 696 { 697 // get the first entry in the access control list 698 SecACLRef aclRef=(SecACLRef)CFArrayGetValueAtIndex(aclList, 0); 699 CFArrayRef appList=nil; 700 CFStringRef promptDescription=nil; 701 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector; 702 err = SecACLCopySimpleContents(aclRef, &appList, &promptDescription, &promptSelector); 703 704 // modify the default ACL to not require the passphrase, and have a nil application list 705 promptSelector.flags &= ~CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE; 706 err = SecACLSetSimpleContents(aclRef, NULL, promptDescription, &promptSelector); 707 708 if (appList) CFRelease(appList); 709 if (promptDescription) CFRelease(promptDescription); 710 } 711 } 712 } 713 *returnedAccess = accessToReturn; 714 return err; 715} 716