2  * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   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 
  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. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  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> 
  35 #include <utilities/SecCFWrappers.h> 
  38 /* No restrictions. Permission to perform all operations on 
  39    the resource or available to an ACL owner.  */ 
  42 const CFStringRef kSecACLAuthorizationAny 
= CFSTR("ACLAuthorizationAny"); 
  44 const CFStringRef kSecACLAuthorizationLogin 
= CFSTR("ACLAuthorizationLogin"); 
  45 const CFStringRef kSecACLAuthorizationGenKey 
= CFSTR("ACLAuthorizationGenKey"); 
  46 const CFStringRef kSecACLAuthorizationDelete 
= CFSTR("ACLAuthorizationDelete"); 
  47 const CFStringRef kSecACLAuthorizationExportWrapped 
= CFSTR("ACLAuthorizationExportWrapped"); 
  48 const CFStringRef kSecACLAuthorizationExportClear 
= CFSTR("ACLAuthorizationExportClear"); 
  49 const CFStringRef kSecACLAuthorizationImportWrapped 
= CFSTR("ACLAuthorizationImportWrapped"); 
  50 const CFStringRef kSecACLAuthorizationImportClear 
= CFSTR("ACLAuthorizationImportClear"); 
  51 const CFStringRef kSecACLAuthorizationSign 
= CFSTR("ACLAuthorizationSign"); 
  52 const CFStringRef kSecACLAuthorizationEncrypt 
= CFSTR("ACLAuthorizationEncrypt"); 
  53 const CFStringRef kSecACLAuthorizationDecrypt 
= CFSTR("ACLAuthorizationDecrypt"); 
  54 const CFStringRef kSecACLAuthorizationMAC 
= CFSTR("ACLAuthorizationMAC"); 
  55 const CFStringRef kSecACLAuthorizationDerive 
= CFSTR("ACLAuthorizationDerive"); 
  57 /* Defined authorization tag values for Keychain */ 
  61 const CFStringRef kSecACLAuthorizationKeychainCreate 
= CFSTR("ACLAuthorizationKeychainCreate"); 
  62 const CFStringRef kSecACLAuthorizationKeychainDelete 
= CFSTR("ACLAuthorizationKeychainDelete"); 
  63 const CFStringRef kSecACLAuthorizationKeychainItemRead 
= CFSTR("ACLAuthorizationKeychainItemRead"); 
  64 const CFStringRef kSecACLAuthorizationKeychainItemInsert 
= CFSTR("ACLAuthorizationKeychainItemInsert"); 
  65 const CFStringRef kSecACLAuthorizationKeychainItemModify 
= CFSTR("ACLAuthorizationKeychainItemModify"); 
  66 const CFStringRef kSecACLAuthorizationKeychainItemDelete 
= CFSTR("ACLAuthorizationKeychainItemDelete"); 
  68 const CFStringRef kSecACLAuthorizationChangeACL 
= CFSTR("ACLAuthorizationChangeACL"); 
  69 const CFStringRef kSecACLAuthorizationChangeOwner 
= CFSTR("ACLAuthorizationChangeOwner"); 
  70 const CFStringRef kSecACLAuthorizationPartitionID 
= CFSTR("ACLAuthorizationPartitionID"); 
  71 const CFStringRef kSecACLAuthorizationIntegrity 
= CFSTR("ACLAuthorizationIntegrity"); 
  74 static CFArrayRef 
copyTrustedAppListFromBundle(CFStringRef bundlePath
, CFStringRef trustedAppListFileName
); 
  76 static CFStringRef gKeys
[] = 
  78         kSecACLAuthorizationAny
, 
  79         kSecACLAuthorizationLogin
, 
  80         kSecACLAuthorizationGenKey
, 
  81         kSecACLAuthorizationDelete
, 
  82         kSecACLAuthorizationExportWrapped
, 
  83         kSecACLAuthorizationExportClear
, 
  84         kSecACLAuthorizationImportWrapped
, 
  85         kSecACLAuthorizationImportClear
, 
  86         kSecACLAuthorizationSign
