OSStatus SecACLCopyContents(SecACLRef acl, CFArrayRef *applicationList, CFStringRef *description, SecKeychainPromptSelector *promptSelector) { CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector; memset(&cdsaPromptSelector, 0, sizeof(cdsaPromptSelector)); OSStatus err = errSecSuccess; err = SecACLCopySimpleContents(acl, applicationList, description, &cdsaPromptSelector); *promptSelector = cdsaPromptSelector.flags; return err; }
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; }