2 * Copyright (c) 2006, 2007, 2010, 2014, 2016 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 _SCErrorSet(kSCStatusAccessError
);
330 #endif // !TARGET_OS_IPHONE
335 _SCSecKeychainPasswordItemExists(SecKeychainRef keychain
, CFStringRef unique_id
)
337 #if !TARGET_OS_IPHONE
338 SecKeychainItemRef item
;
341 status
= findKeychainItem(keychain
, unique_id
, &item
);
342 if (status
!= noErr
) {
349 #else // !TARGET_OS_IPHONE
350 _SCErrorSet(kSCStatusAccessError
);
352 #endif // !TARGET_OS_IPHONE
357 _SCSecKeychainPasswordItemRemove(SecKeychainRef keychain
, CFStringRef unique_id
)
359 #if !TARGET_OS_IPHONE
360 SecKeychainItemRef item
;
363 status
= findKeychainItem(keychain
, unique_id
, &item
);
364 if (status
!= noErr
) {
369 status
= SecKeychainItemDelete(item
);
371 if (status
!= noErr
) {
377 #else // !TARGET_OS_IPHONE
378 _SCErrorSet(kSCStatusAccessError
);
380 #endif // !TARGET_OS_IPHONE
385 _SCSecKeychainPasswordItemSet(SecKeychainRef keychain
,
386 CFStringRef unique_id
,
388 CFStringRef description
,
391 CFDictionaryRef options
)
393 #if !TARGET_OS_IPHONE
394 SecAccessRef access
= NULL
;
395 CFBooleanRef allowRoot
= NULL
;
396 CFArrayRef allowedExecutables
= NULL
;
397 SecKeychainAttribute attributes
[4];
398 SecKeychainAttributeList attributeList
= { 0, attributes
};
400 SecKeychainItemRef item
= NULL
;
404 if (options
!= NULL
) {
405 if (isA_CFDictionary(options
)) {
406 allowRoot
= CFDictionaryGetValue(options
, kSCKeychainOptionsAllowRoot
);
407 allowedExecutables
= CFDictionaryGetValue(options
, kSCKeychainOptionsAllowedExecutables
);
409 _SCErrorSet(kSCStatusInvalidArgument
);
414 if (!isA_CFString(unique_id
) ||
415 ((label
!= NULL
) && !isA_CFString (label
)) ||
416 ((description
!= NULL
) && !isA_CFString (description
)) ||
417 ((account
!= NULL
) && !isA_CFString (account
)) ||
418 ((password
!= NULL
) && !isA_CFData (password
)) ||
419 ((allowRoot
!= NULL
) && !isA_CFBoolean(allowRoot
)) ||
420 ((allowedExecutables
!= NULL
) && !isA_CFArray (allowedExecutables
)) ||
421 ((allowRoot
!= NULL
) && (allowedExecutables
!= NULL
))) {
422 _SCErrorSet(kSCStatusInvalidArgument
);
426 if ((allowRoot
!= NULL
) && CFBooleanGetValue(allowRoot
)) {
427 #if (__MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
428 access
= _SCSecAccessCreateForUID(0);
429 if (access
== NULL
) {
432 #else // (__MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
433 CFErrorRef error
= NULL
;
435 access
= SecAccessCreateWithOwnerAndACL(0, 0, kSecUseOnlyUID
, NULL
, &error
);
436 if (access
== NULL
) {
437 CFIndex code
= kSCStatusAccessError
;
441 code
= CFErrorGetCode(error
);
444 _SCErrorSet((int)code
);
447 #endif // (__MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
448 } else if (allowedExecutables
!= NULL
) {
449 access
= _SCSecAccessCreateForExecutables(label
, allowedExecutables
);
450 if (access
== NULL
) {
455 for (i
= 0; i
< 4; i
++) {
456 CFStringRef str
= NULL
;
457 SecKeychainAttrType tag
= 0;
462 tag
= kSecServiceItemAttr
;
466 tag
= kSecLabelItemAttr
;
470 tag
= kSecDescriptionItemAttr
;
474 tag
= kSecAccountItemAttr
;
482 attributes
[n
].tag
= tag
;
483 attributes
[n
].data
= _SC_cfstring_to_cstring(str
, NULL
, 0, kCFStringEncodingUTF8
);
484 attributes
[n
].length
= (UInt32
)strlen(attributes
[n
].data
);
488 status
= findKeychainItem(keychain
, unique_id
, &item
);
491 const void *pw
= NULL
;
494 // keychain item exists
495 if (password
!= NULL
) {
496 pw
= CFDataGetBytePtr(password
);
497 pw_len
= (UInt32
)CFDataGetLength(password
);
500 attributeList
.count
= (UInt32
)n
;
501 status
= SecKeychainItemModifyContent(item
,
508 case errSecItemNotFound
: {
510 if (password
== NULL
) {
511 // creating new keychain item and password not specified
512 status
= kSCStatusInvalidArgument
;
516 attributeList
.count
= (UInt32
)n
;
517 status
= SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass
,
519 (UInt32
)CFDataGetLength(password
),
520 CFDataGetBytePtr(password
),
534 if (access
!= NULL
) CFRelease(access
);
535 if (item
!= NULL
) CFRelease(item
);
537 for (i
= 0; i
< n
; i
++) {
538 CFAllocatorDeallocate(NULL
, attributes
[i
].data
);
541 if (status
!= noErr
) {
547 #else // !TARGET_OS_IPHONE
548 _SCErrorSet(kSCStatusAccessError
);
550 #endif // !TARGET_OS_IPHONE
555 #pragma mark "System" Keychain APIs (w/SCPreferences)
558 #include "SCHelper_client.h"
562 #include <sys/errno.h>
565 #if !TARGET_OS_IPHONE
567 __SCPreferencesSystemKeychainPasswordItemCopy_helper(SCPreferencesRef prefs
,
568 CFStringRef unique_id
)
570 CFDataRef data
= NULL
;
572 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
573 uint32_t status
= kSCStatusOK
;
574 CFDataRef reply
= NULL
;
576 if (prefsPrivate
->helper_port
== MACH_PORT_NULL
) {
577 ok
= __SCPreferencesCreate_helper(prefs
);
583 ok
= _SCSerializeString(unique_id
, &data
, NULL
, NULL
);
588 // have the helper set the "System" Keychain password
589 ok
= _SCHelperExec(prefsPrivate
->helper_port
,
590 SCHELPER_MSG_KEYCHAIN_COPY
,
594 if (data
!= NULL
) CFRelease(data
);
599 if (status
!= kSCStatusOK
) {
608 if (prefsPrivate
->helper_port
!= MACH_PORT_NULL
) {
609 _SCHelperClose(&prefsPrivate
->helper_port
);
612 status
= kSCStatusAccessError
;
617 if (reply
!= NULL
) CFRelease(reply
);
621 #endif // !TARGET_OS_IPHONE
625 _SCPreferencesSystemKeychainPasswordItemCopy(SCPreferencesRef prefs
,
626 CFStringRef unique_id
)
628 #if !TARGET_OS_IPHONE
629 SecKeychainRef keychain
= NULL
;
630 CFDataRef password
= NULL
;
631 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
634 /* sorry, you must provide a session */
635 _SCErrorSet(kSCStatusNoPrefsSession
);
639 if (!isA_CFString(unique_id
)) {
640 _SCErrorSet(kSCStatusInvalidArgument
);
644 if (prefsPrivate
->authorizationData
!= NULL
) {
645 password
= __SCPreferencesSystemKeychainPasswordItemCopy_helper(prefs
, unique_id
);
649 keychain
= _SCSecKeychainCopySystemKeychain();
650 if (keychain
== NULL
) {
654 password
= _SCSecKeychainPasswordItemCopy(keychain
, unique_id
);
658 if (keychain
!= NULL
) CFRelease(keychain
);
660 #else // !TARGET_OS_IPHONE
661 _SCErrorSet(kSCStatusAccessError
);
663 #endif // !TARGET_OS_IPHONE
668 _SCPreferencesSystemKeychainPasswordItemExists(SCPreferencesRef prefs
,
669 CFStringRef unique_id
)
671 #if !TARGET_OS_IPHONE
672 SecKeychainRef keychain
= NULL
;
674 // SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
677 /* sorry, you must provide a session */
678 _SCErrorSet(kSCStatusNoPrefsSession
);
682 if (!isA_CFString(unique_id
)) {
683 _SCErrorSet(kSCStatusInvalidArgument
);
687 // if (prefsPrivate->authorizationData != NULL) {
688 // ok = __SCPreferencesSystemKeychainPasswordItemExists_helper(prefs, unique_id);
692 keychain
= _SCSecKeychainCopySystemKeychain();
693 if (keychain
== NULL
) {
697 ok
= _SCSecKeychainPasswordItemExists(keychain
, unique_id
);
701 if (keychain
!= NULL
) CFRelease(keychain
);
703 #else // !TARGET_OS_IPHONE
704 _SCErrorSet(kSCStatusAccessError
);
706 #endif // !TARGET_OS_IPHONE
710 #if !TARGET_OS_IPHONE
712 __SCPreferencesSystemKeychainPasswordItemRemove_helper(SCPreferencesRef prefs
,
713 CFStringRef unique_id
)
715 CFDataRef data
= NULL
;
717 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
718 uint32_t status
= kSCStatusOK
;
719 CFDataRef reply
= NULL
;
721 if (prefsPrivate
->helper_port
== MACH_PORT_NULL
) {
722 ok
= __SCPreferencesCreate_helper(prefs
);
728 ok
= _SCSerializeString(unique_id
, &data
, NULL
, NULL
);
733 // have the helper set the "System" Keychain password
734 ok
= _SCHelperExec(prefsPrivate
->helper_port
,
735 SCHELPER_MSG_KEYCHAIN_REMOVE
,
739 if (data
!= NULL
) CFRelease(data
);
744 if (status
!= kSCStatusOK
) {
753 if (prefsPrivate
->helper_port
!= MACH_PORT_NULL
) {
754 _SCHelperClose(&prefsPrivate
->helper_port
);
757 status
= kSCStatusAccessError
;
762 if (reply
!= NULL
) CFRelease(reply
);
766 #endif // !TARGET_OS_IPHONE
770 _SCPreferencesSystemKeychainPasswordItemRemove(SCPreferencesRef prefs
,
771 CFStringRef unique_id
)
773 #if !TARGET_OS_IPHONE
774 SecKeychainRef keychain
= NULL
;
776 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
779 /* sorry, you must provide a session */
780 _SCErrorSet(kSCStatusNoPrefsSession
);
784 if (!isA_CFString(unique_id
)) {
785 _SCErrorSet(kSCStatusInvalidArgument
);
789 if (prefsPrivate
->authorizationData
!= NULL
) {
790 ok
= __SCPreferencesSystemKeychainPasswordItemRemove_helper(prefs
, unique_id
);
794 keychain
= _SCSecKeychainCopySystemKeychain();
795 if (keychain
== NULL
) {
799 ok
= _SCSecKeychainPasswordItemRemove(keychain
, unique_id
);
803 if (keychain
!= NULL
) CFRelease(keychain
);
805 #else // !TARGET_OS_IPHONE
806 _SCErrorSet(kSCStatusAccessError
);
808 #endif // !TARGET_OS_IPHONE
812 #if !TARGET_OS_IPHONE
814 __SCPreferencesSystemKeychainPasswordItemSet_helper(SCPreferencesRef prefs
,
815 CFStringRef unique_id
,
817 CFStringRef description
,
820 CFDictionaryRef options
)
822 CFDataRef data
= NULL
;
823 CFMutableDictionaryRef newOptions
= NULL
;
825 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
826 uint32_t status
= kSCStatusOK
;
827 CFDataRef reply
= NULL
;
829 if (prefsPrivate
->helper_port
== MACH_PORT_NULL
) {
830 ok
= __SCPreferencesCreate_helper(prefs
);
836 if (isA_CFDictionary(options
)) {
837 CFArrayRef executableURLs
= NULL
;
839 newOptions
= CFDictionaryCreateMutableCopy(NULL
, 0, options
);
841 if (CFDictionaryGetValueIfPresent(newOptions
,
842 kSCKeychainOptionsAllowedExecutables
,
843 (const void **)&executableURLs
)) {
844 CFMutableArrayRef executablePaths
;
849 executablePaths
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
851 path
= copyMyExecutablePath();
853 CFArrayAppendValue(executablePaths
, path
);
857 n
= CFArrayGetCount(executableURLs
);
858 for (i
= 0; i
< n
; i
++) {
859 char fspath
[MAXPATHLEN
];
862 url
= CFArrayGetValueAtIndex(executableURLs
, i
);
863 ok
= CFURLGetFileSystemRepresentation(url
, TRUE
, (UInt8
*)fspath
, sizeof(fspath
));
867 fspath
[sizeof(fspath
) - 1] = '\0';
868 path
= CFDataCreate(NULL
, (UInt8
*)fspath
, strlen(fspath
));
869 CFArrayAppendValue(executablePaths
, path
);
873 CFDictionarySetValue(newOptions
, kSCKeychainOptionsAllowedExecutables
, executablePaths
);
874 CFRelease(executablePaths
);
877 newOptions
= CFDictionaryCreateMutable(NULL
,
879 &kCFTypeDictionaryKeyCallBacks
,
880 &kCFTypeDictionaryValueCallBacks
);
883 if (unique_id
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsUniqueID
, unique_id
);
884 if (label
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsLabel
, label
);
885 if (description
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsDescription
, description
);
886 if (account
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsAccount
, account
);
887 if (password
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsPassword
, password
);
890 // if not AllowRoot and a list of executables was not provided than
891 // pass the current executable
893 if (!CFDictionaryContainsKey(newOptions
, kSCKeychainOptionsAllowRoot
) &&
894 !CFDictionaryContainsKey(newOptions
, kSCKeychainOptionsAllowedExecutables
)) {
897 path
= copyMyExecutablePath();
899 CFArrayRef executablePaths
;
901 executablePaths
= CFArrayCreate(NULL
, (const void **)&path
, 1, &kCFTypeArrayCallBacks
);
903 CFDictionarySetValue(newOptions
, kSCKeychainOptionsAllowedExecutables
, executablePaths
);
904 CFRelease(executablePaths
);
908 ok
= _SCSerialize(newOptions
, &data
, NULL
, NULL
);
909 CFRelease(newOptions
);
914 // have the helper create the "System" Keychain password
915 ok
= _SCHelperExec(prefsPrivate
->helper_port
,
916 SCHELPER_MSG_KEYCHAIN_SET
,
920 if (data
!= NULL
) CFRelease(data
);
925 if (status
!= kSCStatusOK
) {
934 if (prefsPrivate
->helper_port
!= MACH_PORT_NULL
) {
935 _SCHelperClose(&prefsPrivate
->helper_port
);
938 status
= kSCStatusAccessError
;
943 if (reply
!= NULL
) CFRelease(reply
);
947 #endif // !TARGET_OS_IPHONE
951 _SCPreferencesSystemKeychainPasswordItemSet(SCPreferencesRef prefs
,
952 CFStringRef unique_id
,
954 CFStringRef description
,
957 CFDictionaryRef options
)
959 #if !TARGET_OS_IPHONE
960 SecKeychainRef keychain
= NULL
;
962 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
965 /* sorry, you must provide a session */
966 _SCErrorSet(kSCStatusNoPrefsSession
);
970 if (!isA_CFString(unique_id
) ||
971 ((label
!= NULL
) && !isA_CFString (label
)) ||
972 ((description
!= NULL
) && !isA_CFString (description
)) ||
973 ((account
!= NULL
) && !isA_CFString (account
)) ||
974 ((password
!= NULL
) && !isA_CFData (password
)) ||
975 ((options
!= NULL
) && !isA_CFDictionary(options
))) {
976 _SCErrorSet(kSCStatusInvalidArgument
);
980 if (prefsPrivate
->authorizationData
!= NULL
) {
981 ok
= __SCPreferencesSystemKeychainPasswordItemSet_helper(prefs
,
991 keychain
= _SCSecKeychainCopySystemKeychain();
992 if (keychain
== NULL
) {
996 ok
= _SCSecKeychainPasswordItemSet(keychain
,
1006 if (keychain
!= NULL
) CFRelease(keychain
);
1008 #else // !TARGET_OS_IPHONE
1009 _SCErrorSet(kSCStatusAccessError
);
1011 #endif // !TARGET_OS_IPHONE