, 
  87         kSecACLAuthorizationEncrypt
, 
  88         kSecACLAuthorizationDecrypt
, 
  89         kSecACLAuthorizationMAC
, 
  90         kSecACLAuthorizationDerive
, 
  92         /* Defined authorization tag values for Keychain */ 
  93         kSecACLAuthorizationKeychainCreate
, 
  94         kSecACLAuthorizationKeychainDelete
, 
  95         kSecACLAuthorizationKeychainItemRead
, 
  96         kSecACLAuthorizationKeychainItemInsert
, 
  97         kSecACLAuthorizationKeychainItemModify
, 
  98         kSecACLAuthorizationKeychainItemDelete
, 
 100         kSecACLAuthorizationChangeACL
, 
 101         kSecACLAuthorizationChangeOwner
, 
 102     kSecACLAuthorizationPartitionID
, 
 103     kSecACLAuthorizationIntegrity
 
 106 static sint32 gValues
[] = 
 108         CSSM_ACL_AUTHORIZATION_ANY
, 
 109         CSSM_ACL_AUTHORIZATION_LOGIN
, 
 110         CSSM_ACL_AUTHORIZATION_GENKEY
, 
 111         CSSM_ACL_AUTHORIZATION_DELETE
, 
 112         CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED
, 
 113         CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR
, 
 114         CSSM_ACL_AUTHORIZATION_IMPORT_WRAPPED
, 
 115         CSSM_ACL_AUTHORIZATION_IMPORT_CLEAR
, 
 116         CSSM_ACL_AUTHORIZATION_SIGN
, 
 117         CSSM_ACL_AUTHORIZATION_ENCRYPT
, 
 118         CSSM_ACL_AUTHORIZATION_DECRYPT
, 
 119         CSSM_ACL_AUTHORIZATION_MAC
, 
 120         CSSM_ACL_AUTHORIZATION_DERIVE
, 
 121         CSSM_ACL_AUTHORIZATION_DBS_CREATE
, 
 122         CSSM_ACL_AUTHORIZATION_DBS_DELETE
, 
 123         CSSM_ACL_AUTHORIZATION_DB_READ
, 
 124         CSSM_ACL_AUTHORIZATION_DB_INSERT
, 
 125         CSSM_ACL_AUTHORIZATION_DB_MODIFY
, 
 126         CSSM_ACL_AUTHORIZATION_DB_DELETE
, 
 127         CSSM_ACL_AUTHORIZATION_CHANGE_ACL
, 
 128         CSSM_ACL_AUTHORIZATION_CHANGE_OWNER
, 
 129     CSSM_ACL_AUTHORIZATION_PARTITION_ID
, 
 130     CSSM_ACL_AUTHORIZATION_INTEGRITY
 
 134 CFDictionaryRef 
CreateStringToNumDictionary() 
 136         int numItems 
= (sizeof(gValues
) / sizeof(sint32
)); 
 137         CFMutableDictionaryRef tempDict 
= CFDictionaryCreateMutable(kCFAllocatorDefault
, numItems
, &kCFCopyStringDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
); 
 139         for (int iCnt 
= 0; iCnt 
< numItems
; iCnt
++) 
 141                 sint32 aNumber 
= gValues
[iCnt
]; 
 142                 CFNumberRef aNum 
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
, &aNumber
); 
 144                 CFStringRef aString 
= gKeys
[iCnt
]; 
 145                 CFDictionaryAddValue(tempDict
, aString
, aNum
); 
 149         CFDictionaryRef result 
= CFDictionaryCreateCopy(kCFAllocatorDefault
, tempDict
); 
 156 CFDictionaryRef 
CreateNumToStringDictionary() 
 158         int numItems 
= (sizeof(gValues
) / sizeof(sint32
)); 
 160         CFMutableDictionaryRef tempDict 
= CFDictionaryCreateMutable(kCFAllocatorDefault
, numItems
, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
); 
 162         for (int iCnt 
= 0; iCnt 
< numItems
; iCnt
++) 
 164                 sint32 aNumber 
