SecKeychainAddIToolsPassword.c [plain text]
#include <Security/SecKeychain.h>
#include <Security/SecKeychainItem.h>
#include <Security/SecAccess.h>
#include <Security/SecAccessPriv.h>
#include <Security/SecTrustedApplication.h>
#include <Security/SecACL.h>
#include <CoreFoundation/CoreFoundation.h>
#include <sys/param.h>
static CFArrayRef CopyTrustedAppListFromBundle();
static SecAccessRef createAccess(CFStringRef accessLabel,const int allowAny);
OSStatus SecKeychainAddIToolsPassword(SecKeychainRef keychain, UInt32 accountNameLength, const char *accountName,
UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef)
{
OSStatus err;
SecKeychainItemRef item = nil;
const char *serviceUTF8 = "iTools";
CFStringRef itemLabel = CFSTR("iTools");
const int allowAny = 0;
SecAccessRef access = createAccess(itemLabel, allowAny);
SecKeychainAttribute attrs[] =
{
{ kSecLabelItemAttr, strlen(serviceUTF8), (char *)serviceUTF8 }, { kSecAccountItemAttr, accountNameLength, (char *)accountName },
{ kSecServiceItemAttr, strlen(serviceUTF8), (char *)serviceUTF8 }
};
SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
err = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass,
&attributes,
passwordLength,
(const char *)passwordData,
keychain,
access,
&item);
if (access)
CFRelease(access);
if (item)
CFRelease(item);
return noErr;
}
SecAccessRef createAccess(CFStringRef accessLabel,const int allowAny)
{
OSStatus err;
SecAccessRef access=nil;
CFMutableArrayRef trustedApplications=nil;
if (!allowAny) {
SecTrustedApplicationRef myself=NULL, someOther=NULL;
CFArrayRef trustedAppListFromBundle=NULL;
trustedApplications=CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks);
err = SecTrustedApplicationCreateFromPath(NULL, &myself);
if (!err)
CFArrayAppendValue(trustedApplications,myself);
trustedAppListFromBundle=CopyTrustedAppListFromBundle();
if (trustedAppListFromBundle)
{
int ix,top;
char buffer[MAXPATHLEN];
top = CFArrayGetCount(trustedAppListFromBundle);
for (ix=0;ix<top;ix++)
{
CFStringRef filename = 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;
err = SecTrustedApplicationCreateFromPath(buffer,&someOther);
if (!err)
CFArrayAppendValue(trustedApplications,someOther);
}
CFRelease(trustedAppListFromBundle);
}
}
err = SecAccessCreate((CFStringRef)accessLabel, (CFArrayRef)trustedApplications, &access);
if (err)
return nil;
if (allowAny) {
CFArrayRef aclList=nil;
err = SecAccessCopySelectedACLList(access, CSSM_ACL_AUTHORIZATION_DECRYPT, &aclList);
if (!err)
{
SecACLRef aclRef=(SecACLRef)CFArrayGetValueAtIndex(aclList, 0);
CFArrayRef appList=nil;
CFStringRef promptDescription=nil;
CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector;
err = SecACLCopySimpleContents(aclRef, &appList, &promptDescription, &promptSelector);
promptSelector.flags &= ~CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE;
err = SecACLSetSimpleContents(aclRef, NULL, promptDescription, &promptSelector);
if (appList) CFRelease(appList);
if (promptDescription) CFRelease(promptDescription);
}
}
return access;
}
CFArrayRef CopyTrustedAppListFromBundle()
{
CFStringRef errorString = nil;
CFURLRef bundleURL,trustedAppsURL = NULL;
CFBundleRef secBundle = NULL;
CFPropertyListRef trustedAppsPlist = NULL;
CFDataRef xmlDataRef = NULL;
SInt32 errorCode;
CFArrayRef trustedAppList = NULL;
bundleURL = CFURLCreateWithFileSystemPath(
kCFAllocatorDefault,CFSTR("/System/Library/Frameworks/Security.framework/Resources/"),kCFURLPOSIXPathStyle,true);
if (!bundleURL)
goto xit;
secBundle = CFBundleCreate(kCFAllocatorDefault,bundleURL);
if (!secBundle)
goto xit;
trustedAppsURL = CFBundleCopyResourceURL(secBundle,CFSTR("iToolsTrustedApps"),CFSTR("plist"),NULL);
if (!trustedAppsURL)
goto xit;
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;
}