2 * Copyright (c) 2006 Apple Computer, 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 <sys/param.h>
36 #include <CoreFoundation/CoreFoundation.h>
37 #include <CoreFoundation/CFBundlePriv.h> // for _CFBundleCopyMainBundleExecutableURL
38 #include <SystemConfiguration/SCPrivate.h> // for _SCErrorSet
39 #include <Security/Security.h>
40 #include "dy_framework.h"
42 #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
95 * Create a SecAccessRef with a custom form.
97 * Both the owner and the ACL set allow free access to root,
98 * but nothing to anyone else.
100 * NOTE: This is not the easiest way to build up CSSM data structures
101 * but it is a way that does not depend on any outside software
102 * layers (other than CSSM and Security's Sec* layer, of course).
105 _SCSecAccessCreateForUID(uid_t uid
)
107 SecAccessRef access
= NULL
;
110 // make the "uid/gid" ACL subject
111 // this is a CSSM_LIST_ELEMENT chain
113 CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector
= {
114 CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION
, // version
115 CSSM_ACL_MATCH_UID
, // active fields mask: match uids (only)
116 uid
, // effective user id to match
117 0 // effective group id to match
120 CSSM_LIST_ELEMENT subject2
= {
126 subject2
.Element
.Word
.Data
= (UInt8
*)&selector
;
127 subject2
.Element
.Word
.Length
= sizeof(selector
);
129 CSSM_LIST_ELEMENT subject1
= {
130 &subject2
, // NextElement
131 CSSM_ACL_SUBJECT_TYPE_PROCESS
, // WordID
132 CSSM_LIST_ELEMENT_WORDID
// ElementType
136 // rights granted (replace with individual list if desired)
137 CSSM_ACL_AUTHORIZATION_TAG rights
[] = {
138 CSSM_ACL_AUTHORIZATION_ANY
// everything
141 // owner component (right to change ACL)
142 CSSM_ACL_OWNER_PROTOTYPE owner
= {
144 CSSM_LIST_TYPE_UNKNOWN
, // type of this list
145 &subject1
, // head of the list
146 &subject2
// tail of the list
151 // ACL entries (any number, just one here)
152 CSSM_ACL_ENTRY_INFO acls
[] = {
156 CSSM_LIST_TYPE_UNKNOWN
, // type of this list
157 &subject1
, // head of the list
158 &subject2
// tail of the list
162 sizeof(rights
) / sizeof(rights
[0]), // NumberOfAuthTags
174 status
= SecAccessCreateFromOwnerAndACL(&owner
,
175 sizeof(acls
) / sizeof(acls
[0]),
178 if (status
!= noErr
) {
186 // one example would be to pass a URL for "/System/Library/CoreServices/SystemUIServer.app"
188 _SCSecAccessCreateForExecutables(CFStringRef label
,
189 CFArrayRef executableURLs
)
191 SecAccessRef access
= NULL
;
192 CFArrayRef aclList
= NULL
;
196 SecTrustedApplicationRef trustedApplication
;
197 CFMutableArrayRef trustedApplications
;
199 trustedApplications
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
201 // Use default access ("confirm access")
203 // Next, we make an exception list of applications you want to trust.
204 // These applications will be allowed to access the item without requiring
205 // user confirmation.
207 // Trust the calling application
208 status
= SecTrustedApplicationCreateFromPath(NULL
, &trustedApplication
);
209 if (status
== noErr
) {
210 CFArrayAppendValue(trustedApplications
, trustedApplication
);
211 CFRelease(trustedApplication
);
214 n
= (executableURLs
!= NULL
) ? CFArrayGetCount(executableURLs
) : 0;
215 for (i
= 0; i
< n
; i
++) {
217 char path
[MAXPATHLEN
];
220 url
= CFArrayGetValueAtIndex(executableURLs
, i
);
221 ok
= CFURLGetFileSystemRepresentation(url
, TRUE
, (UInt8
*)path
, sizeof(path
));
226 status
= SecTrustedApplicationCreateFromPath(path
, &trustedApplication
);
227 if (status
== noErr
) {
228 CFArrayAppendValue(trustedApplications
, trustedApplication
);
229 CFRelease(trustedApplication
);
233 status
= SecAccessCreate(label
, trustedApplications
, &access
);
234 if (status
!= noErr
) {
239 // get the access control list for decryption operations (this controls access to an item's data)
240 status
= SecAccessCopySelectedACLList(access
, CSSM_ACL_AUTHORIZATION_DECRYPT
, &aclList
);
241 if (status
== noErr
) {
243 CFArrayRef applicationList
= NULL
;
244 CFStringRef description
= NULL
;
245 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector
;
247 // get the first entry in the access control list
248 acl
= (SecACLRef
)CFArrayGetValueAtIndex(aclList
, 0);
250 // get the description and prompt selector
251 status
= SecACLCopySimpleContents(acl
, &applicationList
, &description
, &promptSelector
);
253 // modify the application list
254 status
= SecACLSetSimpleContents(acl
, (CFArrayRef
)trustedApplications
, description
, &promptSelector
);
256 if (applicationList
!= NULL
) CFRelease(applicationList
);
257 if (description
!= NULL
) CFRelease(description
);
263 if (aclList
!= NULL
) CFRelease(aclList
);
264 CFRelease(trustedApplications
);
271 _SCSecKeychainCopySystemKeychain(void)
273 SecPreferencesDomain domain
;
274 SecKeychainRef keychain
= NULL
;
277 status
= SecKeychainGetPreferenceDomain(&domain
);
278 if (status
!= noErr
) {
283 status
= SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem
);
284 if (status
!= noErr
) {
289 status
= SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem
, &keychain
);
290 if (status
!= noErr
) {
292 (void) SecKeychainSetPreferenceDomain(domain
);
293 if (keychain
!= NULL
) CFRelease(keychain
);
297 status
= SecKeychainSetPreferenceDomain(domain
);
298 if (status
!= noErr
) {
300 if (keychain
!= NULL
) CFRelease(keychain
);
309 findKeychainItem(SecKeychainRef keychain
,
310 UInt32 serviceNameLength
,
312 SecKeychainItemRef
*item
)
314 SecKeychainAttribute attributes
[1];
315 SecKeychainAttributeList attributeList
= { 1, attributes
};
316 SecKeychainSearchRef search
= NULL
;
319 attributes
[0].tag
= kSecServiceItemAttr
;
320 attributes
[0].data
= serviceName
;
321 attributes
[0].length
= serviceNameLength
;
323 status
= SecKeychainSearchCreateFromAttributes(keychain
,
324 kSecGenericPasswordItemClass
,
327 if (status
!= noErr
) {
331 status
= SecKeychainSearchCopyNext(search
, item
);
339 _SCSecKeychainPasswordItemCopy(SecKeychainRef keychain
,
340 CFStringRef unique_id
)
342 SecKeychainItemRef item
= NULL
;
343 CFDataRef keychain_password
= NULL
;
344 const char *keychain_serviceName
;
347 keychain_serviceName
= _SC_cfstring_to_cstring(unique_id
, NULL
, 0, kCFStringEncodingUTF8
);
348 status
= findKeychainItem(keychain
,
349 strlen(keychain_serviceName
),
350 (void *)keychain_serviceName
,
352 CFAllocatorDeallocate(NULL
, (void *)keychain_serviceName
);
353 if (status
== noErr
) {
357 status
= SecKeychainItemCopyContent(item
, NULL
, NULL
, &pw_len
, &pw
);
358 if (status
== noErr
) {
359 keychain_password
= CFDataCreate(NULL
, pw
, pw_len
);
360 status
= SecKeychainItemFreeContent(NULL
, pw
);
363 if (item
!= NULL
) CFRelease(item
);
364 if (status
!= noErr
) {
368 return keychain_password
;
373 _SCSecKeychainPasswordItemExists(SecKeychainRef keychain
, CFStringRef unique_id
)
375 SecKeychainItemRef item
;
376 const char *keychain_serviceName
;
379 keychain_serviceName
= _SC_cfstring_to_cstring(unique_id
, NULL
, 0, kCFStringEncodingUTF8
);
380 status
= findKeychainItem(keychain
,
381 strlen(keychain_serviceName
),
382 (void *)keychain_serviceName
,
384 CFAllocatorDeallocate(NULL
, (void *)keychain_serviceName
);
385 if (status
!= noErr
) {
396 _SCSecKeychainPasswordItemRemove(SecKeychainRef keychain
, CFStringRef unique_id
)
398 SecKeychainItemRef item
;
399 const char *keychain_serviceName
;
402 keychain_serviceName
= _SC_cfstring_to_cstring(unique_id
, NULL
, 0, kCFStringEncodingUTF8
);
403 status
= findKeychainItem(keychain
,
404 strlen(keychain_serviceName
),
405 (void *)keychain_serviceName
,
407 CFAllocatorDeallocate(NULL
, (void *)keychain_serviceName
);
408 if (status
!= noErr
) {
413 status
= SecKeychainItemDelete(item
);
415 if (status
!= noErr
) {
425 _SCSecKeychainPasswordItemSet(SecKeychainRef keychain
,
426 CFStringRef unique_id
,
428 CFStringRef description
,
431 CFDictionaryRef options
)
433 SecAccessRef access
= NULL
;
434 CFBooleanRef allowRoot
= NULL
;
435 CFArrayRef allowedExecutables
= NULL
;
436 SecKeychainAttribute attributes
[4];
437 SecKeychainAttributeList attributeList
= { 0, attributes
};
439 SecKeychainItemRef item
= NULL
;
443 if (options
!= NULL
) {
444 if (isA_CFDictionary(options
)) {
445 allowRoot
= CFDictionaryGetValue(options
, kSCKeychainOptionsAllowRoot
);
446 allowedExecutables
= CFDictionaryGetValue(options
, kSCKeychainOptionsAllowedExecutables
);
448 _SCErrorSet(kSCStatusInvalidArgument
);
453 if (!isA_CFString(unique_id
) ||
454 ((label
!= NULL
) && !isA_CFString (label
)) ||
455 ((description
!= NULL
) && !isA_CFString (description
)) ||
456 ((account
!= NULL
) && !isA_CFString (account
)) ||
457 ((password
!= NULL
) && !isA_CFData (password
)) ||
458 ((allowRoot
!= NULL
) && !isA_CFBoolean(allowRoot
)) ||
459 ((allowedExecutables
!= NULL
) && !isA_CFArray (allowedExecutables
)) ||
460 ((allowRoot
!= NULL
) && (allowedExecutables
!= NULL
))) {
461 _SCErrorSet(kSCStatusInvalidArgument
);
465 if ((allowRoot
!= NULL
) && CFBooleanGetValue(allowRoot
)) {
466 access
= _SCSecAccessCreateForUID(0);
467 if (access
== NULL
) {
470 } else if (allowedExecutables
!= NULL
) {
471 access
= _SCSecAccessCreateForExecutables(label
, allowedExecutables
);
472 if (access
== NULL
) {
477 for (i
= 0; i
< 4; i
++) {
478 CFStringRef str
= NULL
;
479 SecKeychainAttrType tag
= 0;
484 tag
= kSecServiceItemAttr
;
488 tag
= kSecLabelItemAttr
;
492 tag
= kSecDescriptionItemAttr
;
496 tag
= kSecAccountItemAttr
;
504 attributes
[n
].tag
= tag
;
505 attributes
[n
].data
= _SC_cfstring_to_cstring(str
, NULL
, 0, kCFStringEncodingUTF8
);
506 attributes
[n
].length
= strlen(attributes
[n
].data
);
510 status
= findKeychainItem(keychain
,
511 attributes
[0].length
,
516 const void *pw
= NULL
;
519 // keychain item exists
520 if (password
!= NULL
) {
521 pw
= CFDataGetBytePtr(password
);
522 pw_len
= CFDataGetLength(password
);
525 attributeList
.count
= n
;
526 status
= SecKeychainItemModifyContent(item
,
533 case errSecItemNotFound
: {
535 if (password
== NULL
) {
536 // creating new keychain item and password not specified
537 status
= kSCStatusInvalidArgument
;
541 attributeList
.count
= n
;
542 status
= SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass
,
544 CFDataGetLength(password
),
545 CFDataGetBytePtr(password
),
559 if (access
!= NULL
) CFRelease(access
);
560 if (item
!= NULL
) CFRelease(item
);
562 for (i
= 0; i
< n
; i
++) {
563 CFAllocatorDeallocate(NULL
, attributes
[i
].data
);
566 if (status
!= noErr
) {
576 #pragma mark "System" Keychain APIs (w/SCPreferences)
579 #include "SCHelper_client.h"
583 #include <sys/errno.h>
587 __SCPreferencesSystemKeychainPasswordItemCopy_helper(SCPreferencesRef prefs
,
588 CFStringRef unique_id
)
590 CFDataRef data
= NULL
;
592 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
593 uint32_t status
= kSCStatusOK
;
594 CFDataRef reply
= NULL
;
596 if (prefsPrivate
->helper
== -1) {
597 ok
= __SCPreferencesCreate_helper(prefs
);
603 ok
= _SCSerializeString(unique_id
, &data
, NULL
, NULL
);
608 // have the helper set the "System" Keychain password
609 ok
= _SCHelperExec(prefsPrivate
->helper
,
610 SCHELPER_MSG_KEYCHAIN_COPY
,
614 if (data
!= NULL
) CFRelease(data
);
619 if (status
!= kSCStatusOK
) {
628 if (prefsPrivate
->helper
!= -1) {
629 _SCHelperClose(prefsPrivate
->helper
);
630 prefsPrivate
->helper
= -1;
633 status
= kSCStatusAccessError
;
638 if (reply
!= NULL
) CFRelease(reply
);
645 _SCPreferencesSystemKeychainPasswordItemCopy(SCPreferencesRef prefs
,
646 CFStringRef unique_id
)
648 SecKeychainRef keychain
= NULL
;
649 CFDataRef password
= NULL
;
650 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
653 /* sorry, you must provide a session */
654 _SCErrorSet(kSCStatusNoPrefsSession
);
658 if (!isA_CFString(unique_id
)) {
659 _SCErrorSet(kSCStatusInvalidArgument
);
663 if (prefsPrivate
->authorizationData
!= NULL
) {
664 password
= __SCPreferencesSystemKeychainPasswordItemCopy_helper(prefs
, unique_id
);
668 keychain
= _SCSecKeychainCopySystemKeychain();
669 if (keychain
== NULL
) {
673 password
= _SCSecKeychainPasswordItemCopy(keychain
, unique_id
);
677 if (keychain
!= NULL
) CFRelease(keychain
);
683 _SCPreferencesSystemKeychainPasswordItemExists(SCPreferencesRef prefs
,
684 CFStringRef unique_id
)
686 SecKeychainRef keychain
= NULL
;
688 // SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
691 /* sorry, you must provide a session */
692 _SCErrorSet(kSCStatusNoPrefsSession
);
696 if (!isA_CFString(unique_id
)) {
697 _SCErrorSet(kSCStatusInvalidArgument
);
701 // if (prefsPrivate->authorizationData != NULL) {
702 // ok = __SCPreferencesSystemKeychainPasswordItemExists_helper(prefs, unique_id);
706 keychain
= _SCSecKeychainCopySystemKeychain();
707 if (keychain
== NULL
) {
711 ok
= _SCSecKeychainPasswordItemExists(keychain
, unique_id
);
715 if (keychain
!= NULL
) CFRelease(keychain
);
721 __SCPreferencesSystemKeychainPasswordItemRemove_helper(SCPreferencesRef prefs
,
722 CFStringRef unique_id
)
724 CFDataRef data
= NULL
;
726 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
727 uint32_t status
= kSCStatusOK
;
728 CFDataRef reply
= NULL
;
730 if (prefsPrivate
->helper
== -1) {
731 ok
= __SCPreferencesCreate_helper(prefs
);
737 ok
= _SCSerializeString(unique_id
, &data
, NULL
, NULL
);
742 // have the helper set the "System" Keychain password
743 ok
= _SCHelperExec(prefsPrivate
->helper
,
744 SCHELPER_MSG_KEYCHAIN_REMOVE
,
748 if (data
!= NULL
) CFRelease(data
);
753 if (status
!= kSCStatusOK
) {
762 if (prefsPrivate
->helper
!= -1) {
763 _SCHelperClose(prefsPrivate
->helper
);
764 prefsPrivate
->helper
= -1;
767 status
= kSCStatusAccessError
;
772 if (reply
!= NULL
) CFRelease(reply
);
779 _SCPreferencesSystemKeychainPasswordItemRemove(SCPreferencesRef prefs
,
780 CFStringRef unique_id
)
782 SecKeychainRef keychain
= NULL
;
784 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
787 /* sorry, you must provide a session */
788 _SCErrorSet(kSCStatusNoPrefsSession
);
792 if (!isA_CFString(unique_id
)) {
793 _SCErrorSet(kSCStatusInvalidArgument
);
797 if (prefsPrivate
->authorizationData
!= NULL
) {
798 ok
= __SCPreferencesSystemKeychainPasswordItemRemove_helper(prefs
, unique_id
);
802 keychain
= _SCSecKeychainCopySystemKeychain();
803 if (keychain
== NULL
) {
807 ok
= _SCSecKeychainPasswordItemRemove(keychain
, unique_id
);
811 if (keychain
!= NULL
) CFRelease(keychain
);
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
== -1) {
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
,
919 SCHELPER_MSG_KEYCHAIN_SET
,
923 if (data
!= NULL
) CFRelease(data
);
928 if (status
!= kSCStatusOK
) {
937 if (prefsPrivate
->helper
!= -1) {
938 _SCHelperClose(prefsPrivate
->helper
);
939 prefsPrivate
->helper
= -1;
942 status
= kSCStatusAccessError
;
947 if (reply
!= NULL
) CFRelease(reply
);
954 _SCPreferencesSystemKeychainPasswordItemSet(SCPreferencesRef prefs
,
955 CFStringRef unique_id
,
957 CFStringRef description
,
960 CFDictionaryRef options
)
962 SecKeychainRef keychain
= NULL
;
964 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
967 /* sorry, you must provide a session */
968 _SCErrorSet(kSCStatusNoPrefsSession
);
972 if (!isA_CFString(unique_id
) ||
973 ((label
!= NULL
) && !isA_CFString (label
)) ||
974 ((description
!= NULL
) && !isA_CFString (description
)) ||
975 ((account
!= NULL
) && !isA_CFString (account
)) ||
976 ((password
!= NULL
) && !isA_CFData (password
)) ||
977 ((options
!= NULL
) && !isA_CFDictionary(options
))) {
978 _SCErrorSet(kSCStatusInvalidArgument
);
982 if (prefsPrivate
->authorizationData
!= NULL
) {
983 ok
= __SCPreferencesSystemKeychainPasswordItemSet_helper(prefs
,
993 keychain
= _SCSecKeychainCopySystemKeychain();
994 if (keychain
== NULL
) {
998 ok
= _SCSecKeychainPasswordItemSet(keychain
,
1008 if (keychain
!= NULL
) CFRelease(keychain
);