= gValues
[iCnt
]; 
 165                 CFNumberRef aNum 
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
, &aNumber
); 
 167                 CFStringRef aString 
= gKeys
[iCnt
]; 
 168                 CFDictionaryAddValue(tempDict
, aNum
, aString
); 
 173         CFDictionaryRef result 
= CFDictionaryCreateCopy(kCFAllocatorDefault
, tempDict
); 
 179 /* TODO: This should be in some header */ 
 180 sint32 
GetACLAuthorizationTagFromString(CFStringRef aclStr
); 
 181 sint32 
GetACLAuthorizationTagFromString(CFStringRef aclStr
) 
 186                 CFShow(CFSTR("GetACLAuthorizationTagFromString aclStr is NULL")); 
 191         static CFDictionaryRef gACLMapping 
= NULL
; 
 193         if (NULL 
== gACLMapping
) 
 195                 gACLMapping 
= CreateStringToNumDictionary(); 
 199         CFNumberRef valueResult 
= (CFNumberRef
)CFDictionaryGetValue(gACLMapping
, aclStr
); 
 200         if (NULL 
!= valueResult
) 
 202                 if (!CFNumberGetValue(valueResult
, kCFNumberSInt32Type
, &result
)) 
 217 /* TODO: This should be in some header */ 
 218 CFStringRef 
GetAuthStringFromACLAuthorizationTag(sint32 tag
); 
 219 CFStringRef 
GetAuthStringFromACLAuthorizationTag(sint32 tag
) 
 221         static CFDictionaryRef gTagMapping 
= NULL
; 
 222         CFNumberRef aNum 
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
, &tag
); 
 224         if (NULL 
== gTagMapping
) 
 226                 gTagMapping 
= CreateNumToStringDictionary(); 
 229         CFStringRef result 
= (CFStringRef
)kSecACLAuthorizationAny
; 
 231         if (NULL 
!= gTagMapping 
&& CFDictionaryContainsKey(gTagMapping
, aNum
)) 
 233                 result 
= (CFStringRef
)CFDictionaryGetValue(gTagMapping
, aNum
); 
 242 CFTypeID 
SecAccessGetTypeID(void) 
 245         return gTypes().Access
.typeID
; 
 246         END_SECAPI1(_kCFRuntimeNotATypeID
) 
 254  *      Create a new SecAccessRef that is set to the default configuration 
 255  *      of a (newly created) security object. 
 257 OSStatus 
SecAccessCreate(CFStringRef descriptor
, CFArrayRef trustedList
, SecAccessRef 
*accessRef
) 
 260         Required(descriptor
); 
 261         SecPointer
<Access
> access
; 
 263                 CFIndex length 
= CFArrayGetCount(trustedList
); 
 264                 ACL::ApplicationList trusted
; 
 265                 for (CFIndex n 
= 0; n 
< length
; n
++) 
 266                         trusted
.push_back(TrustedApplication::required( 
 267                                 SecTrustedApplicationRef(CFArrayGetValueAtIndex(trustedList
, n
)))); 
 268                 access 
= new Access(cfString(descriptor
), trusted
); 
 270                 access 
= new Access(cfString(descriptor
)); 
 272         Required(accessRef
) = access
->handle(); 
 279 OSStatus 
SecAccessCreateFromOwnerAndACL(const CSSM_ACL_OWNER_PROTOTYPE 
*owner
, 
 280         uint32 aclCount
, const CSSM_ACL_ENTRY_INFO 
*acls
, 
 281         SecAccessRef 
*accessRef
) 
 284         Required(accessRef
);    // preflight 
 285         SecPointer
<Access
> access 
= new Access(Required(owner
), aclCount
, &Required(acls
)); 
 286         *accessRef 
= access
->handle(); 
 290 SecAccessRef 
SecAccessCreateWithOwnerAndACL(uid_t userId
, gid_t groupId
, SecAccessOwnerType ownerType
, CFArrayRef acls
, CFErrorRef 
*error
) 
 292         SecAccessRef result 
= NULL
; 
 294         CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector 
= 
 296                 CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION
