]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_keychain/lib/SecAccess.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_keychain / lib / SecAccess.cpp
diff --git a/Security/libsecurity_keychain/lib/SecAccess.cpp b/Security/libsecurity_keychain/lib/SecAccess.cpp
new file mode 100644 (file)
index 0000000..239f4f5
--- /dev/null
@@ -0,0 +1,715 @@
+/*
+ * 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 <SecBase.h>
+#include <Security/SecAccess.h>
+#include <Security/SecAccessPriv.h>
+#include <Security/SecTrustedApplication.h>
+#include <Security/SecTrustedApplicationPriv.h>
+#include <security_keychain/Access.h>
+#include "SecBridge.h"
+#include <sys/param.h>
+
+#undef secdebug
+#include <utilities/SecCFWrappers.h>
+
+
+/* No restrictions. Permission to perform all operations on
+   the resource or available to an ACL owner.  */
+
+
+CFTypeRef kSecACLAuthorizationAny = (CFTypeRef)(CFSTR("ACLAuthorizationAny"));
+
+CFTypeRef kSecACLAuthorizationLogin = (CFTypeRef)(CFSTR("ACLAuthorizationLogin"));
+CFTypeRef kSecACLAuthorizationGenKey = (CFTypeRef)(CFSTR("ACLAuthorizationGenKey"));
+CFTypeRef kSecACLAuthorizationDelete = (CFTypeRef)(CFSTR("ACLAuthorizationDelete"));
+CFTypeRef kSecACLAuthorizationExportWrapped = (CFTypeRef)(CFSTR("ACLAuthorizationExportWrapped"));
+CFTypeRef kSecACLAuthorizationExportClear = (CFTypeRef)(CFSTR("ACLAuthorizationExportClear"));
+CFTypeRef kSecACLAuthorizationImportWrapped = (CFTypeRef)(CFSTR("ACLAuthorizationImportWrapped"));
+CFTypeRef kSecACLAuthorizationImportClear = (CFTypeRef)(CFSTR("ACLAuthorizationImportClear"));
+CFTypeRef kSecACLAuthorizationSign = (CFTypeRef)(CFSTR("ACLAuthorizationSign"));
+CFTypeRef kSecACLAuthorizationEncrypt = (CFTypeRef)(CFSTR("ACLAuthorizationEncrypt"));
+CFTypeRef kSecACLAuthorizationDecrypt = (CFTypeRef)(CFSTR("ACLAuthorizationDecrypt"));
+CFTypeRef kSecACLAuthorizationMAC = (CFTypeRef)(CFSTR("ACLAuthorizationMAC"));
+CFTypeRef kSecACLAuthorizationDerive = (CFTypeRef)(CFSTR("ACLAuthorizationDerive"));
+
+/* Defined authorization tag values for Keychain */
+
+
+
+CFTypeRef kSecACLAuthorizationKeychainCreate = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainCreate"));
+CFTypeRef kSecACLAuthorizationKeychainDelete = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainDelete"));
+CFTypeRef kSecACLAuthorizationKeychainItemRead = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainItemRead"));
+CFTypeRef kSecACLAuthorizationKeychainItemInsert = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainItemInsert"));
+CFTypeRef kSecACLAuthorizationKeychainItemModify = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainItemModify"));
+CFTypeRef kSecACLAuthorizationKeychainItemDelete = (CFTypeRef)(CFSTR("ACLAuthorizationKeychainItemDelete"));
+
+CFTypeRef kSecACLAuthorizationChangeACL = (CFTypeRef)(CFSTR("ACLAuthorizationChangeACL"));
+CFTypeRef kSecACLAuthorizationChangeOwner = (CFTypeRef)(CFSTR("ACLAuthorizationChangeOwner"));
+
+
+static CFArrayRef copyTrustedAppListFromBundle(CFStringRef bundlePath, CFStringRef trustedAppListFileName);
+
+static CFStringRef gKeys[] =
+{
+       (CFStringRef)kSecACLAuthorizationAny,
+       (CFStringRef)kSecACLAuthorizationLogin,
+       (CFStringRef)kSecACLAuthorizationGenKey,
+       (CFStringRef)kSecACLAuthorizationDelete,
+       (CFStringRef)kSecACLAuthorizationExportWrapped,
+       (CFStringRef)kSecACLAuthorizationExportClear,
+       (CFStringRef)kSecACLAuthorizationImportWrapped,
+       (CFStringRef)kSecACLAuthorizationImportClear,
+       (CFStringRef)kSecACLAuthorizationSign,
+       (CFStringRef)kSecACLAuthorizationEncrypt,
+       (CFStringRef)kSecACLAuthorizationDecrypt,
+       (CFStringRef)kSecACLAuthorizationMAC,
+       (CFStringRef)kSecACLAuthorizationDerive,
+
+       /* Defined authorization tag values for Keychain */
+       (CFStringRef)kSecACLAuthorizationKeychainCreate,
+       (CFStringRef)kSecACLAuthorizationKeychainDelete,
+       (CFStringRef)kSecACLAuthorizationKeychainItemRead,
+       (CFStringRef)kSecACLAuthorizationKeychainItemInsert,
+       (CFStringRef)kSecACLAuthorizationKeychainItemModify,
+       (CFStringRef)kSecACLAuthorizationKeychainItemDelete,
+
+       (CFStringRef)kSecACLAuthorizationChangeACL,
+       (CFStringRef)kSecACLAuthorizationChangeOwner
+
+};
+
+static sint32 gValues[] =
+{
+       CSSM_ACL_AUTHORIZATION_ANY,
+       CSSM_ACL_AUTHORIZATION_LOGIN,
+       CSSM_ACL_AUTHORIZATION_GENKEY,
+       CSSM_ACL_AUTHORIZATION_DELETE,
+       CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED,
+       CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR,
+       CSSM_ACL_AUTHORIZATION_IMPORT_WRAPPED,
+       CSSM_ACL_AUTHORIZATION_IMPORT_CLEAR,
+       CSSM_ACL_AUTHORIZATION_SIGN,
+       CSSM_ACL_AUTHORIZATION_ENCRYPT,
+       CSSM_ACL_AUTHORIZATION_DECRYPT,
+       CSSM_ACL_AUTHORIZATION_MAC,
+       CSSM_ACL_AUTHORIZATION_DERIVE,
+       CSSM_ACL_AUTHORIZATION_DBS_CREATE,
+       CSSM_ACL_AUTHORIZATION_DBS_DELETE,
+       CSSM_ACL_AUTHORIZATION_DB_READ,
+       CSSM_ACL_AUTHORIZATION_DB_INSERT,
+       CSSM_ACL_AUTHORIZATION_DB_MODIFY,
+       CSSM_ACL_AUTHORIZATION_DB_DELETE,
+       CSSM_ACL_AUTHORIZATION_CHANGE_ACL,
+       CSSM_ACL_AUTHORIZATION_CHANGE_OWNER
+};
+
+static
+CFDictionaryRef CreateStringToNumDictionary()
+{
+       int numItems = (sizeof(gValues) / sizeof(sint32));
+       CFMutableDictionaryRef tempDict = CFDictionaryCreateMutable(kCFAllocatorDefault, numItems, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+       for (int iCnt = 0; iCnt < numItems; iCnt++)
+       {
+               sint32 aNumber = gValues[iCnt];
+               CFNumberRef aNum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &aNumber);
+
+               CFStringRef aString = gKeys[iCnt];
+               CFDictionaryAddValue(tempDict, aString, aNum);
+               CFRelease(aNum);
+       }
+
+       CFDictionaryRef result = CFDictionaryCreateCopy(kCFAllocatorDefault, tempDict);
+       CFRelease(tempDict);
+       return result;
+
+}
+
+static
+CFDictionaryRef CreateNumToStringDictionary()
+{
+       int numItems = (sizeof(gValues) / sizeof(sint32));
+
+       CFMutableDictionaryRef tempDict = CFDictionaryCreateMutable(kCFAllocatorDefault, numItems, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+       for (int iCnt = 0; iCnt < numItems; iCnt++)
+       {
+               sint32 aNumber = gValues[iCnt];
+               CFNumberRef aNum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &aNumber);
+
+               CFStringRef aString = gKeys[iCnt];
+               CFDictionaryAddValue(tempDict, aNum, aString);
+               CFRelease(aNum);
+
+       }
+
+       CFDictionaryRef result = CFDictionaryCreateCopy(kCFAllocatorDefault, tempDict);
+       CFRelease(tempDict);
+       return result;
+}
+
+
+/* TODO: This should be in some header */
+sint32 GetACLAuthorizationTagFromString(CFStringRef aclStr);
+sint32 GetACLAuthorizationTagFromString(CFStringRef aclStr)
+{
+       if (NULL == aclStr)
+       {
+#ifndef NDEBUG
+               CFShow(CFSTR("GetACLAuthorizationTagFromString aclStr is NULL"));
+#endif
+               return 0;
+       }
+
+       static CFDictionaryRef gACLMapping = NULL;
+
+       if (NULL == gACLMapping)
+       {
+               gACLMapping = CreateStringToNumDictionary();
+       }
+
+       sint32 result = 0;
+       CFNumberRef valueResult = (CFNumberRef)CFDictionaryGetValue(gACLMapping, aclStr);
+       if (NULL != valueResult)
+       {
+               if (!CFNumberGetValue(valueResult, kCFNumberSInt32Type, &result))
+               {
+                       return 0;
+               }
+
+       }
+       else
+       {
+               return 0;
+       }
+
+       return result;
+
+}
+
+/* TODO: This should be in some header */
+CFStringRef GetAuthStringFromACLAuthorizationTag(sint32 tag);
+CFStringRef GetAuthStringFromACLAuthorizationTag(sint32 tag)
+{
+       static CFDictionaryRef gTagMapping = NULL;
+       CFNumberRef aNum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &tag);
+
+       if (NULL == gTagMapping)
+       {
+               gTagMapping = CreateNumToStringDictionary();
+       }
+
+       CFStringRef result = (CFStringRef)kSecACLAuthorizationAny;
+
+       if (NULL != gTagMapping && CFDictionaryContainsKey(gTagMapping, aNum))
+       {
+               result = (CFStringRef)CFDictionaryGetValue(gTagMapping, aNum);
+       }
+       return result;
+}
+
+//
+// CF boilerplate
+//
+CFTypeID SecAccessGetTypeID(void)
+{
+       BEGIN_SECAPI
+       return gTypes().Access.typeID;
+       END_SECAPI1(_kCFRuntimeNotATypeID)
+}
+
+
+//
+// API bridge calls
+//
+/*!
+ *     Create a new SecAccessRef that is set to the default configuration
+ *     of a (newly created) security object.
+ */
+OSStatus SecAccessCreate(CFStringRef descriptor, CFArrayRef trustedList, SecAccessRef *accessRef)
+{
+       BEGIN_SECAPI
+       Required(descriptor);
+       SecPointer<Access> access;
+       if (trustedList) {
+               CFIndex length = CFArrayGetCount(trustedList);
+               ACL::ApplicationList trusted;
+               for (CFIndex n = 0; n < length; n++)
+                       trusted.push_back(TrustedApplication::required(
+                               SecTrustedApplicationRef(CFArrayGetValueAtIndex(trustedList, n))));
+               access = new Access(cfString(descriptor), trusted);
+       } else {
+               access = new Access(cfString(descriptor));
+       }
+       Required(accessRef) = access->handle();
+       END_SECAPI
+}
+
+
+/*!
+ */
+OSStatus SecAccessCreateFromOwnerAndACL(const CSSM_ACL_OWNER_PROTOTYPE *owner,
+       uint32 aclCount, const CSSM_ACL_ENTRY_INFO *acls,
+       SecAccessRef *accessRef)
+{
+       BEGIN_SECAPI
+       Required(accessRef);    // preflight
+       SecPointer<Access> access = new Access(Required(owner), aclCount, &Required(acls));
+       *accessRef = access->handle();
+       END_SECAPI
+}
+
+SecAccessRef SecAccessCreateWithOwnerAndACL(uid_t userId, gid_t groupId, SecAccessOwnerType ownerType, CFArrayRef acls, CFErrorRef *error)
+{
+       SecAccessRef result = NULL;
+
+       CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector =
+       {
+               CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION,      // selector version
+               ownerType,
+               userId,
+               groupId
+       };
+
+       CSSM_LIST_ELEMENT subject2 = { NULL, 0 };
+       subject2.Element.Word.Data = (UInt8 *)&selector;
+       subject2.Element.Word.Length = sizeof(selector);
+       CSSM_LIST_ELEMENT subject1 =
+       {
+               &subject2, CSSM_ACL_SUBJECT_TYPE_PROCESS, CSSM_LIST_ELEMENT_WORDID
+       };
+
+       CFIndex numAcls = 0;
+
+       if (NULL != acls)
+       {
+               numAcls = CFArrayGetCount(acls);
+       }
+
+#ifndef NDEBUG
+       CFStringRef debugStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
+               CFSTR("SecAccessCreateWithOwnerAndACL: processing %d acls"), (int)numAcls);
+       CFShow(debugStr);
+       CFRelease(debugStr);
+#endif
+
+       CSSM_ACL_AUTHORIZATION_TAG rights[numAcls];
+       memset(rights, 0, sizeof(rights));
+
+       for (CFIndex iCnt = 0; iCnt < numAcls; iCnt++)
+       {
+               CFStringRef aclStr = (CFStringRef)CFArrayGetValueAtIndex(acls, iCnt);
+
+#ifndef NDEBUG
+               debugStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
+                       CFSTR("SecAccessCreateWithOwnerAndACL: acls[%d] = %@"), (int)iCnt, aclStr);
+
+               CFShow(debugStr);
+               CFRelease(debugStr);
+#endif
+
+               CSSM_ACL_AUTHORIZATION_TAG aTag = GetACLAuthorizationTagFromString(aclStr);
+
+#ifndef NDEBUG
+               debugStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
+                       CFSTR("SecAccessCreateWithOwnerAndACL: rights[%d] = %d"), (int)iCnt, aTag);
+
+               CFShow(debugStr);
+               CFRelease(debugStr);
+#endif
+
+               rights[iCnt] = aTag;
+       }
+
+
+       for (CFIndex iCnt = 0; iCnt < numAcls; iCnt++)
+       {
+#ifndef NDEBUG
+               debugStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
+                       CFSTR("SecAccessCreateWithOwnerAndACL: rights[%d]  = %d"), (int)iCnt, rights[iCnt]);
+
+               CFShow(debugStr);
+               CFRelease(debugStr);
+#endif
+
+
+       }
+
+       CSSM_ACL_OWNER_PROTOTYPE owner =
+       {
+               // TypedSubject
+               { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 },
+               // Delegate
+               false
+       };
+
+
+       // ACL entries (any number, just one here)
+       CSSM_ACL_ENTRY_INFO acl_rights[] =
+       {
+               {
+                       // prototype
+                       {
+                               // TypedSubject
+                               { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 },
+                               false,  // Delegate
+                               // rights for this entry
+                               { (uint32)(sizeof(rights) / sizeof(rights[0])), rights },
+                               // rest is defaulted
+                       }
+               }
+       };
+
+       OSStatus err = SecAccessCreateFromOwnerAndACL(&owner,
+               sizeof(acl_rights) / sizeof(acl_rights[0]), acl_rights, &result);
+
+       if (errSecSuccess != err)
+       {
+               result = NULL;
+               if (NULL != error)
+               {
+                       *error  = CFErrorCreate(kCFAllocatorDefault, CFSTR("FIX ME"), err, NULL);
+               }
+       }
+       return result;
+}
+
+
+/*!
+ */
+OSStatus SecAccessGetOwnerAndACL(SecAccessRef accessRef,
+       CSSM_ACL_OWNER_PROTOTYPE_PTR *owner,
+       uint32 *aclCount, CSSM_ACL_ENTRY_INFO_PTR *acls)
+{
+       BEGIN_SECAPI
+       Access::required(accessRef)->copyOwnerAndAcl(
+               Required(owner), Required(aclCount), Required(acls));
+       END_SECAPI
+}
+
+OSStatus SecAccessCopyOwnerAndACL(SecAccessRef accessRef, uid_t* userId, gid_t* groupId, SecAccessOwnerType* ownerType, CFArrayRef* aclList)
+{
+       CSSM_ACL_OWNER_PROTOTYPE_PTR owner = NULL;
+       CSSM_ACL_ENTRY_INFO_PTR acls = NULL;
+       uint32 aclCount = 0;
+       OSStatus result = SecAccessGetOwnerAndACL(accessRef, &owner, &aclCount, &acls);
+       if (errSecSuccess != result )
+       {
+               return result;
+       }
+
+       if (NULL != owner)
+       {
+               CSSM_LIST_ELEMENT_PTR listHead = owner->TypedSubject.Head;
+               if (listHead != NULL && listHead->ElementType == CSSM_LIST_ELEMENT_WORDID)
+               {
+                       CSSM_LIST_ELEMENT_PTR nextElement = listHead->NextElement;
+                       if (listHead->WordID == CSSM_ACL_SUBJECT_TYPE_PROCESS && listHead->ElementType == CSSM_LIST_ELEMENT_WORDID)
+                       {
+                               // nextElement contains the required data
+                               CSSM_ACL_PROCESS_SUBJECT_SELECTOR* selectorPtr = (CSSM_ACL_PROCESS_SUBJECT_SELECTOR*)nextElement->Element.Word.Data;
+                               if (NULL != selectorPtr)
+                               {
+                                       if (NULL != userId)
+                                       {
+                                               *userId = (uid_t)selectorPtr->uid;
+                                       }
+
+                                       if (NULL != groupId)
+                                       {
+                                               *groupId = (gid_t)selectorPtr->gid;
+                                       }
+
+                                       if (NULL != ownerType)
+                                       {
+                                               *ownerType = (SecAccessOwnerType)selectorPtr->mask;
+                                       }
+                               }
+                       }
+
+               }
+
+       }
+
+       if (NULL != aclList)
+       {
+#ifndef NDEBUG
+               CFShow(CFSTR("SecAccessCopyOwnerAndACL: processing the ACL list"));
+#endif
+
+               CFMutableArrayRef stringArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
+               CSSM_ACL_OWNER_PROTOTYPE_PTR protoPtr = NULL;
+               uint32 numAcls = 0L;
+               CSSM_ACL_ENTRY_INFO_PTR aclEntry = NULL;
+
+               result = SecAccessGetOwnerAndACL(accessRef, &protoPtr, &numAcls, &aclEntry);
+               if (errSecSuccess == result)
+               {
+#ifndef NDEBUG
+                       CFStringRef tempStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("SecAccessCopyOwnerAndACL: numAcls = %d"), numAcls);
+                       CFShow(tempStr);
+                       CFRelease(tempStr);
+#endif
+
+                       for (uint32 iCnt = 0; iCnt < numAcls; iCnt++)
+                       {
+                               CSSM_ACL_ENTRY_PROTOTYPE prototype = aclEntry[iCnt].EntryPublicInfo;
+                               CSSM_AUTHORIZATIONGROUP authGroup = prototype.Authorization;
+                               int numAuthTags = (int)authGroup.NumberOfAuthTags;
+
+                               for (int jCnt = 0; jCnt < numAuthTags; jCnt++)
+                               {
+
+                                       sint32 aTag = authGroup.AuthTags[jCnt];
+                                       CFStringRef aString = GetAuthStringFromACLAuthorizationTag(aTag);
+
+                                       CFArrayAppendValue(stringArray, aString);
+                               }
+                       }
+               }
+
+               if (NULL != stringArray)
+               {
+                       if (0 < CFArrayGetCount(stringArray))
+                       {
+                               *aclList = CFArrayCreateCopy(kCFAllocatorDefault, stringArray);
+                       }
+                       CFRelease(stringArray);
+               }
+       }
+
+       return result;
+}
+
+/*!
+ */
+OSStatus SecAccessCopyACLList(SecAccessRef accessRef,
+       CFArrayRef *aclList)
+{
+       BEGIN_SECAPI
+       Required(aclList) = Access::required(accessRef)->copySecACLs();
+       END_SECAPI
+}
+
+
+/*!
+ */
+OSStatus SecAccessCopySelectedACLList(SecAccessRef accessRef,
+       CSSM_ACL_AUTHORIZATION_TAG action,
+       CFArrayRef *aclList)
+{
+       BEGIN_SECAPI
+       Required(aclList) = Access::required(accessRef)->copySecACLs(action);
+       END_SECAPI
+}
+
+CFArrayRef SecAccessCopyMatchingACLList(SecAccessRef accessRef, CFTypeRef authorizationTag)
+{
+       CFArrayRef result = NULL;
+       CSSM_ACL_AUTHORIZATION_TAG tag = GetACLAuthorizationTagFromString((CFStringRef)authorizationTag);
+       OSStatus err = SecAccessCopySelectedACLList(accessRef, tag, &result);
+       if (errSecSuccess != err)
+       {
+               result = NULL;
+       }
+       return result;
+}
+
+CFArrayRef copyTrustedAppListFromBundle(CFStringRef bundlePath, CFStringRef trustedAppListFileName)
+{
+       CFStringRef errorString = nil;
+    CFURLRef bundleURL,trustedAppsURL = NULL;
+    CFBundleRef secBundle = NULL;
+       CFPropertyListRef trustedAppsPlist = NULL;
+       CFDataRef xmlDataRef = NULL;
+       SInt32 errorCode;
+    CFArrayRef trustedAppList = NULL;
+       CFMutableStringRef trustedAppListFileNameWithoutExtension = NULL;
+
+    // Make a CFURLRef from the CFString representation of the bundleƕs path.
+    bundleURL = CFURLCreateWithFileSystemPath(
+        kCFAllocatorDefault,bundlePath,kCFURLPOSIXPathStyle,true);
+
+       CFRange wholeStrRange;
+
+       if (!bundleURL)
+        goto xit;
+
+    // Make a bundle instance using the URLRef.
+    secBundle = CFBundleCreate(kCFAllocatorDefault,bundleURL);
+    if (!secBundle)
+        goto xit;
+
+       trustedAppListFileNameWithoutExtension =
+               CFStringCreateMutableCopy(NULL,CFStringGetLength(trustedAppListFileName),trustedAppListFileName);
+       wholeStrRange = CFStringFind(trustedAppListFileName,CFSTR(".plist"),0);
+
+       CFStringDelete(trustedAppListFileNameWithoutExtension,wholeStrRange);
+
+    // Look for a resource in the bundle by name and type
+    trustedAppsURL = CFBundleCopyResourceURL(secBundle,trustedAppListFileNameWithoutExtension,CFSTR("plist"),NULL);
+    if (!trustedAppsURL)
+        goto xit;
+
+    if ( trustedAppListFileNameWithoutExtension )
+               CFRelease(trustedAppListFileNameWithoutExtension);
+
+       if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,trustedAppsURL,&xmlDataRef,NULL,NULL,&errorCode))
+        goto xit;
+
+       trustedAppsPlist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault,xmlDataRef,kCFPropertyListImmutable,&errorString);
+    trustedAppList = (CFArrayRef)trustedAppsPlist;
+
+xit:
+    if (bundleURL)
+        CFRelease(bundleURL);
+    if (secBundle)
+        CFRelease(secBundle);
+    if (trustedAppsURL)
+        CFRelease(trustedAppsURL);
+    if (xmlDataRef)
+        CFRelease(xmlDataRef);
+    if (errorString)
+        CFRelease(errorString);
+
+    return trustedAppList;
+}
+
+OSStatus SecAccessCreateWithTrustedApplications(CFStringRef trustedApplicationsPListPath, CFStringRef accessLabel, Boolean allowAny, SecAccessRef* returnedAccess)
+{
+       OSStatus err = errSecSuccess;
+       SecAccessRef accessToReturn=nil;
+       CFMutableArrayRef trustedApplications=nil;
+
+       if (!allowAny) // use default access ("confirm access")
+       {
+               // make an exception list of applications you want to trust,
+               // which are allowed to access the item without requiring user confirmation
+               SecTrustedApplicationRef myself=NULL, someOther=NULL;
+        CFArrayRef trustedAppListFromBundle=NULL;
+
+        trustedApplications=CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks);
+        err = SecTrustedApplicationCreateFromPath(NULL, &myself);
+        if (!err)
+            CFArrayAppendValue(trustedApplications,myself);
+
+               CFURLRef url = CFURLCreateWithFileSystemPath(NULL, trustedApplicationsPListPath, kCFURLPOSIXPathStyle, 0);
+               CFStringRef leafStr = NULL;
+               leafStr = CFURLCopyLastPathComponent(url);
+
+               CFURLRef bndlPathURL = NULL;
+               bndlPathURL = CFURLCreateCopyDeletingLastPathComponent(NULL, url);
+               CFStringRef bndlPath = NULL;
+               bndlPath = CFURLCopyFileSystemPath(bndlPathURL, kCFURLPOSIXPathStyle);
+        trustedAppListFromBundle=copyTrustedAppListFromBundle(bndlPath, leafStr);
+               if ( leafStr )
+                       CFRelease(leafStr);
+               if ( bndlPath )
+                       CFRelease(bndlPath);
+               if ( url )
+                       CFRelease(url);
+               if ( bndlPathURL )
+                       CFRelease(bndlPathURL);
+        if (trustedAppListFromBundle)
+        {
+            CFIndex ix,top;
+            char buffer[MAXPATHLEN];
+            top = CFArrayGetCount(trustedAppListFromBundle);
+            for (ix=0;ix<top;ix++)
+            {
+                CFStringRef filename = (CFStringRef)CFArrayGetValueAtIndex(trustedAppListFromBundle,ix);
+                CFIndex stringLength = CFStringGetLength(filename);
+                CFIndex usedBufLen;
+
+                if (stringLength != CFStringGetBytes(filename,CFRangeMake(0,stringLength),kCFStringEncodingUTF8,0,
+                    false,(UInt8 *)&buffer,MAXPATHLEN, &usedBufLen))
+                    break;
+                buffer[usedBufLen] = 0;
+                               //
+                               // Support specification of trusted applications by either
+                               // a full pathname or a code requirement string.
+                               //
+                               if (buffer[0]=='/')
+                               {
+                                       err = SecTrustedApplicationCreateFromPath(buffer,&someOther);
+                               }
+                               else
+                               {
+                                       char *buf = NULL;
+                                       CFStringRef reqStr = filename;
+                                       CFArrayRef descArray = CFStringCreateArrayBySeparatingStrings(NULL, reqStr, CFSTR("\""));
+                                       if (descArray && (CFArrayGetCount(descArray) > 1))
+                                       {
+                                               CFStringRef descStr = (CFStringRef) CFArrayGetValueAtIndex(descArray, 1);
+                                               if (descStr)
+                                                       buf = CFStringToCString(descStr);
+                                       }
+                                       SecRequirementRef reqRef = NULL;
+                                       err = SecRequirementCreateWithString(reqStr, kSecCSDefaultFlags, &reqRef);
+                                       if (!err)
+                                               err = SecTrustedApplicationCreateFromRequirement((const char *)buf, reqRef, &someOther);
+                                       if (buf)
+                                               free(buf);
+                                       CFReleaseSafe(reqRef);
+                                       CFReleaseSafe(descArray);
+                               }
+                if (!err)
+                    CFArrayAppendValue(trustedApplications,someOther);
+
+                               if (someOther)
+                                       CFReleaseNull(someOther);
+            }
+            CFRelease(trustedAppListFromBundle);
+        }
+       }
+
+       err = SecAccessCreate((CFStringRef)accessLabel, (CFArrayRef)trustedApplications, &accessToReturn);
+    if (!err)
+       {
+               if (allowAny) // change access to be wide-open for decryption ("always allow access")
+               {
+                       // get the access control list for decryption operations
+                       CFArrayRef aclList=nil;
+                       err = SecAccessCopySelectedACLList(accessToReturn, CSSM_ACL_AUTHORIZATION_DECRYPT, &aclList);
+                       if (!err)
+                       {
+                               // get the first entry in the access control list
+                               SecACLRef aclRef=(SecACLRef)CFArrayGetValueAtIndex(aclList, 0);
+                               CFArrayRef appList=nil;
+                               CFStringRef promptDescription=nil;
+                               CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector;
+                               err = SecACLCopySimpleContents(aclRef, &appList, &promptDescription, &promptSelector);
+
+                               // modify the default ACL to not require the passphrase, and have a nil application list
+                               promptSelector.flags &= ~CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE;
+                               err = SecACLSetSimpleContents(aclRef, NULL, promptDescription, &promptSelector);
+
+                               if (appList) CFRelease(appList);
+                               if (promptDescription) CFRelease(promptDescription);
+                       }
+               }
+       }
+       *returnedAccess = accessToReturn;
+       return err;
+}