2 * Copyright (c) 2006, 2007, 2010, 2014, 2016, 2017 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 "dy_framework.h"
41 #include "SCPreferencesInternal.h"
46 copyMyExecutablePath(void)
48 char fspath
[MAXPATHLEN
];
49 Boolean isBundle
= FALSE
;
51 CFDataRef path
= NULL
;
54 url
= _CFBundleCopyMainBundleExecutableURL(&isBundle
);
59 ok
= CFURLGetFileSystemRepresentation(url
, TRUE
, (UInt8
*)fspath
, sizeof(fspath
));
64 fspath
[sizeof(fspath
) - 1] = '\0';
69 slash
= strrchr(fspath
, '/');
73 contents
= strstr(fspath
, "/Contents/MacOS/");
74 if ((contents
!= NULL
) &&
75 ((contents
+ sizeof("/Contents/MacOS/") - 1) == slash
)) {
76 path
= CFDataCreate(NULL
, (UInt8
*)fspath
, contents
- fspath
);
82 path
= CFDataCreate(NULL
, (UInt8
*)fspath
, strlen(fspath
));
91 #pragma mark Keychain helper APIs
94 #if (__MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
96 * Create a SecAccessRef with a custom form.
98 * Both the owner and the ACL set allow free access to root,
99 * but nothing to anyone else.
101 * NOTE: This is not the easiest way to build up CSSM data structures
102 * but it is a way that does not depend on any outside software
103 * layers (other than CSSM and Security's Sec* layer, of course).
106 _SCSecAccessCreateForUID(uid_t uid
)
108 SecAccessRef access
= NULL
;
111 // make the "uid/gid" ACL subject
112 // this is a CSSM_LIST_ELEMENT chain
114 CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector
= {
115 CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION
, // version
116 CSSM_ACL_MATCH_UID
, // active fields mask: match uids (only)
117 uid
, // effective user id to match
118 0 // effective group id to match
121 CSSM_LIST_ELEMENT subject2
= {
127 subject2
.Element
.Word
.Data
= (UInt8
*)&selector
;
128 subject2
.Element
.Word
.Length
= sizeof(selector
);
130 CSSM_LIST_ELEMENT subject1
= {
131 &subject2
, // NextElement
132 CSSM_ACL_SUBJECT_TYPE_PROCESS
, // WordID
133 CSSM_LIST_ELEMENT_WORDID
// ElementType
137 // rights granted (replace with individual list if desired)
138 CSSM_ACL_AUTHORIZATION_TAG rights
[] = {
139 CSSM_ACL_AUTHORIZATION_ANY
// everything
142 // owner component (right to change ACL)
143 CSSM_ACL_OWNER_PROTOTYPE owner
= {
145 CSSM_LIST_TYPE_UNKNOWN
, // type of this list
146 &subject1
, // head of the list
147 &subject2
// tail of the list
152 // ACL entries (any number, just one here)
153 CSSM_ACL_ENTRY_INFO acls
[] = {
157 CSSM_LIST_TYPE_UNKNOWN
, // type of this list
158 &subject1
, // head of the list
159 &subject2
// tail of the list
163 sizeof(rights
) / sizeof(rights
[0]), // NumberOfAuthTags
175 status
= SecAccessCreateFromOwnerAndACL(&owner
,
176 sizeof(acls
) / sizeof(acls
[0]),
179 if (status
!= noErr
) {
185 #endif // (__MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
188 // one example would be to pass a URL for "/System/Library/CoreServices/SystemUIServer.app"
190 _SCSecAccessCreateForExecutables(CFStringRef label
,
191 CFArrayRef executableURLs
)
193 SecAccessRef access
= NULL
;
197 SecTrustedApplicationRef trustedApplication
;
198 CFMutableArrayRef trustedApplications
;
200 trustedApplications
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
202 // Use default access ("confirm access")
204 // Next, we make an exception list of applications you want to trust.
205 // These applications will be allowed to access the item without requiring
206 // user confirmation.
208 // Trust the calling application
209 status
= SecTrustedApplicationCreateFromPath(NULL
, &trustedApplication
);
210 if (status
== noErr
) {
211 CFArrayAppendValue(trustedApplications
, trustedApplication
);
212 CFRelease(trustedApplication
);
215 n
= (executableURLs
!= NULL
) ? CFArrayGetCount(executableURLs
) : 0;
216 for (i
= 0; i
< n
; i
++) {
218 char path
[MAXPATHLEN
];
221 url
= CFArrayGetValueAtIndex(executableURLs
, i
);
222 ok
= CFURLGetFileSystemRepresentation(url
, TRUE
, (UInt8
*)path
, sizeof(path
));
227 status
= SecTrustedApplicationCreateFromPath(path
, &trustedApplication
);
228 if (status
== noErr
) {
229 CFArrayAppendValue(trustedApplications
, trustedApplication
);
230 CFRelease(trustedApplication
);
234 status
= SecAccessCreate(label
, trustedApplications
, &access
);
235 if (status
!= noErr
) {
241 CFRelease(trustedApplications
);
245 #endif // !TARGET_OS_IPHONE
249 _SCSecKeychainCopySystemKeychain(void)
251 #if !TARGET_OS_IPHONE
252 SecKeychainRef keychain
= NULL
;
255 status
= SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem
, &keychain
);
256 if (status
!= noErr
) {
258 if (keychain
!= NULL
) CFRelease(keychain
);
263 #else // !TARGET_OS_IPHONE
264 _SCErrorSet(kSCStatusAccessError
);
266 #endif // !TARGET_OS_IPHONE
270 #if !TARGET_OS_IPHONE
272 findKeychainItem(SecKeychainRef keychain
,
273 CFStringRef unique_id
,
274 SecKeychainItemRef
*item
)
276 CFMutableDictionaryRef query
;
279 query
= CFDictionaryCreateMutable(NULL
,
281 &kCFTypeDictionaryKeyCallBacks
,
282 &kCFTypeDictionaryValueCallBacks
);
283 if (keychain
!= NULL
) {
284 CFArrayRef keychains
;
286 keychains
= CFArrayCreate(NULL
, (const void **)&keychain
, 1, &kCFTypeArrayCallBacks
);
287 CFDictionarySetValue(query
, kSecMatchSearchList
, keychains
);
288 CFRelease(keychains
);
290 CFDictionarySetValue(query
, kSecClass
, kSecClassGenericPassword
);
291 CFDictionarySetValue(query
, kSecAttrService
, unique_id
);
292 CFDictionarySetValue(query
, kSecReturnRef
, kCFBooleanTrue
);
293 status
= SecItemCopyMatching(query
, (CFTypeRef
*)item
);
298 #endif // !TARGET_OS_IPHONE
302 _SCSecKeychainPasswordItemCopy(SecKeychainRef keychain
,
303 CFStringRef unique_id
)
305 #if !TARGET_OS_IPHONE
306 SecKeychainItemRef item
= NULL
;
307 CFDataRef keychain_password
= NULL
;
310 status
= findKeychainItem(keychain
, unique_id
, &item
);
311 if (status
== noErr
) {
315 status
= SecKeychainItemCopyContent(item
, NULL
, NULL
, &pw_len
, &pw
);
316 if (status
== noErr
) {
317 keychain_password
= CFDataCreate(NULL
, pw
, pw_len
);
318 status
= SecKeychainItemFreeContent(NULL
, pw
);
321 if (item
!= NULL
) CFRelease(item
);
322 if (status
!= noErr
) {
326 return keychain_password
;
327 #else // !TARGET_OS_IPHONE
328 #pragma unused(keychain)
329 #pragma unused(unique_id)
330 _SCErrorSet(kSCStatusAccessError
);
332 #endif // !TARGET_OS_IPHONE
337 _SCSecKeychainPasswordItemExists(SecKeychainRef keychain
, CFStringRef unique_id
)
339 #if !TARGET_OS_IPHONE
340 SecKeychainItemRef item
;
343 status
= findKeychainItem(keychain
, unique_id
, &item
);
344 if (status
!= noErr
) {
351 #else // !TARGET_OS_IPHONE
352 #pragma unused(keychain)
353 #pragma unused(unique_id)
354 _SCErrorSet(kSCStatusAccessError
);
356 #endif // !TARGET_OS_IPHONE
361 _SCSecKeychainPasswordItemRemove(SecKeychainRef keychain
, CFStringRef unique_id
)
363 #if !TARGET_OS_IPHONE
364 SecKeychainItemRef item
;
367 status
= findKeychainItem(keychain
, unique_id
, &item
);
368 if (status
!= noErr
) {
373 status
= SecKeychainItemDelete(item
);
375 if (status
!= noErr
) {
381 #else // !TARGET_OS_IPHONE
382 #pragma unused(keychain)
383 #pragma unused(unique_id)
384 _SCErrorSet(kSCStatusAccessError
);
386 #endif // !TARGET_OS_IPHONE
391 _SCSecKeychainPasswordItemSet(SecKeychainRef keychain
,
392 CFStringRef unique_id
,
394 CFStringRef description
,
397 CFDictionaryRef options
)
399 #if !TARGET_OS_IPHONE
400 SecAccessRef access
= NULL
;
401 CFBooleanRef allowRoot
= NULL
;
402 CFArrayRef allowedExecutables
= NULL
;
403 SecKeychainAttribute attributes
[4];
404 SecKeychainAttributeList attributeList
= { 0, attributes
};
406 SecKeychainItemRef item
= NULL
;
410 if (options
!= NULL
) {
411 if (isA_CFDictionary(options
)) {
412 allowRoot
= CFDictionaryGetValue(options
, kSCKeychainOptionsAllowRoot
);
413 allowedExecutables
= CFDictionaryGetValue(options
, kSCKeychainOptionsAllowedExecutables
);
415 _SCErrorSet(kSCStatusInvalidArgument
);
420 if (!isA_CFString(unique_id
) ||
421 ((label
!= NULL
) && !isA_CFString (label
)) ||
422 ((description
!= NULL
) && !isA_CFString (description
)) ||
423 ((account
!= NULL
) && !isA_CFString (account
)) ||
424 ((password
!= NULL
) && !isA_CFData (password
)) ||
425 ((allowRoot
!= NULL
) && !isA_CFBoolean(allowRoot
)) ||
426 ((allowedExecutables
!= NULL
) && !isA_CFArray (allowedExecutables
)) ||
427 ((allowRoot
!= NULL
) && (allowedExecutables
!= NULL
))) {
428 _SCErrorSet(kSCStatusInvalidArgument
);
432 if ((allowRoot
!= NULL
) && CFBooleanGetValue(allowRoot
)) {
433 #if (__MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
434 access
= _SCSecAccessCreateForUID(0);
435 if (access
== NULL
) {
438 #else // (__MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
439 CFErrorRef error
= NULL
;
441 access
= SecAccessCreateWithOwnerAndACL(0, 0, kSecUseOnlyUID
, NULL
, &error
);
442 if (access
== NULL
) {
443 CFIndex code
= kSCStatusAccessError
;
447 code
= CFErrorGetCode(error
);
450 _SCErrorSet((int)code
);
453 #endif // (__MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
454 } else if (allowedExecutables
!= NULL
) {
455 access
= _SCSecAccessCreateForExecutables(label
, allowedExecutables
);
456 if (access
== NULL
) {
461 for (i
= 0; i
< 4; i
++) {
462 CFStringRef str
= NULL
;
463 SecKeychainAttrType tag
= 0;
468 tag
= kSecServiceItemAttr
;
472 tag
= kSecLabelItemAttr
;
476 tag
= kSecDescriptionItemAttr
;
480 tag
= kSecAccountItemAttr
;
488 attributes
[n
].tag
= tag
;
489 attributes
[n
].data
= _SC_cfstring_to_cstring(str
, NULL
, 0, kCFStringEncodingUTF8
);
490 attributes
[n
].length
= (UInt32
)strlen(attributes
[n
].data
);
494 status
= findKeychainItem(keychain
, unique_id
, &item
);
497 const void *pw
= NULL
;
500 // keychain item exists
501 if (password
!= NULL
) {
502 pw
= CFDataGetBytePtr(password
);
503 pw_len
= (UInt32
)CFDataGetLength(password
);
506 attributeList
.count
= (UInt32
)n
;
507 status
= SecKeychainItemModifyContent(item
,
514 case errSecItemNotFound
: {
516 if (password
== NULL
) {
517 // creating new keychain item and password not specified
518 status
= kSCStatusInvalidArgument
;
522 attributeList
.count
= (UInt32
)n
;
523 status
= SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass
,
525 (UInt32
)CFDataGetLength(password
),
526 CFDataGetBytePtr(password
),
540 if (access
!= NULL
) CFRelease(access
);
541 if (item
!= NULL
) CFRelease(item
);
543 for (i
= 0; i
< n
; i
++) {
544 CFAllocatorDeallocate(NULL
, attributes
[i
].data
);
547 if (status
!= noErr
) {
553 #else // !TARGET_OS_IPHONE
554 #pragma unused(keychain)
555 #pragma unused(unique_id)
556 #pragma unused(label)
557 #pragma unused(description)
558 #pragma unused(account)
559 #pragma unused(password)
560 #pragma unused(options)
561 _SCErrorSet(kSCStatusAccessError
);
563 #endif // !TARGET_OS_IPHONE
568 #pragma mark "System" Keychain APIs (w/SCPreferences)
571 #include "SCHelper_client.h"
575 #include <sys/errno.h>
578 #if !TARGET_OS_IPHONE
580 __SCPreferencesSystemKeychainPasswordItemCopy_helper(SCPreferencesRef prefs
,
581 CFStringRef unique_id
)
583 CFDataRef data
= NULL
;
585 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
586 uint32_t status
= kSCStatusOK
;
587 CFDataRef reply
= NULL
;
589 if (prefsPrivate
->helper_port
== MACH_PORT_NULL
) {
590 ok
= __SCPreferencesCreate_helper(prefs
);
596 ok
= _SCSerializeString(unique_id
, &data
, NULL
, NULL
);
601 // have the helper set the "System" Keychain password
602 ok
= _SCHelperExec(prefsPrivate
->helper_port
,
603 SCHELPER_MSG_KEYCHAIN_COPY
,
607 if (data
!= NULL
) CFRelease(data
);
612 if (status
!= kSCStatusOK
) {
621 if (prefsPrivate
->helper_port
!= MACH_PORT_NULL
) {
622 _SCHelperClose(&prefsPrivate
->helper_port
);
625 status
= kSCStatusAccessError
;
630 if (reply
!= NULL
) CFRelease(reply
);
634 #endif // !TARGET_OS_IPHONE
638 _SCPreferencesSystemKeychainPasswordItemCopy(SCPreferencesRef prefs
,
639 CFStringRef unique_id
)
641 #if !TARGET_OS_IPHONE
642 SecKeychainRef keychain
= NULL
;
643 CFDataRef password
= NULL
;
644 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
647 /* sorry, you must provide a session */
648 _SCErrorSet(kSCStatusNoPrefsSession
);
652 if (!isA_CFString(unique_id
)) {
653 _SCErrorSet(kSCStatusInvalidArgument
);
657 if (prefsPrivate
->authorizationData
!= NULL
) {
658 password
= __SCPreferencesSystemKeychainPasswordItemCopy_helper(prefs
, unique_id
);
662 keychain
= _SCSecKeychainCopySystemKeychain();
663 if (keychain
== NULL
) {
667 password
= _SCSecKeychainPasswordItemCopy(keychain
, unique_id
);
671 if (keychain
!= NULL
) CFRelease(keychain
);
673 #else // !TARGET_OS_IPHONE
674 #pragma unused(prefs)
675 #pragma unused(unique_id)
676 _SCErrorSet(kSCStatusAccessError
);
678 #endif // !TARGET_OS_IPHONE
683 _SCPreferencesSystemKeychainPasswordItemExists(SCPreferencesRef prefs
,
684 CFStringRef unique_id
)
686 #if !TARGET_OS_IPHONE
687 SecKeychainRef keychain
= NULL
;
689 // SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
692 /* sorry, you must provide a session */
693 _SCErrorSet(kSCStatusNoPrefsSession
);
697 if (!isA_CFString(unique_id
)) {
698 _SCErrorSet(kSCStatusInvalidArgument
);
702 // if (prefsPrivate->authorizationData != NULL) {
703 // ok = __SCPreferencesSystemKeychainPasswordItemExists_helper(prefs, unique_id);
707 keychain
= _SCSecKeychainCopySystemKeychain();
708 if (keychain
== NULL
) {
712 ok
= _SCSecKeychainPasswordItemExists(keychain
, unique_id
);
716 if (keychain
!= NULL
) CFRelease(keychain
);
718 #else // !TARGET_OS_IPHONE
719 #pragma unused(prefs)
720 #pragma unused(unique_id)
721 _SCErrorSet(kSCStatusAccessError
);
723 #endif // !TARGET_OS_IPHONE
727 #if !TARGET_OS_IPHONE
729 __SCPreferencesSystemKeychainPasswordItemRemove_helper(SCPreferencesRef prefs
,
730 CFStringRef unique_id
)
732 CFDataRef data
= NULL
;
734 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
735 uint32_t status
= kSCStatusOK
;
736 CFDataRef reply
= NULL
;
738 if (prefsPrivate
->helper_port
== MACH_PORT_NULL
) {
739 ok
= __SCPreferencesCreate_helper(prefs
);
745 ok
= _SCSerializeString(unique_id
, &data
, NULL
, NULL
);
750 // have the helper set the "System" Keychain password
751 ok
= _SCHelperExec(prefsPrivate
->helper_port
,
752 SCHELPER_MSG_KEYCHAIN_REMOVE
,
756 if (data
!= NULL
) CFRelease(data
);
761 if (status
!= kSCStatusOK
) {
770 if (prefsPrivate
->helper_port
!= MACH_PORT_NULL
) {
771 _SCHelperClose(&prefsPrivate
->helper_port
);
774 status
= kSCStatusAccessError
;
779 if (reply
!= NULL
) CFRelease(reply
);
783 #endif // !TARGET_OS_IPHONE
787 _SCPreferencesSystemKeychainPasswordItemRemove(SCPreferencesRef prefs
,
788 CFStringRef unique_id
)
790 #if !TARGET_OS_IPHONE
791 SecKeychainRef keychain
= NULL
;
793 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
796 /* sorry, you must provide a session */
797 _SCErrorSet(kSCStatusNoPrefsSession
);
801 if (!isA_CFString(unique_id
)) {
802 _SCErrorSet(kSCStatusInvalidArgument
);
806 if (prefsPrivate
->authorizationData
!= NULL
) {
807 ok
= __SCPreferencesSystemKeychainPasswordItemRemove_helper(prefs
, unique_id
);
811 keychain
= _SCSecKeychainCopySystemKeychain();
812 if (keychain
== NULL
) {
816 ok
= _SCSecKeychainPasswordItemRemove(keychain
, unique_id
);
820 if (keychain
!= NULL
) CFRelease(keychain
);
822 #else // !TARGET_OS_IPHONE
823 #pragma unused(prefs)
824 #pragma unused(unique_id)
825 _SCErrorSet(kSCStatusAccessError
);
827 #endif // !TARGET_OS_IPHONE
831 #if !TARGET_OS_IPHONE
833 __SCPreferencesSystemKeychainPasswordItemSet_helper(SCPreferencesRef prefs
,
834 CFStringRef unique_id
,
836 CFStringRef description
,
839 CFDictionaryRef options
)
841 CFDataRef data
= NULL
;
842 CFMutableDictionaryRef newOptions
= NULL
;
844 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
845 uint32_t status
= kSCStatusOK
;
846 CFDataRef reply
= NULL
;
848 if (prefsPrivate
->helper_port
== MACH_PORT_NULL
) {
849 ok
= __SCPreferencesCreate_helper(prefs
);
855 if (isA_CFDictionary(options
)) {
856 CFArrayRef executableURLs
= NULL
;
858 newOptions
= CFDictionaryCreateMutableCopy(NULL
, 0, options
);
860 if (CFDictionaryGetValueIfPresent(newOptions
,
861 kSCKeychainOptionsAllowedExecutables
,
862 (const void **)&executableURLs
)) {
863 CFMutableArrayRef executablePaths
;
868 executablePaths
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
870 path
= copyMyExecutablePath();
872 CFArrayAppendValue(executablePaths
, path
);
876 n
= CFArrayGetCount(executableURLs
);
877 for (i
= 0; i
< n
; i
++) {
878 char fspath
[MAXPATHLEN
];
881 url
= CFArrayGetValueAtIndex(executableURLs
, i
);
882 ok
= CFURLGetFileSystemRepresentation(url
, TRUE
, (UInt8
*)fspath
, sizeof(fspath
));
886 fspath
[sizeof(fspath
) - 1] = '\0';
887 path
= CFDataCreate(NULL
, (UInt8
*)fspath
, strlen(fspath
));
888 CFArrayAppendValue(executablePaths
, path
);
892 CFDictionarySetValue(newOptions
, kSCKeychainOptionsAllowedExecutables
, executablePaths
);
893 CFRelease(executablePaths
);
896 newOptions
= CFDictionaryCreateMutable(NULL
,
898 &kCFTypeDictionaryKeyCallBacks
,
899 &kCFTypeDictionaryValueCallBacks
);
902 if (unique_id
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsUniqueID
, unique_id
);
903 if (label
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsLabel
, label
);
904 if (description
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsDescription
, description
);
905 if (account
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsAccount
, account
);
906 if (password
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsPassword
, password
);
909 // if not AllowRoot and a list of executables was not provided than
910 // pass the current executable
912 if (!CFDictionaryContainsKey(newOptions
, kSCKeychainOptionsAllowRoot
) &&
913 !CFDictionaryContainsKey(newOptions
, kSCKeychainOptionsAllowedExecutables
)) {
916 path
= copyMyExecutablePath();
918 CFArrayRef executablePaths
;
920 executablePaths
= CFArrayCreate(NULL
, (const void **)&path
, 1, &kCFTypeArrayCallBacks
);
922 CFDictionarySetValue(newOptions
, kSCKeychainOptionsAllowedExecutables
, executablePaths
);
923 CFRelease(executablePaths
);
927 ok
= _SCSerialize(newOptions
, &data
, NULL
, NULL
);
928 CFRelease(newOptions
);
933 // have the helper create the "System" Keychain password
934 ok
= _SCHelperExec(prefsPrivate
->helper_port
,
935 SCHELPER_MSG_KEYCHAIN_SET
,
939 if (data
!= NULL
) CFRelease(data
);
944 if (status
!= kSCStatusOK
) {
953 if (prefsPrivate
->helper_port
!= MACH_PORT_NULL
) {
954 _SCHelperClose(&prefsPrivate
->helper_port
);
957 status
= kSCStatusAccessError
;
962 if (reply
!= NULL
) CFRelease(reply
);
966 #endif // !TARGET_OS_IPHONE
970 _SCPreferencesSystemKeychainPasswordItemSet(SCPreferencesRef prefs
,
971 CFStringRef unique_id
,
973 CFStringRef description
,
976 CFDictionaryRef options
)
978 #if !TARGET_OS_IPHONE
979 SecKeychainRef keychain
= NULL
;
981 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
984 /* sorry, you must provide a session */
985 _SCErrorSet(kSCStatusNoPrefsSession
);
989 if (!isA_CFString(unique_id
) ||
990 ((label
!= NULL
) && !isA_CFString (label
)) ||
991 ((description
!= NULL
) && !isA_CFString (description
)) ||
992 ((account
!= NULL
) && !isA_CFString (account
)) ||
993 ((password
!= NULL
) && !isA_CFData (password
)) ||
994 ((options
!= NULL
) && !isA_CFDictionary(options
))) {
995 _SCErrorSet(kSCStatusInvalidArgument
);
999 if (prefsPrivate
->authorizationData
!= NULL
) {
1000 ok
= __SCPreferencesSystemKeychainPasswordItemSet_helper(prefs
,
1010 keychain
= _SCSecKeychainCopySystemKeychain();
1011 if (keychain
== NULL
) {
1015 ok
= _SCSecKeychainPasswordItemSet(keychain
,
1025 if (keychain
!= NULL
) CFRelease(keychain
);
1027 #else // !TARGET_OS_IPHONE
1028 #pragma unused(prefs)
1029 #pragma unused(unique_id)
1030 #pragma unused(label)
1031 #pragma unused(description)
1032 #pragma unused(account)
1033 #pragma unused(password)
1034 #pragma unused(options)
1035 _SCErrorSet(kSCStatusAccessError
);
1037 #endif // !TARGET_OS_IPHONE