,      // selector version 
 297                 int_cast
<UInt32
, uint16
>(ownerType
), 
 302         CSSM_LIST_ELEMENT subject2 
= { NULL
, 0 }; 
 303         subject2
.Element
.Word
.Data 
= (UInt8 
*)&selector
; 
 304         subject2
.Element
.Word
.Length 
= sizeof(selector
); 
 305         CSSM_LIST_ELEMENT subject1 
= 
 307                 &subject2
, CSSM_ACL_SUBJECT_TYPE_PROCESS
, CSSM_LIST_ELEMENT_WORDID
 
 314                 numAcls 
= CFArrayGetCount(acls
); 
 318         CFStringRef debugStr 
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, 
 319                 CFSTR("SecAccessCreateWithOwnerAndACL: processing %d acls"), (int)numAcls
); 
 324         CSSM_ACL_AUTHORIZATION_TAG rights
[numAcls
]; 
 325         memset(rights
, 0, sizeof(rights
)); 
 327         for (CFIndex iCnt 
= 0; iCnt 
< numAcls
; iCnt
++) 
 329                 CFStringRef aclStr 
= (CFStringRef
)CFArrayGetValueAtIndex(acls
, iCnt
); 
 332                 debugStr 
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, 
 333                         CFSTR("SecAccessCreateWithOwnerAndACL: acls[%d] = %@"), (int)iCnt
, aclStr
); 
 339                 CSSM_ACL_AUTHORIZATION_TAG aTag 
= GetACLAuthorizationTagFromString(aclStr
); 
 342                 debugStr 
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, 
 343                         CFSTR("SecAccessCreateWithOwnerAndACL: rights[%d] = %d"), (int)iCnt
, aTag
); 
 353         for (CFIndex iCnt 
= 0; iCnt 
< numAcls
; iCnt
++) 
 356                 debugStr 
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, 
 357                         CFSTR("SecAccessCreateWithOwnerAndACL: rights[%d]  = %d"), (int)iCnt
, rights
[iCnt
]); 
 366         CSSM_ACL_OWNER_PROTOTYPE owner 
= 
 369                 { CSSM_LIST_TYPE_UNKNOWN
, &subject1
, &subject2 
}, 
 375         // ACL entries (any number, just one here) 
 376         CSSM_ACL_ENTRY_INFO acl_rights
[] = 
 382                                 { CSSM_LIST_TYPE_UNKNOWN
, &subject1
, &subject2 
}, 
 384                                 // rights for this entry 
 385                                 { (uint32
)(sizeof(rights
) / sizeof(rights
[0])), rights 
}, 
 391         OSStatus err 
= SecAccessCreateFromOwnerAndACL(&owner
, 
 392                 sizeof(acl_rights
) / sizeof(acl_rights
[0]), acl_rights
, &result
); 
 394         if (errSecSuccess 
!= err
) 
 399                         *error  
= CFErrorCreate(kCFAllocatorDefault
, CFSTR("FIX ME"), err
, NULL
); 
 408 OSStatus 
SecAccessGetOwnerAndACL(SecAccessRef accessRef
, 
 409         CSSM_ACL_OWNER_PROTOTYPE_PTR 
*owner
, 
 410         uint32 
*aclCount
, CSSM_ACL_ENTRY_INFO_PTR 
*acls
) 
 413         Access::required(accessRef
)->copyOwnerAndAcl( 
 414                 Required(owner
), Required(aclCount
), Required(acls
)); 
 418 OSStatus 
SecAccessCopyOwnerAndACL(SecAccessRef accessRef
, uid_t
* userId
, gid_t
* groupId
, SecAccessOwnerType
* ownerType
, CFArrayRef
* aclList
) 
 420         CSSM_ACL_OWNER_PROTOTYPE_PTR owner 
= NULL
; 
 421         CSSM_ACL_ENTRY_INFO_PTR acls 
= NULL
; 
 423         OSStatus result 
= SecAccessGetOwnerAndACL(accessRef
, &owner
, &aclCount
, &acls
); 
 424         if (errSecSuccess 
!= result 
) 
 431                 CSSM_LIST_ELEMENT_PTR listHead 
