2 * Copyright (c) 2006, 2007, 2010 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 * Modification History
27 * May 24, 2006 Allan Nathanson (ajn@apple.com)
28 * - adapted (for SystemConfiguration)
30 * May 10, 2006 Dieter Siegmund (dieter@apple.com)
34 #include <Availability.h>
35 #include <TargetConditionals.h>
36 #include <sys/param.h>
37 #include <CoreFoundation/CoreFoundation.h>
38 #include <CoreFoundation/CFBundlePriv.h> // for _CFBundleCopyMainBundleExecutableURL
39 #include <SystemConfiguration/SCPrivate.h> // for _SCErrorSet
40 #include "dy_framework.h"
42 #include "SCPreferencesInternal.h"
47 copyMyExecutablePath(void)
49 char fspath
[MAXPATHLEN
];
50 Boolean isBundle
= FALSE
;
52 CFDataRef path
= NULL
;
55 url
= _CFBundleCopyMainBundleExecutableURL(&isBundle
);
60 ok
= CFURLGetFileSystemRepresentation(url
, TRUE
, (UInt8
*)fspath
, sizeof(fspath
));
65 fspath
[sizeof(fspath
) - 1] = '\0';
70 slash
= strrchr(fspath
, '/');
74 contents
= strstr(fspath
, "/Contents/MacOS/");
75 if ((contents
!= NULL
) &&
76 ((contents
+ sizeof("/Contents/MacOS/") - 1) == slash
)) {
77 path
= CFDataCreate(NULL
, (UInt8
*)fspath
, contents
- fspath
);
83 path
= CFDataCreate(NULL
, (UInt8
*)fspath
, strlen(fspath
));
92 #pragma mark Keychain helper APIs
95 #if (__MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
97 * Create a SecAccessRef with a custom form.
99 * Both the owner and the ACL set allow free access to root,
100 * but nothing to anyone else.
102 * NOTE: This is not the easiest way to build up CSSM data structures
103 * but it is a way that does not depend on any outside software
104 * layers (other than CSSM and Security's Sec* layer, of course).
107 _SCSecAccessCreateForUID(uid_t uid
)
109 SecAccessRef access
= NULL
;
112 // make the "uid/gid" ACL subject
113 // this is a CSSM_LIST_ELEMENT chain
115 CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector
= {
116 CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION
, // version
117 CSSM_ACL_MATCH_UID
, // active fields mask: match uids (only)
118 uid
, // effective user id to match
119 0 // effective group id to match
122 CSSM_LIST_ELEMENT subject2
= {
128 subject2
.Element
.Word
.Data
= (UInt8
*)&selector
;
129 subject2
.Element
.Word
.Length
= sizeof(selector
);
131 CSSM_LIST_ELEMENT subject1
= {
132 &subject2
, // NextElement
133 CSSM_ACL_SUBJECT_TYPE_PROCESS
, // WordID
134 CSSM_LIST_ELEMENT_WORDID
// ElementType
138 // rights granted (replace with individual list if desired)
139 CSSM_ACL_AUTHORIZATION_TAG rights
[] = {
140 CSSM_ACL_AUTHORIZATION_ANY
// everything
143 // owner component (right to change ACL)
144 CSSM_ACL_OWNER_PROTOTYPE owner
= {
146 CSSM_LIST_TYPE_UNKNOWN
, // type of this list
147 &subject1
, // head of the list
148 &subject2
// tail of the list
153 // ACL entries (any number, just one here)
154 CSSM_ACL_ENTRY_INFO acls
[] = {
158 CSSM_LIST_TYPE_UNKNOWN
, // type of this list
159 &subject1
, // head of the list
160 &subject2
// tail of the list
164 sizeof(rights
) / sizeof(rights
[0]), // NumberOfAuthTags
176 status
= SecAccessCreateFromOwnerAndACL(&owner
,
177 sizeof(acls
) / sizeof(acls
[0]),
180 if (status
!= noErr
) {
186 #endif // (__MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
189 // one example would be to pass a URL for "/System/Library/CoreServices/SystemUIServer.app"
191 _SCSecAccessCreateForExecutables(CFStringRef label
,
192 CFArrayRef executableURLs
)
194 SecAccessRef access
= NULL
;
195 CFArrayRef aclList
= NULL
;
199 SecTrustedApplicationRef trustedApplication
;
200 CFMutableArrayRef trustedApplications
;
202 trustedApplications
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
204 // Use default access ("confirm access")
206 // Next, we make an exception list of applications you want to trust.
207 // These applications will be allowed to access the item without requiring
208 // user confirmation.
210 // Trust the calling application
211 status
= SecTrustedApplicationCreateFromPath(NULL
, &trustedApplication
);
212 if (status
== noErr
) {
213 CFArrayAppendValue(trustedApplications
, trustedApplication
);
214 CFRelease(trustedApplication
);
217 n
= (executableURLs
!= NULL
) ? CFArrayGetCount(executableURLs
) : 0;
218 for (i
= 0; i
< n
; i
++) {
220 char path
[MAXPATHLEN
];
223 url
= CFArrayGetValueAtIndex(executableURLs
, i
);
224 ok
= CFURLGetFileSystemRepresentation(url
, TRUE
, (UInt8
*)path
, sizeof(path
));
229 status
= SecTrustedApplicationCreateFromPath(path
, &trustedApplication
);
230 if (status
== noErr
) {
231 CFArrayAppendValue(trustedApplications
, trustedApplication
);
232 CFRelease(trustedApplication
);
236 status
= SecAccessCreate(label
, trustedApplications
, &access
);
237 if (status
!= noErr
) {
243 if (aclList
!= NULL
) CFRelease(aclList
);
244 CFRelease(trustedApplications
);
248 #endif // !TARGET_OS_IPHONE
252 _SCSecKeychainCopySystemKeychain(void)
254 #if !TARGET_OS_IPHONE
255 SecPreferencesDomain domain
;
256 SecKeychainRef keychain
= NULL
;
259 status
= SecKeychainGetPreferenceDomain(&domain
);
260 if (status
!= noErr
) {
265 status
= SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem
);
266 if (status
!= noErr
) {
271 status
= SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem
, &keychain
);
272 if (status
!= noErr
) {
274 (void) SecKeychainSetPreferenceDomain(domain
);
275 if (keychain
!= NULL
) CFRelease(keychain
);
279 status
= SecKeychainSetPreferenceDomain(domain
);
280 if (status
!= noErr
) {
282 if (keychain
!= NULL
) CFRelease(keychain
);
287 #else // !TARGET_OS_IPHONE
288 _SCErrorSet(kSCStatusAccessError
);
290 #endif // !TARGET_OS_IPHONE
294 #if !TARGET_OS_IPHONE
296 findKeychainItem(SecKeychainRef keychain
,
297 CFStringRef unique_id
,
298 SecKeychainItemRef
*item
)
300 CFMutableDictionaryRef query
;
303 query
= CFDictionaryCreateMutable(NULL
,
305 &kCFTypeDictionaryKeyCallBacks
,
306 &kCFTypeDictionaryValueCallBacks
);
307 if (keychain
!= NULL
) {
308 CFArrayRef keychains
;
310 keychains
= CFArrayCreate(NULL
, (const void **)&keychain
, 1, &kCFTypeArrayCallBacks
);
311 CFDictionarySetValue(query
, kSecMatchSearchList
, keychains
);
312 CFRelease(keychains
);
314 CFDictionarySetValue(query
, kSecClass
, kSecClassGenericPassword
);
315 CFDictionarySetValue(query
, kSecAttrService
, unique_id
);
316 CFDictionarySetValue(query
, kSecReturnRef
, kCFBooleanTrue
);
317 status
= SecItemCopyMatching(query
, (CFTypeRef
*)item
);
322 #endif // !TARGET_OS_IPHONE
326 _SCSecKeychainPasswordItemCopy(SecKeychainRef keychain
,
327 CFStringRef unique_id
)
329 #if !TARGET_OS_IPHONE
330 SecKeychainItemRef item
= NULL
;
331 CFDataRef keychain_password
= NULL
;
334 status
= findKeychainItem(keychain
, unique_id
, &item
);
335 if (status
== noErr
) {
339 status
= SecKeychainItemCopyContent(item
, NULL
, NULL
, &pw_len
, &pw
);
340 if (status
== noErr
) {
341 keychain_password
= CFDataCreate(NULL
, pw
, pw_len
);
342 status
= SecKeychainItemFreeContent(NULL
, pw
);
345 if (item
!= NULL
) CFRelease(item
);
346 if (status
!= noErr
) {
350 return keychain_password
;
351 #else // !TARGET_OS_IPHONE
352 _SCErrorSet(kSCStatusAccessError
);
354 #endif // !TARGET_OS_IPHONE
359 _SCSecKeychainPasswordItemExists(SecKeychainRef keychain
, CFStringRef unique_id
)
361 #if !TARGET_OS_IPHONE
362 SecKeychainItemRef item
;
365 status
= findKeychainItem(keychain
, unique_id
, &item
);
366 if (status
!= noErr
) {
373 #else // !TARGET_OS_IPHONE
374 _SCErrorSet(kSCStatusAccessError
);
376 #endif // !TARGET_OS_IPHONE
381 _SCSecKeychainPasswordItemRemove(SecKeychainRef keychain
, CFStringRef unique_id
)
383 #if !TARGET_OS_IPHONE
384 SecKeychainItemRef item
;
387 status
= findKeychainItem(keychain
, unique_id
, &item
);
388 if (status
!= noErr
) {
393 status
= SecKeychainItemDelete(item
);
395 if (status
!= noErr
) {
401 #else // !TARGET_OS_IPHONE
402 _SCErrorSet(kSCStatusAccessError
);
404 #endif // !TARGET_OS_IPHONE
409 _SCSecKeychainPasswordItemSet(SecKeychainRef keychain
,
410 CFStringRef unique_id
,
412 CFStringRef description
,
415 CFDictionaryRef options
)
417 #if !TARGET_OS_IPHONE
418 SecAccessRef access
= NULL
;
419 CFBooleanRef allowRoot
= NULL
;
420 CFArrayRef allowedExecutables
= NULL
;
421 SecKeychainAttribute attributes
[4];
422 SecKeychainAttributeList attributeList
= { 0, attributes
};
424 SecKeychainItemRef item
= NULL
;
428 if (options
!= NULL
) {
429 if (isA_CFDictionary(options
)) {
430 allowRoot
= CFDictionaryGetValue(options
, kSCKeychainOptionsAllowRoot
);
431 allowedExecutables
= CFDictionaryGetValue(options
, kSCKeychainOptionsAllowedExecutables
);
433 _SCErrorSet(kSCStatusInvalidArgument
);
438 if (!isA_CFString(unique_id
) ||
439 ((label
!= NULL
) && !isA_CFString (label
)) ||
440 ((description
!= NULL
) && !isA_CFString (description
)) ||
441 ((account
!= NULL
) && !isA_CFString (account
)) ||
442 ((password
!= NULL
) && !isA_CFData (password
)) ||
443 ((allowRoot
!= NULL
) && !isA_CFBoolean(allowRoot
)) ||
444 ((allowedExecutables
!= NULL
) && !isA_CFArray (allowedExecutables
)) ||
445 ((allowRoot
!= NULL
) && (allowedExecutables
!= NULL
))) {
446 _SCErrorSet(kSCStatusInvalidArgument
);
450 if ((allowRoot
!= NULL
) && CFBooleanGetValue(allowRoot
)) {
451 #if (__MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
452 access
= _SCSecAccessCreateForUID(0);
453 if (access
== NULL
) {
456 #else // (__MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
457 CFErrorRef error
= NULL
;
459 access
= SecAccessCreateWithOwnerAndACL(0, 0, kSecUseOnlyUID
, NULL
, &error
);
460 if (access
== NULL
) {
461 CFIndex code
= kSCStatusAccessError
;
465 code
= CFErrorGetCode(error
);
471 #endif // (__MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
472 } else if (allowedExecutables
!= NULL
) {
473 access
= _SCSecAccessCreateForExecutables(label
, allowedExecutables
);
474 if (access
== NULL
) {
479 for (i
= 0; i
< 4; i
++) {
480 CFStringRef str
= NULL
;
481 SecKeychainAttrType tag
= 0;
486 tag
= kSecServiceItemAttr
;
490 tag
= kSecLabelItemAttr
;
494 tag
= kSecDescriptionItemAttr
;
498 tag
= kSecAccountItemAttr
;
506 attributes
[n
].tag
= tag
;
507 attributes
[n
].data
= _SC_cfstring_to_cstring(str
, NULL
, 0, kCFStringEncodingUTF8
);
508 attributes
[n
].length
= strlen(attributes
[n
].data
);
512 status
= findKeychainItem(keychain
, unique_id
, &item
);
515 const void *pw
= NULL
;
518 // keychain item exists
519 if (password
!= NULL
) {
520 pw
= CFDataGetBytePtr(password
);
521 pw_len
= CFDataGetLength(password
);
524 attributeList
.count
= n
;
525 status
= SecKeychainItemModifyContent(item
,
532 case errSecItemNotFound
: {
534 if (password
== NULL
) {
535 // creating new keychain item and password not specified
536 status
= kSCStatusInvalidArgument
;
540 attributeList
.count
= n
;
541 status
= SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass
,
543 CFDataGetLength(password
),
544 CFDataGetBytePtr(password
),
558 if (access
!= NULL
) CFRelease(access
);
559 if (item
!= NULL
) CFRelease(item
);
561 for (i
= 0; i
< n
; i
++) {
562 CFAllocatorDeallocate(NULL
, attributes
[i
].data
);
565 if (status
!= noErr
) {
571 #else // !TARGET_OS_IPHONE
572 _SCErrorSet(kSCStatusAccessError
);
574 #endif // !TARGET_OS_IPHONE
579 #pragma mark "System" Keychain APIs (w/SCPreferences)
582 #include "SCHelper_client.h"
586 #include <sys/errno.h>
589 #if !TARGET_OS_IPHONE
591 __SCPreferencesSystemKeychainPasswordItemCopy_helper(SCPreferencesRef prefs
,
592 CFStringRef unique_id
)
594 CFDataRef data
= NULL
;
596 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
597 uint32_t status
= kSCStatusOK
;
598 CFDataRef reply
= NULL
;
600 if (prefsPrivate
->helper_port
== MACH_PORT_NULL
) {
601 ok
= __SCPreferencesCreate_helper(prefs
);
607 ok
= _SCSerializeString(unique_id
, &data
, NULL
, NULL
);
612 // have the helper set the "System" Keychain password
613 ok
= _SCHelperExec(prefsPrivate
->helper_port
,
614 SCHELPER_MSG_KEYCHAIN_COPY
,
618 if (data
!= NULL
) CFRelease(data
);
623 if (status
!= kSCStatusOK
) {
632 if (prefsPrivate
->helper_port
!= MACH_PORT_NULL
) {
633 _SCHelperClose(&prefsPrivate
->helper_port
);
636 status
= kSCStatusAccessError
;
641 if (reply
!= NULL
) CFRelease(reply
);
645 #endif // !TARGET_OS_IPHONE
649 _SCPreferencesSystemKeychainPasswordItemCopy(SCPreferencesRef prefs
,
650 CFStringRef unique_id
)
652 #if !TARGET_OS_IPHONE
653 SecKeychainRef keychain
= NULL
;
654 CFDataRef password
= NULL
;
655 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
658 /* sorry, you must provide a session */
659 _SCErrorSet(kSCStatusNoPrefsSession
);
663 if (!isA_CFString(unique_id
)) {
664 _SCErrorSet(kSCStatusInvalidArgument
);
668 if (prefsPrivate
->authorizationData
!= NULL
) {
669 password
= __SCPreferencesSystemKeychainPasswordItemCopy_helper(prefs
, unique_id
);
673 keychain
= _SCSecKeychainCopySystemKeychain();
674 if (keychain
== NULL
) {
678 password
= _SCSecKeychainPasswordItemCopy(keychain
, unique_id
);
682 if (keychain
!= NULL
) CFRelease(keychain
);
684 #else // !TARGET_OS_IPHONE
685 _SCErrorSet(kSCStatusAccessError
);
687 #endif // !TARGET_OS_IPHONE
692 _SCPreferencesSystemKeychainPasswordItemExists(SCPreferencesRef prefs
,
693 CFStringRef unique_id
)
695 #if !TARGET_OS_IPHONE
696 SecKeychainRef keychain
= NULL
;
698 // SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
701 /* sorry, you must provide a session */
702 _SCErrorSet(kSCStatusNoPrefsSession
);
706 if (!isA_CFString(unique_id
)) {
707 _SCErrorSet(kSCStatusInvalidArgument
);
711 // if (prefsPrivate->authorizationData != NULL) {
712 // ok = __SCPreferencesSystemKeychainPasswordItemExists_helper(prefs, unique_id);
716 keychain
= _SCSecKeychainCopySystemKeychain();
717 if (keychain
== NULL
) {
721 ok
= _SCSecKeychainPasswordItemExists(keychain
, unique_id
);
725 if (keychain
!= NULL
) CFRelease(keychain
);
727 #else // !TARGET_OS_IPHONE
728 _SCErrorSet(kSCStatusAccessError
);
730 #endif // !TARGET_OS_IPHONE
734 #if !TARGET_OS_IPHONE
736 __SCPreferencesSystemKeychainPasswordItemRemove_helper(SCPreferencesRef prefs
,
737 CFStringRef unique_id
)
739 CFDataRef data
= NULL
;
741 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
742 uint32_t status
= kSCStatusOK
;
743 CFDataRef reply
= NULL
;
745 if (prefsPrivate
->helper_port
== MACH_PORT_NULL
) {
746 ok
= __SCPreferencesCreate_helper(prefs
);
752 ok
= _SCSerializeString(unique_id
, &data
, NULL
, NULL
);
757 // have the helper set the "System" Keychain password
758 ok
= _SCHelperExec(prefsPrivate
->helper_port
,
759 SCHELPER_MSG_KEYCHAIN_REMOVE
,
763 if (data
!= NULL
) CFRelease(data
);
768 if (status
!= kSCStatusOK
) {
777 if (prefsPrivate
->helper_port
!= MACH_PORT_NULL
) {
778 _SCHelperClose(&prefsPrivate
->helper_port
);
781 status
= kSCStatusAccessError
;
786 if (reply
!= NULL
) CFRelease(reply
);
790 #endif // !TARGET_OS_IPHONE
794 _SCPreferencesSystemKeychainPasswordItemRemove(SCPreferencesRef prefs
,
795 CFStringRef unique_id
)
797 #if !TARGET_OS_IPHONE
798 SecKeychainRef keychain
= NULL
;
800 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
803 /* sorry, you must provide a session */
804 _SCErrorSet(kSCStatusNoPrefsSession
);
808 if (!isA_CFString(unique_id
)) {
809 _SCErrorSet(kSCStatusInvalidArgument
);
813 if (prefsPrivate
->authorizationData
!= NULL
) {
814 ok
= __SCPreferencesSystemKeychainPasswordItemRemove_helper(prefs
, unique_id
);
818 keychain
= _SCSecKeychainCopySystemKeychain();
819 if (keychain
== NULL
) {
823 ok
= _SCSecKeychainPasswordItemRemove(keychain
, unique_id
);
827 if (keychain
!= NULL
) CFRelease(keychain
);
829 #else // !TARGET_OS_IPHONE
830 _SCErrorSet(kSCStatusAccessError
);
832 #endif // !TARGET_OS_IPHONE
836 #if !TARGET_OS_IPHONE
838 __SCPreferencesSystemKeychainPasswordItemSet_helper(SCPreferencesRef prefs
,
839 CFStringRef unique_id
,
841 CFStringRef description
,
844 CFDictionaryRef options
)
846 CFDataRef data
= NULL
;
847 CFMutableDictionaryRef newOptions
= NULL
;
849 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
850 uint32_t status
= kSCStatusOK
;
851 CFDataRef reply
= NULL
;
853 if (prefsPrivate
->helper_port
== MACH_PORT_NULL
) {
854 ok
= __SCPreferencesCreate_helper(prefs
);
860 if (isA_CFDictionary(options
)) {
861 CFArrayRef executableURLs
= NULL
;
863 newOptions
= CFDictionaryCreateMutableCopy(NULL
, 0, options
);
865 if (CFDictionaryGetValueIfPresent(newOptions
,
866 kSCKeychainOptionsAllowedExecutables
,
867 (const void **)&executableURLs
)) {
868 CFMutableArrayRef executablePaths
;
873 executablePaths
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
875 path
= copyMyExecutablePath();
877 CFArrayAppendValue(executablePaths
, path
);
881 n
= CFArrayGetCount(executableURLs
);
882 for (i
= 0; i
< n
; i
++) {
883 char fspath
[MAXPATHLEN
];
886 url
= CFArrayGetValueAtIndex(executableURLs
, i
);
887 ok
= CFURLGetFileSystemRepresentation(url
, TRUE
, (UInt8
*)fspath
, sizeof(fspath
));
891 fspath
[sizeof(fspath
) - 1] = '\0';
892 path
= CFDataCreate(NULL
, (UInt8
*)fspath
, strlen(fspath
));
893 CFArrayAppendValue(executablePaths
, path
);
897 CFDictionarySetValue(newOptions
, kSCKeychainOptionsAllowedExecutables
, executablePaths
);
898 CFRelease(executablePaths
);
901 newOptions
= CFDictionaryCreateMutable(NULL
,
903 &kCFTypeDictionaryKeyCallBacks
,
904 &kCFTypeDictionaryValueCallBacks
);
907 if (unique_id
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsUniqueID
, unique_id
);
908 if (label
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsLabel
, label
);
909 if (description
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsDescription
, description
);
910 if (account
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsAccount
, account
);
911 if (password
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsPassword
, password
);
914 // if not AllowRoot and a list of executables was not provided than
915 // pass the current executable
917 if (!CFDictionaryContainsKey(newOptions
, kSCKeychainOptionsAllowRoot
) &&
918 !CFDictionaryContainsKey(newOptions
, kSCKeychainOptionsAllowedExecutables
)) {
921 path
= copyMyExecutablePath();
923 CFArrayRef executablePaths
;
925 executablePaths
= CFArrayCreate(NULL
, (const void **)&path
, 1, &kCFTypeArrayCallBacks
);
927 CFDictionarySetValue(newOptions
, kSCKeychainOptionsAllowedExecutables
, executablePaths
);
928 CFRelease(executablePaths
);
932 ok
= _SCSerialize(newOptions
, &data
, NULL
, NULL
);
933 CFRelease(newOptions
);
938 // have the helper create the "System" Keychain password
939 ok
= _SCHelperExec(prefsPrivate
->helper_port
,
940 SCHELPER_MSG_KEYCHAIN_SET
,
944 if (data
!= NULL
) CFRelease(data
);
949 if (status
!= kSCStatusOK
) {
958 if (prefsPrivate
->helper_port
!= MACH_PORT_NULL
) {
959 _SCHelperClose(&prefsPrivate
->helper_port
);
962 status
= kSCStatusAccessError
;
967 if (reply
!= NULL
) CFRelease(reply
);
971 #endif // !TARGET_OS_IPHONE
975 _SCPreferencesSystemKeychainPasswordItemSet(SCPreferencesRef prefs
,
976 CFStringRef unique_id
,
978 CFStringRef description
,
981 CFDictionaryRef options
)
983 #if !TARGET_OS_IPHONE
984 SecKeychainRef keychain
= NULL
;
986 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
989 /* sorry, you must provide a session */
990 _SCErrorSet(kSCStatusNoPrefsSession
);
994 if (!isA_CFString(unique_id
) ||
995 ((label
!= NULL
) && !isA_CFString (label
)) ||
996 ((description
!= NULL
) && !isA_CFString (description
)) ||
997 ((account
!= NULL
) && !isA_CFString (account
)) ||
998 ((password
!= NULL
) && !isA_CFData (password
)) ||
999 ((options
!= NULL
) && !isA_CFDictionary(options
))) {
1000 _SCErrorSet(kSCStatusInvalidArgument
);
1004 if (prefsPrivate
->authorizationData
!= NULL
) {
1005 ok
= __SCPreferencesSystemKeychainPasswordItemSet_helper(prefs
,
1015 keychain
= _SCSecKeychainCopySystemKeychain();
1016 if (keychain
== NULL
) {
1020 ok
= _SCSecKeychainPasswordItemSet(keychain
,
1030 if (keychain
!= NULL
) CFRelease(keychain
);
1032 #else // !TARGET_OS_IPHONE
1033 _SCErrorSet(kSCStatusAccessError
);
1035 #endif // !TARGET_OS_IPHONE