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