= owner
->TypedSubject
.Head
; 
 432                 if (listHead 
!= NULL 
&& listHead
->ElementType 
== CSSM_LIST_ELEMENT_WORDID
) 
 434                         CSSM_LIST_ELEMENT_PTR nextElement 
= listHead
->NextElement
; 
 435                         if (listHead
->WordID 
== CSSM_ACL_SUBJECT_TYPE_PROCESS 
&& listHead
->ElementType 
== CSSM_LIST_ELEMENT_WORDID
) 
 437                                 // nextElement contains the required data 
 438                                 CSSM_ACL_PROCESS_SUBJECT_SELECTOR
* selectorPtr 
= (CSSM_ACL_PROCESS_SUBJECT_SELECTOR
*)nextElement
->Element
.Word
.Data
; 
 439                                 if (NULL 
!= selectorPtr
) 
 443                                                 *userId 
= (uid_t
)selectorPtr
->uid
; 
 448                                                 *groupId 
= (gid_t
)selectorPtr
->gid
; 
 451                                         if (NULL 
!= ownerType
) 
 453                                                 *ownerType 
= (SecAccessOwnerType
)selectorPtr
->mask
; 
 465                 CFShow(CFSTR("SecAccessCopyOwnerAndACL: processing the ACL list")); 
 468                 CFMutableArrayRef stringArray 
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
); 
 469                 CSSM_ACL_OWNER_PROTOTYPE_PTR protoPtr 
= NULL
; 
 471                 CSSM_ACL_ENTRY_INFO_PTR aclEntry 
= NULL
; 
 473                 result 
= SecAccessGetOwnerAndACL(accessRef
, &protoPtr
, &numAcls
, &aclEntry
); 
 474                 if (errSecSuccess 
== result
) 
 477                         CFStringRef tempStr 
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("SecAccessCopyOwnerAndACL: numAcls = %d"), numAcls
); 
 482                         for (uint32 iCnt 
= 0; iCnt 
< numAcls
; iCnt
++) 
 484                                 CSSM_ACL_ENTRY_PROTOTYPE prototype 
= aclEntry
[iCnt
].EntryPublicInfo
; 
 485                                 CSSM_AUTHORIZATIONGROUP authGroup 
= prototype
.Authorization
; 
 486                                 int numAuthTags 
= (int)authGroup
.NumberOfAuthTags
; 
 488                                 for (int jCnt 
= 0; jCnt 
< numAuthTags
; jCnt
++) 
 491                                         sint32 aTag 
= authGroup
.AuthTags
[jCnt
]; 
 492                                         CFStringRef aString 
= GetAuthStringFromACLAuthorizationTag(aTag
); 
 494                                         CFArrayAppendValue(stringArray
, aString
); 
 499                 if (NULL 
!= stringArray
) 
 501                         if (0 < CFArrayGetCount(stringArray
)) 
 503                                 *aclList 
= CFArrayCreateCopy(kCFAllocatorDefault
, stringArray
); 
 505                         CFRelease(stringArray
); 
 514 OSStatus 
