2 * SecKeychainAddIToolsPassword.c
4 * Created by jhurley on Thu Jun 19 2003.
5 * Copyright (c) 2003 Apple. All rights reserved.
7 * Based on Keychain item access control example
8 * Created by Perry Kiehtreiber on Wed Jun 19 2002
9 * Modified by Ken McLeod, Mon Apr 21 2003 -- added "always allow" ACL support
12 #include <Security/SecKeychain.h>
13 #include <Security/SecKeychainItem.h>
14 #include <Security/SecAccess.h>
15 #include <Security/SecAccessPriv.h>
16 #include <Security/SecTrustedApplication.h>
17 #include <Security/SecACL.h>
18 #include <CoreFoundation/CoreFoundation.h>
19 #include <sys/param.h>
21 static CFArrayRef
CopyTrustedAppListFromBundle();
22 static SecAccessRef
createAccess(CFStringRef accessLabel
,const int allowAny
);
24 OSStatus
SecKeychainAddIToolsPassword(SecKeychainRef keychain
, UInt32 accountNameLength
, const char *accountName
,
25 UInt32 passwordLength
, const void *passwordData
, SecKeychainItemRef
*itemRef
)
28 SecKeychainItemRef item
= nil
;
29 const char *serviceUTF8
= "iTools";
30 CFStringRef itemLabel
= CFSTR("iTools");
31 const int allowAny
= 0;
33 // create initial access control settings for the item
34 SecAccessRef access
= createAccess(itemLabel
, allowAny
);
36 // below is the lower-layer equivalent to the SecKeychainAddGenericPassword() function;
37 // it does the same thing (except specify the access controls)
39 // set up attribute vector (each attribute consists of {tag, length, pointer})
40 SecKeychainAttribute attrs
[] =
42 { kSecLabelItemAttr
, strlen(serviceUTF8
), (char *)serviceUTF8
}, // use the service string as the name of this item for display purposes
43 { kSecAccountItemAttr
, accountNameLength
, (char *)accountName
},
44 { kSecServiceItemAttr
, strlen(serviceUTF8
), (char *)serviceUTF8
}
46 SecKeychainAttributeList attributes
= { sizeof(attrs
) / sizeof(attrs
[0]), attrs
};
48 err
= SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass
,
51 (const char *)passwordData
,
63 SecAccessRef
createAccess(CFStringRef accessLabel
,const int allowAny
)
66 SecAccessRef access
=nil
;
67 CFMutableArrayRef trustedApplications
=nil
;
69 if (!allowAny
) // use default access ("confirm access")
71 // make an exception list of applications you want to trust,
72 // which are allowed to access the item without requiring user confirmation
73 SecTrustedApplicationRef myself
=NULL
, someOther
=NULL
;
74 CFArrayRef trustedAppListFromBundle
=NULL
;
76 trustedApplications
=CFArrayCreateMutable(kCFAllocatorDefault
,0,&kCFTypeArrayCallBacks
);
77 err
= SecTrustedApplicationCreateFromPath(NULL
, &myself
);
79 CFArrayAppendValue(trustedApplications
,myself
);
81 trustedAppListFromBundle
=CopyTrustedAppListFromBundle();
82 if (trustedAppListFromBundle
)
85 char buffer
[MAXPATHLEN
];
86 top
= CFArrayGetCount(trustedAppListFromBundle
);
87 for (ix
=0;ix
<top
;ix
++)
89 CFStringRef filename
= CFArrayGetValueAtIndex(trustedAppListFromBundle
,ix
);
90 CFIndex stringLength
= CFStringGetLength(filename
);
92 // CFShow(filename); // debug
94 if (stringLength
!= CFStringGetBytes(filename
,CFRangeMake(0,stringLength
),kCFStringEncodingUTF8
,0,
95 false,(UInt8
*)&buffer
,MAXPATHLEN
, &usedBufLen
))
97 buffer
[usedBufLen
] = 0;
98 // printf("converted filename: [sl=%d, ubl=%d %s\n",stringLength,usedBufLen,buffer);
99 err
= SecTrustedApplicationCreateFromPath(buffer
,&someOther
);
101 CFArrayAppendValue(trustedApplications
,someOther
);
103 CFRelease(trustedAppListFromBundle
);
107 err
= SecAccessCreate((CFStringRef
)accessLabel
, (CFArrayRef
)trustedApplications
, &access
);
111 if (allowAny
) // change access to be wide-open for decryption ("always allow access")
113 // get the access control list for decryption operations
114 CFArrayRef aclList
=nil
;
115 err
= SecAccessCopySelectedACLList(access
, CSSM_ACL_AUTHORIZATION_DECRYPT
, &aclList
);
119 // get the first entry in the access control list
120 SecACLRef aclRef
=(SecACLRef
)CFArrayGetValueAtIndex(aclList
, 0);
121 CFArrayRef appList
=nil
;
122 CFStringRef promptDescription
=nil
;
123 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector
;
124 err
= SecACLCopySimpleContents(aclRef
, &appList
, &promptDescription
, &promptSelector
);
126 // modify the default ACL to not require the passphrase, and have a nil application list
127 promptSelector
.flags
&= ~CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE
;
128 err
= SecACLSetSimpleContents(aclRef
, NULL
, promptDescription
, &promptSelector
);
130 if (appList
) CFRelease(appList
);
131 if (promptDescription
) CFRelease(promptDescription
);
138 CFArrayRef
CopyTrustedAppListFromBundle()
140 CFStringRef errorString
= nil
;
141 CFURLRef bundleURL
,trustedAppsURL
= NULL
;
142 CFBundleRef secBundle
= NULL
;
143 CFPropertyListRef trustedAppsPlist
= NULL
;
144 CFDataRef xmlDataRef
= NULL
;
146 CFArrayRef trustedAppList
= NULL
;
148 // Make a CFURLRef from the CFString representation of the bundleĆs path.
149 bundleURL
= CFURLCreateWithFileSystemPath(
150 kCFAllocatorDefault
,CFSTR("/System/Library/Frameworks/Security.framework/Resources/"),kCFURLPOSIXPathStyle
,true);
154 // Make a bundle instance using the URLRef.
155 secBundle
= CFBundleCreate(kCFAllocatorDefault
,bundleURL
);
159 // Look for a resource in the bundle by name and type
160 trustedAppsURL
= CFBundleCopyResourceURL(secBundle
,CFSTR("iToolsTrustedApps"),CFSTR("plist"),NULL
);
164 if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault
,trustedAppsURL
,&xmlDataRef
,NULL
,NULL
,&errorCode
))
167 trustedAppsPlist
= CFPropertyListCreateFromXMLData(kCFAllocatorDefault
,xmlDataRef
,kCFPropertyListImmutable
,&errorString
);
169 // if (!CFPropertyListIsValid(trustedAppsPlist,kCFPropertyListXMLFormat_v1_0))
173 if (CFGetTypeID(trustedAppsPlist) != CFGetTypeID(trustedAppList))
175 CFRelease(trustedAppsPlist);
179 trustedAppList
= (CFArrayRef
)trustedAppsPlist
;
183 CFRelease(bundleURL
);
185 CFRelease(secBundle
);
187 CFRelease(trustedAppsURL
);
189 CFRelease(xmlDataRef
);
191 CFRelease(errorString
);
193 return trustedAppList
;