2 * Copyright (c) 2006, 2007, 2010, 2014 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 SecKeychainRef keychain
= NULL
;
258 status
= SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem
, &keychain
);
259 if (status
!= noErr
) {
261 if (keychain
!= NULL
) CFRelease(keychain
);
266 #else // !TARGET_OS_IPHONE
267 _SCErrorSet(kSCStatusAccessError
);
269 #endif // !TARGET_OS_IPHONE
273 #if !TARGET_OS_IPHONE
275 findKeychainItem(SecKeychainRef keychain
,
276 CFStringRef unique_id
,
277 SecKeychainItemRef
*item
)
279 CFMutableDictionaryRef query
;
282 query
= CFDictionaryCreateMutable(NULL
,
284 &kCFTypeDictionaryKeyCallBacks
,
285 &kCFTypeDictionaryValueCallBacks
);
286 if (keychain
!= NULL
) {
287 CFArrayRef keychains
;
289 keychains
= CFArrayCreate(NULL
, (const void **)&keychain
, 1, &kCFTypeArrayCallBacks
);
290 CFDictionarySetValue(query
, kSecMatchSearchList
, keychains
);
291 CFRelease(keychains
);
293 CFDictionarySetValue(query
, kSecClass
, kSecClassGenericPassword
);
294 CFDictionarySetValue(query
, kSecAttrService
, unique_id
);
295 CFDictionarySetValue(query
, kSecReturnRef
, kCFBooleanTrue
);
296 status
= SecItemCopyMatching(query
, (CFTypeRef
*)item
);
301 #endif // !TARGET_OS_IPHONE
305 _SCSecKeychainPasswordItemCopy(SecKeychainRef keychain
,
306 CFStringRef unique_id
)
308 #if !TARGET_OS_IPHONE
309 SecKeychainItemRef item
= NULL
;
310 CFDataRef keychain_password
= NULL
;
313 status
= findKeychainItem(keychain
, unique_id
, &item
);
314 if (status
== noErr
) {
318 status
= SecKeychainItemCopyContent(item
, NULL
, NULL
, &pw_len
, &pw
);
319 if (status
== noErr
) {
320 keychain_password
= CFDataCreate(NULL
, pw
, pw_len
);
321 status
= SecKeychainItemFreeContent(NULL
, pw
);
324 if (item
!= NULL
) CFRelease(item
);
325 if (status
!= noErr
) {
329 return keychain_password
;
330 #else // !TARGET_OS_IPHONE
331 _SCErrorSet(kSCStatusAccessError
);
333 #endif // !TARGET_OS_IPHONE
338 _SCSecKeychainPasswordItemExists(SecKeychainRef keychain
, CFStringRef unique_id
)
340 #if !TARGET_OS_IPHONE
341 SecKeychainItemRef item
;
344 status
= findKeychainItem(keychain
, unique_id
, &item
);
345 if (status
!= noErr
) {
352 #else // !TARGET_OS_IPHONE
353 _SCErrorSet(kSCStatusAccessError
);
355 #endif // !TARGET_OS_IPHONE
360 _SCSecKeychainPasswordItemRemove(SecKeychainRef keychain
, CFStringRef unique_id
)
362 #if !TARGET_OS_IPHONE
363 SecKeychainItemRef item
;
366 status
= findKeychainItem(keychain
, unique_id
, &item
);
367 if (status
!= noErr
) {
372 status
= SecKeychainItemDelete(item
);
374 if (status
!= noErr
) {
380 #else // !TARGET_OS_IPHONE
381 _SCErrorSet(kSCStatusAccessError
);
383 #endif // !TARGET_OS_IPHONE
388 _SCSecKeychainPasswordItemSet(SecKeychainRef keychain
,
389 CFStringRef unique_id
,
391 CFStringRef description
,
394 CFDictionaryRef options
)
396 #if !TARGET_OS_IPHONE
397 SecAccessRef access
= NULL
;
398 CFBooleanRef allowRoot
= NULL
;
399 CFArrayRef allowedExecutables
= NULL
;
400 SecKeychainAttribute attributes
[4];
401 SecKeychainAttributeList attributeList
= { 0, attributes
};
403 SecKeychainItemRef item
= NULL
;
407 if (options
!= NULL
) {
408 if (isA_CFDictionary(options
)) {
409 allowRoot
= CFDictionaryGetValue(options
, kSCKeychainOptionsAllowRoot
);
410 allowedExecutables
= CFDictionaryGetValue(options
, kSCKeychainOptionsAllowedExecutables
);
412 _SCErrorSet(kSCStatusInvalidArgument
);
417 if (!isA_CFString(unique_id
) ||
418 ((label
!= NULL
) && !isA_CFString (label
)) ||
419 ((description
!= NULL
) && !isA_CFString (description
)) ||
420 ((account
!= NULL
) && !isA_CFString (account
)) ||
421 ((password
!= NULL
) && !isA_CFData (password
)) ||
422 ((allowRoot
!= NULL
) && !isA_CFBoolean(allowRoot
)) ||
423 ((allowedExecutables
!= NULL
) && !isA_CFArray (allowedExecutables
)) ||
424 ((allowRoot
!= NULL
) && (allowedExecutables
!= NULL
))) {
425 _SCErrorSet(kSCStatusInvalidArgument
);
429 if ((allowRoot
!= NULL
) && CFBooleanGetValue(allowRoot
)) {
430 #if (__MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
431 access
= _SCSecAccessCreateForUID(0);
432 if (access
== NULL
) {
435 #else // (__MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
436 CFErrorRef error
= NULL
;
438 access
= SecAccessCreateWithOwnerAndACL(0, 0, kSecUseOnlyUID
, NULL
, &error
);
439 if (access
== NULL
) {
440 CFIndex code
= kSCStatusAccessError
;
444 code
= CFErrorGetCode(error
);
447 _SCErrorSet((int)code
);
450 #endif // (__MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
451 } else if (allowedExecutables
!= NULL
) {
452 access
= _SCSecAccessCreateForExecutables(label
, allowedExecutables
);
453 if (access
== NULL
) {
458 for (i
= 0; i
< 4; i
++) {
459 CFStringRef str
= NULL
;
460 SecKeychainAttrType tag
= 0;
465 tag
= kSecServiceItemAttr
;
469 tag
= kSecLabelItemAttr
;
473 tag
= kSecDescriptionItemAttr
;
477 tag
= kSecAccountItemAttr
;
485 attributes
[n
].tag
= tag
;
486 attributes
[n
].data
= _SC_cfstring_to_cstring(str
, NULL
, 0, kCFStringEncodingUTF8
);
487 attributes
[n
].length
= (UInt32
)strlen(attributes
[n
].data
);
491 status
= findKeychainItem(keychain
, unique_id
, &item
);
494 const void *pw
= NULL
;
497 // keychain item exists
498 if (password
!= NULL
) {
499 pw
= CFDataGetBytePtr(password
);
500 pw_len
= (UInt32
)CFDataGetLength(password
);
503 attributeList
.count
= (UInt32
)n
;
504 status
= SecKeychainItemModifyContent(item
,
511 case errSecItemNotFound
: {
513 if (password
== NULL
) {
514 // creating new keychain item and password not specified
515 status
= kSCStatusInvalidArgument
;
519 attributeList
.count
= (UInt32
)n
;
520 status
= SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass
,
522 (UInt32
)CFDataGetLength(password
),
523 CFDataGetBytePtr(password
),
537 if (access
!= NULL
) CFRelease(access
);
538 if (item
!= NULL
) CFRelease(item
);
540 for (i
= 0; i
< n
; i
++) {
541 CFAllocatorDeallocate(NULL
, attributes
[i
].data
);
544 if (status
!= noErr
) {
550 #else // !TARGET_OS_IPHONE
551 _SCErrorSet(kSCStatusAccessError
);
553 #endif // !TARGET_OS_IPHONE
558 #pragma mark "System" Keychain APIs (w/SCPreferences)
561 #include "SCHelper_client.h"
565 #include <sys/errno.h>
568 #if !TARGET_OS_IPHONE
570 __SCPreferencesSystemKeychainPasswordItemCopy_helper(SCPreferencesRef prefs
,
571 CFStringRef unique_id
)
573 CFDataRef data
= NULL
;
575 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
576 uint32_t status
= kSCStatusOK
;
577 CFDataRef reply
= NULL
;
579 if (prefsPrivate
->helper_port
== MACH_PORT_NULL
) {
580 ok
= __SCPreferencesCreate_helper(prefs
);
586 ok
= _SCSerializeString(unique_id
, &data
, NULL
, NULL
);
591 // have the helper set the "System" Keychain password
592 ok
= _SCHelperExec(prefsPrivate
->helper_port
,
593 SCHELPER_MSG_KEYCHAIN_COPY
,
597 if (data
!= NULL
) CFRelease(data
);
602 if (status
!= kSCStatusOK
) {
611 if (prefsPrivate
->helper_port
!= MACH_PORT_NULL
) {
612 _SCHelperClose(&prefsPrivate
->helper_port
);
615 status
= kSCStatusAccessError
;
620 if (reply
!= NULL
) CFRelease(reply
);
624 #endif // !TARGET_OS_IPHONE
628 _SCPreferencesSystemKeychainPasswordItemCopy(SCPreferencesRef prefs
,
629 CFStringRef unique_id
)
631 #if !TARGET_OS_IPHONE
632 SecKeychainRef keychain
= NULL
;
633 CFDataRef password
= NULL
;
634 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
637 /* sorry, you must provide a session */
638 _SCErrorSet(kSCStatusNoPrefsSession
);
642 if (!isA_CFString(unique_id
)) {
643 _SCErrorSet(kSCStatusInvalidArgument
);
647 if (prefsPrivate
->authorizationData
!= NULL
) {
648 password
= __SCPreferencesSystemKeychainPasswordItemCopy_helper(prefs
, unique_id
);
652 keychain
= _SCSecKeychainCopySystemKeychain();
653 if (keychain
== NULL
) {
657 password
= _SCSecKeychainPasswordItemCopy(keychain
, unique_id
);
661 if (keychain
!= NULL
) CFRelease(keychain
);
663 #else // !TARGET_OS_IPHONE
664 _SCErrorSet(kSCStatusAccessError
);
666 #endif // !TARGET_OS_IPHONE
671 _SCPreferencesSystemKeychainPasswordItemExists(SCPreferencesRef prefs
,
672 CFStringRef unique_id
)
674 #if !TARGET_OS_IPHONE
675 SecKeychainRef keychain
= NULL
;
677 // SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
680 /* sorry, you must provide a session */
681 _SCErrorSet(kSCStatusNoPrefsSession
);
685 if (!isA_CFString(unique_id
)) {
686 _SCErrorSet(kSCStatusInvalidArgument
);
690 // if (prefsPrivate->authorizationData != NULL) {
691 // ok = __SCPreferencesSystemKeychainPasswordItemExists_helper(prefs, unique_id);
695 keychain
= _SCSecKeychainCopySystemKeychain();
696 if (keychain
== NULL
) {
700 ok
= _SCSecKeychainPasswordItemExists(keychain
, unique_id
);
704 if (keychain
!= NULL
) CFRelease(keychain
);
706 #else // !TARGET_OS_IPHONE
707 _SCErrorSet(kSCStatusAccessError
);
709 #endif // !TARGET_OS_IPHONE
713 #if !TARGET_OS_IPHONE
715 __SCPreferencesSystemKeychainPasswordItemRemove_helper(SCPreferencesRef prefs
,
716 CFStringRef unique_id
)
718 CFDataRef data
= NULL
;
720 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
721 uint32_t status
= kSCStatusOK
;
722 CFDataRef reply
= NULL
;
724 if (prefsPrivate
->helper_port
== MACH_PORT_NULL
) {
725 ok
= __SCPreferencesCreate_helper(prefs
);
731 ok
= _SCSerializeString(unique_id
, &data
, NULL
, NULL
);
736 // have the helper set the "System" Keychain password
737 ok
= _SCHelperExec(prefsPrivate
->helper_port
,
738 SCHELPER_MSG_KEYCHAIN_REMOVE
,
742 if (data
!= NULL
) CFRelease(data
);
747 if (status
!= kSCStatusOK
) {
756 if (prefsPrivate
->helper_port
!= MACH_PORT_NULL
) {
757 _SCHelperClose(&prefsPrivate
->helper_port
);
760 status
= kSCStatusAccessError
;
765 if (reply
!= NULL
) CFRelease(reply
);
769 #endif // !TARGET_OS_IPHONE
773 _SCPreferencesSystemKeychainPasswordItemRemove(SCPreferencesRef prefs
,
774 CFStringRef unique_id
)
776 #if !TARGET_OS_IPHONE
777 SecKeychainRef keychain
= NULL
;
779 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
782 /* sorry, you must provide a session */
783 _SCErrorSet(kSCStatusNoPrefsSession
);
787 if (!isA_CFString(unique_id
)) {
788 _SCErrorSet(kSCStatusInvalidArgument
);
792 if (prefsPrivate
->authorizationData
!= NULL
) {
793 ok
= __SCPreferencesSystemKeychainPasswordItemRemove_helper(prefs
, unique_id
);
797 keychain
= _SCSecKeychainCopySystemKeychain();
798 if (keychain
== NULL
) {
802 ok
= _SCSecKeychainPasswordItemRemove(keychain
, unique_id
);
806 if (keychain
!= NULL
) CFRelease(keychain
);
808 #else // !TARGET_OS_IPHONE
809 _SCErrorSet(kSCStatusAccessError
);
811 #endif // !TARGET_OS_IPHONE
815 #if !TARGET_OS_IPHONE
817 __SCPreferencesSystemKeychainPasswordItemSet_helper(SCPreferencesRef prefs
,
818 CFStringRef unique_id
,
820 CFStringRef description
,
823 CFDictionaryRef options
)
825 CFDataRef data
= NULL
;
826 CFMutableDictionaryRef newOptions
= NULL
;
828 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
829 uint32_t status
= kSCStatusOK
;
830 CFDataRef reply
= NULL
;
832 if (prefsPrivate
->helper_port
== MACH_PORT_NULL
) {
833 ok
= __SCPreferencesCreate_helper(prefs
);
839 if (isA_CFDictionary(options
)) {
840 CFArrayRef executableURLs
= NULL
;
842 newOptions
= CFDictionaryCreateMutableCopy(NULL
, 0, options
);
844 if (CFDictionaryGetValueIfPresent(newOptions
,
845 kSCKeychainOptionsAllowedExecutables
,
846 (const void **)&executableURLs
)) {
847 CFMutableArrayRef executablePaths
;
852 executablePaths
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
854 path
= copyMyExecutablePath();
856 CFArrayAppendValue(executablePaths
, path
);
860 n
= CFArrayGetCount(executableURLs
);
861 for (i
= 0; i
< n
; i
++) {
862 char fspath
[MAXPATHLEN
];
865 url
= CFArrayGetValueAtIndex(executableURLs
, i
);
866 ok
= CFURLGetFileSystemRepresentation(url
, TRUE
, (UInt8
*)fspath
, sizeof(fspath
));
870 fspath
[sizeof(fspath
) - 1] = '\0';
871 path
= CFDataCreate(NULL
, (UInt8
*)fspath
, strlen(fspath
));
872 CFArrayAppendValue(executablePaths
, path
);
876 CFDictionarySetValue(newOptions
, kSCKeychainOptionsAllowedExecutables
, executablePaths
);
877 CFRelease(executablePaths
);
880 newOptions
= CFDictionaryCreateMutable(NULL
,
882 &kCFTypeDictionaryKeyCallBacks
,
883 &kCFTypeDictionaryValueCallBacks
);
886 if (unique_id
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsUniqueID
, unique_id
);
887 if (label
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsLabel
, label
);
888 if (description
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsDescription
, description
);
889 if (account
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsAccount
, account
);
890 if (password
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsPassword
, password
);
893 // if not AllowRoot and a list of executables was not provided than
894 // pass the current executable
896 if (!CFDictionaryContainsKey(newOptions
, kSCKeychainOptionsAllowRoot
) &&
897 !CFDictionaryContainsKey(newOptions
, kSCKeychainOptionsAllowedExecutables
)) {
900 path
= copyMyExecutablePath();
902 CFArrayRef executablePaths
;
904 executablePaths
= CFArrayCreate(NULL
, (const void **)&path
, 1, &kCFTypeArrayCallBacks
);
906 CFDictionarySetValue(newOptions
, kSCKeychainOptionsAllowedExecutables
, executablePaths
);
907 CFRelease(executablePaths
);
911 ok
= _SCSerialize(newOptions
, &data
, NULL
, NULL
);
912 CFRelease(newOptions
);
917 // have the helper create the "System" Keychain password
918 ok
= _SCHelperExec(prefsPrivate
->helper_port
,
919 SCHELPER_MSG_KEYCHAIN_SET
,
923 if (data
!= NULL
) CFRelease(data
);
928 if (status
!= kSCStatusOK
) {
937 if (prefsPrivate
->helper_port
!= MACH_PORT_NULL
) {
938 _SCHelperClose(&prefsPrivate
->helper_port
);
941 status
= kSCStatusAccessError
;
946 if (reply
!= NULL
) CFRelease(reply
);
950 #endif // !TARGET_OS_IPHONE
954 _SCPreferencesSystemKeychainPasswordItemSet(SCPreferencesRef prefs
,
955 CFStringRef unique_id
,
957 CFStringRef description
,
960 CFDictionaryRef options
)
962 #if !TARGET_OS_IPHONE
963 SecKeychainRef keychain
= NULL
;
965 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
968 /* sorry, you must provide a session */
969 _SCErrorSet(kSCStatusNoPrefsSession
);
973 if (!isA_CFString(unique_id
) ||
974 ((label
!= NULL
) && !isA_CFString (label
)) ||
975 ((description
!= NULL
) && !isA_CFString (description
)) ||
976 ((account
!= NULL
) && !isA_CFString (account
)) ||
977 ((password
!= NULL
) && !isA_CFData (password
)) ||
978 ((options
!= NULL
) && !isA_CFDictionary(options
))) {
979 _SCErrorSet(kSCStatusInvalidArgument
);
983 if (prefsPrivate
->authorizationData
!= NULL
) {
984 ok
= __SCPreferencesSystemKeychainPasswordItemSet_helper(prefs
,
994 keychain
= _SCSecKeychainCopySystemKeychain();
995 if (keychain
== NULL
) {
999 ok
= _SCSecKeychainPasswordItemSet(keychain
,
1009 if (keychain
!= NULL
) CFRelease(keychain
);
1011 #else // !TARGET_OS_IPHONE
1012 _SCErrorSet(kSCStatusAccessError
);
1014 #endif // !TARGET_OS_IPHONE