SecAccessCopyACLList(SecAccessRef accessRef
, 
 518         Required(aclList
) = Access::required(accessRef
)->copySecACLs(); 
 525 OSStatus 
SecAccessCopySelectedACLList(SecAccessRef accessRef
, 
 526         CSSM_ACL_AUTHORIZATION_TAG action
, 
 530         Required(aclList
) = Access::required(accessRef
)->copySecACLs(action
); 
 534 CFArrayRef 
SecAccessCopyMatchingACLList(SecAccessRef accessRef
, CFTypeRef authorizationTag
) 
 536         CFArrayRef result 
= NULL
; 
 537         CSSM_ACL_AUTHORIZATION_TAG tag 
= GetACLAuthorizationTagFromString((CFStringRef
)authorizationTag
); 
 538         OSStatus err 
= SecAccessCopySelectedACLList(accessRef
, tag
, &result
); 
 539         if (errSecSuccess 
!= err
) 
 546 CFArrayRef 
copyTrustedAppListFromBundle(CFStringRef bundlePath
, CFStringRef trustedAppListFileName
) 
 548         CFStringRef errorString 
= nil
; 
 549     CFURLRef bundleURL
,trustedAppsURL 
= NULL
; 
 550     CFBundleRef secBundle 
= NULL
; 
 551         CFPropertyListRef trustedAppsPlist 
= NULL
; 
 552         CFDataRef xmlDataRef 
= NULL
; 
 554     CFArrayRef trustedAppList 
= NULL
; 
 555         CFMutableStringRef trustedAppListFileNameWithoutExtension 
= NULL
; 
 557     // Make a CFURLRef from the CFString representation of the bundleĆs path. 
 558     bundleURL 
= CFURLCreateWithFileSystemPath( 
 559         kCFAllocatorDefault
,bundlePath
,kCFURLPOSIXPathStyle
,true); 
 561         CFRange wholeStrRange
; 
 566     // Make a bundle instance using the URLRef. 
 567     secBundle 
= CFBundleCreate(kCFAllocatorDefault
,bundleURL
); 
 571         trustedAppListFileNameWithoutExtension 
= 
 572                 CFStringCreateMutableCopy(NULL
,CFStringGetLength(trustedAppListFileName
),trustedAppListFileName
); 
 573         wholeStrRange 
= CFStringFind(trustedAppListFileName
,CFSTR(".plist"),0); 
 575         CFStringDelete(trustedAppListFileNameWithoutExtension
,wholeStrRange
); 
 577     // Look for a resource in the bundle by name and type 
 578     trustedAppsURL 
= CFBundleCopyResourceURL(secBundle
,trustedAppListFileNameWithoutExtension
,CFSTR("plist"),NULL
); 
 582     if ( trustedAppListFileNameWithoutExtension 
) 
 583                 CFRelease(trustedAppListFileNameWithoutExtension
); 
 585         if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault
,trustedAppsURL
,&xmlDataRef
,NULL
,NULL
,&errorCode
)) 
 588         trustedAppsPlist 
= CFPropertyListCreateFromXMLData(kCFAllocatorDefault
,xmlDataRef
,kCFPropertyListImmutable
,&errorString
); 
 589     trustedAppList 
= (CFArrayRef
)trustedAppsPlist
; 
 593         CFRelease(bundleURL
); 
 595         CFRelease(secBundle
); 
 597         CFRelease(trustedAppsURL
); 
 599         CFRelease(xmlDataRef
); 
 601         CFRelease(errorString
); 
 603     return trustedAppList
; 
 606 OSStatus 
SecAccessCreateWithTrustedApplications(CFStringRef trustedApplicationsPListPath
, CFStringRef accessLabel
, Boolean allowAny
, SecAccessRef
* returnedAccess
) 
 608         OSStatus err 
= errSecSuccess
; 
 609         SecAccessRef accessToReturn
=nil
; 
 610         CFMutableArrayRef trustedApplications
=nil
; 
 612         if (!allowAny
) // use default access ("confirm access") 
 614                 // make an exception list of applications you want to trust, 
 615                 // which are allowed to access the item without requiring user confirmation 
 616                 SecTrustedApplicationRef myself
=NULL
, someOther
=NULL
; 
 617         CFArrayRef trustedAppListFromBundle
=NULL
; 
 619         trustedApplications
=CFArrayCreateMutable(kCFAllocatorDefault
,0,&kCFTypeArrayCallBacks
); 
 620         err 
= SecTrustedApplicationCreateFromPath(NULL
, &myself
); 
 622             CFArrayAppendValue(trustedApplications
,myself
); 
 624                 CFURLRef url 
= CFURLCreateWithFileSystemPath(NULL
, trustedApplicationsPListPath
, kCFURLPOSIXPathStyle
, 0); 
 625                 CFStringRef leafStr 
= NULL
; 
 626                 leafStr 
= CFURLCopyLastPathComponent(url
); 
 628                 CFURLRef bndlPathURL 
= NULL
; 
 629                 bndlPathURL 
= CFURLCreateCopyDeletingLastPathComponent(NULL
, url
); 
 630                 CFStringRef bndlPath 
= NULL
; 
 631                 bndlPath 
= CFURLCopyFileSystemPath(bndlPathURL
, kCFURLPOSIXPathStyle
); 
 632         trustedAppListFromBundle
=copyTrustedAppListFromBundle(bndlPath
, leafStr
); 
 640                         CFRelease(bndlPathURL
); 
 641         if (trustedAppListFromBundle
) 
 644             char buffer
[MAXPATHLEN
]; 
 645             top 
= CFArrayGetCount(trustedAppListFromBundle
); 
 646             for (ix
=0;ix
<top
;ix
++) 
 648                 CFStringRef filename 
= (CFStringRef
)CFArrayGetValueAtIndex(trustedAppListFromBundle
,ix
); 
 649                 CFIndex stringLength 
= CFStringGetLength(filename
); 
 652                 if (stringLength 
!= CFStringGetBytes(filename
,CFRangeMake(0,stringLength
),kCFStringEncodingUTF8
,0, 
 653                     false,(UInt8 
*)&buffer
,MAXPATHLEN
, &usedBufLen
)) 
 655                 buffer
[usedBufLen
] = 0; 
 657                                 // Support specification of trusted applications by either 
 658                                 // a full pathname or a code requirement string. 
 662                                         err 
= SecTrustedApplicationCreateFromPath(buffer
,&someOther
); 
 667                                         CFStringRef reqStr 
= filename
; 
 668                                         CFArrayRef descArray 
= CFStringCreateArrayBySeparatingStrings(NULL
, reqStr
, CFSTR("\"")); 
 669                                         if (descArray 
&& (CFArrayGetCount(descArray
) > 1)) 
 671                                                 CFStringRef descStr 
= (CFStringRef
) CFArrayGetValueAtIndex(descArray
, 1); 
 673                                                         buf 
= CFStringToCString(descStr
); 
 675                                         SecRequirementRef reqRef 
= NULL
; 
 676                                         err 
= SecRequirementCreateWithString(reqStr
, kSecCSDefaultFlags
, &reqRef
); 
 678                                                 err 
= SecTrustedApplicationCreateFromRequirement((const char *)buf
, reqRef
, &someOther
); 
 681                                         CFReleaseSafe(reqRef
); 
 682                                         CFReleaseSafe(descArray
); 
 685                     CFArrayAppendValue(trustedApplications
,someOther
); 
 688                                         CFReleaseNull(someOther
); 
 690             CFRelease(trustedAppListFromBundle
); 
 694         err 
= SecAccessCreate((CFStringRef
)accessLabel
, (CFArrayRef
)trustedApplications
, &accessToReturn
); 
 697                 if (allowAny
) // change access to be wide-open for decryption ("always allow access") 
 699                         // get the access control list for decryption operations 
 700                         CFArrayRef aclList
=nil
; 
 701                         err 
= SecAccessCopySelectedACLList(accessToReturn
, CSSM_ACL_AUTHORIZATION_DECRYPT
, &aclList
); 
 704                                 // get the first entry in the access control list 
 705                                 SecACLRef aclRef
=(SecACLRef
)CFArrayGetValueAtIndex(aclList
, 0); 
 706                                 CFArrayRef appList
=nil
; 
 707                                 CFStringRef promptDescription
=nil
; 
 708                                 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector
; 
 709                                 err 
= SecACLCopySimpleContents(aclRef
, &appList
, &promptDescription
, &promptSelector
); 
 711                                 // modify the default ACL to not require the passphrase, and have a nil application list 
 712                                 promptSelector
.flags 
&= ~CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE
; 
 713                                 err 
= SecACLSetSimpleContents(aclRef
, NULL
, promptDescription
, &promptSelector
); 
 715                                 if (appList
) CFRelease(appList
); 
 716                                 if (promptDescription
) CFRelease(promptDescription
); 
 720         *returnedAccess 
= accessToReturn
;