2 * Copyright (c) 2006, 2007 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
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
) {
187 // one example would be to pass a URL for "/System/Library/CoreServices/SystemUIServer.app"
189 _SCSecAccessCreateForExecutables(CFStringRef label
,
190 CFArrayRef executableURLs
)
192 SecAccessRef access
= NULL
;
193 CFArrayRef aclList
= 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
) {
240 // get the access control list for decryption operations (this controls access to an item's data)
241 status
= SecAccessCopySelectedACLList(access
, CSSM_ACL_AUTHORIZATION_DECRYPT
, &aclList
);
242 if (status
== noErr
) {
244 CFArrayRef applicationList
= NULL
;
245 CFStringRef description
= NULL
;
246 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector
;
248 // get the first entry in the access control list
249 acl
= (SecACLRef
)CFArrayGetValueAtIndex(aclList
, 0);
251 // get the description and prompt selector
252 status
= SecACLCopySimpleContents(acl
, &applicationList
, &description
, &promptSelector
);
254 // modify the application list
255 status
= SecACLSetSimpleContents(acl
, (CFArrayRef
)trustedApplications
, description
, &promptSelector
);
257 if (applicationList
!= NULL
) CFRelease(applicationList
);
258 if (description
!= NULL
) CFRelease(description
);
264 if (aclList
!= NULL
) CFRelease(aclList
);
265 CFRelease(trustedApplications
);
269 #endif // !TARGET_OS_IPHONE
273 _SCSecKeychainCopySystemKeychain(void)
275 #if !TARGET_OS_IPHONE
276 SecPreferencesDomain domain
;
277 SecKeychainRef keychain
= NULL
;
280 status
= SecKeychainGetPreferenceDomain(&domain
);
281 if (status
!= noErr
) {
286 status
= SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem
);
287 if (status
!= noErr
) {
292 status
= SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem
, &keychain
);
293 if (status
!= noErr
) {
295 (void) SecKeychainSetPreferenceDomain(domain
);
296 if (keychain
!= NULL
) CFRelease(keychain
);
300 status
= SecKeychainSetPreferenceDomain(domain
);
301 if (status
!= noErr
) {
303 if (keychain
!= NULL
) CFRelease(keychain
);
308 #else // !TARGET_OS_IPHONE
309 _SCErrorSet(kSCStatusAccessError
);
311 #endif // !TARGET_OS_IPHONE
315 #if !TARGET_OS_IPHONE
317 findKeychainItem(SecKeychainRef keychain
,
318 UInt32 serviceNameLength
,
320 SecKeychainItemRef
*item
)
322 SecKeychainAttribute attributes
[1];
323 SecKeychainAttributeList attributeList
= { 1, attributes
};
324 SecKeychainSearchRef search
= NULL
;
327 attributes
[0].tag
= kSecServiceItemAttr
;
328 attributes
[0].data
= serviceName
;
329 attributes
[0].length
= serviceNameLength
;
331 status
= SecKeychainSearchCreateFromAttributes(keychain
,
332 kSecGenericPasswordItemClass
,
335 if (status
!= noErr
) {
339 status
= SecKeychainSearchCopyNext(search
, item
);
344 #endif // !TARGET_OS_IPHONE
348 _SCSecKeychainPasswordItemCopy(SecKeychainRef keychain
,
349 CFStringRef unique_id
)
351 #if !TARGET_OS_IPHONE
352 SecKeychainItemRef item
= NULL
;
353 CFDataRef keychain_password
= NULL
;
354 const char *keychain_serviceName
;
357 keychain_serviceName
= _SC_cfstring_to_cstring(unique_id
, NULL
, 0, kCFStringEncodingUTF8
);
358 status
= findKeychainItem(keychain
,
359 strlen(keychain_serviceName
),
360 (void *)keychain_serviceName
,
362 CFAllocatorDeallocate(NULL
, (void *)keychain_serviceName
);
363 if (status
== noErr
) {
367 status
= SecKeychainItemCopyContent(item
, NULL
, NULL
, &pw_len
, &pw
);
368 if (status
== noErr
) {
369 keychain_password
= CFDataCreate(NULL
, pw
, pw_len
);
370 status
= SecKeychainItemFreeContent(NULL
, pw
);
373 if (item
!= NULL
) CFRelease(item
);
374 if (status
!= noErr
) {
378 return keychain_password
;
379 #else // !TARGET_OS_IPHONE
380 _SCErrorSet(kSCStatusAccessError
);
382 #endif // !TARGET_OS_IPHONE
387 _SCSecKeychainPasswordItemExists(SecKeychainRef keychain
, CFStringRef unique_id
)
389 #if !TARGET_OS_IPHONE
390 SecKeychainItemRef item
;
391 const char *keychain_serviceName
;
394 keychain_serviceName
= _SC_cfstring_to_cstring(unique_id
, NULL
, 0, kCFStringEncodingUTF8
);
395 status
= findKeychainItem(keychain
,
396 strlen(keychain_serviceName
),
397 (void *)keychain_serviceName
,
399 CFAllocatorDeallocate(NULL
, (void *)keychain_serviceName
);
400 if (status
!= noErr
) {
407 #else // !TARGET_OS_IPHONE
408 _SCErrorSet(kSCStatusAccessError
);
410 #endif // !TARGET_OS_IPHONE
415 _SCSecKeychainPasswordItemRemove(SecKeychainRef keychain
, CFStringRef unique_id
)
417 #if !TARGET_OS_IPHONE
418 SecKeychainItemRef item
;
419 const char *keychain_serviceName
;
422 keychain_serviceName
= _SC_cfstring_to_cstring(unique_id
, NULL
, 0, kCFStringEncodingUTF8
);
423 status
= findKeychainItem(keychain
,
424 strlen(keychain_serviceName
),
425 (void *)keychain_serviceName
,
427 CFAllocatorDeallocate(NULL
, (void *)keychain_serviceName
);
428 if (status
!= noErr
) {
433 status
= SecKeychainItemDelete(item
);
435 if (status
!= noErr
) {
441 #else // !TARGET_OS_IPHONE
442 _SCErrorSet(kSCStatusAccessError
);
444 #endif // !TARGET_OS_IPHONE
449 _SCSecKeychainPasswordItemSet(SecKeychainRef keychain
,
450 CFStringRef unique_id
,
452 CFStringRef description
,
455 CFDictionaryRef options
)
457 #if !TARGET_OS_IPHONE
458 SecAccessRef access
= NULL
;
459 CFBooleanRef allowRoot
= NULL
;
460 CFArrayRef allowedExecutables
= NULL
;
461 SecKeychainAttribute attributes
[4];
462 SecKeychainAttributeList attributeList
= { 0, attributes
};
464 SecKeychainItemRef item
= NULL
;
468 if (options
!= NULL
) {
469 if (isA_CFDictionary(options
)) {
470 allowRoot
= CFDictionaryGetValue(options
, kSCKeychainOptionsAllowRoot
);
471 allowedExecutables
= CFDictionaryGetValue(options
, kSCKeychainOptionsAllowedExecutables
);
473 _SCErrorSet(kSCStatusInvalidArgument
);
478 if (!isA_CFString(unique_id
) ||
479 ((label
!= NULL
) && !isA_CFString (label
)) ||
480 ((description
!= NULL
) && !isA_CFString (description
)) ||
481 ((account
!= NULL
) && !isA_CFString (account
)) ||
482 ((password
!= NULL
) && !isA_CFData (password
)) ||
483 ((allowRoot
!= NULL
) && !isA_CFBoolean(allowRoot
)) ||
484 ((allowedExecutables
!= NULL
) && !isA_CFArray (allowedExecutables
)) ||
485 ((allowRoot
!= NULL
) && (allowedExecutables
!= NULL
))) {
486 _SCErrorSet(kSCStatusInvalidArgument
);
490 if ((allowRoot
!= NULL
) && CFBooleanGetValue(allowRoot
)) {
491 access
= _SCSecAccessCreateForUID(0);
492 if (access
== NULL
) {
495 } else if (allowedExecutables
!= NULL
) {
496 access
= _SCSecAccessCreateForExecutables(label
, allowedExecutables
);
497 if (access
== NULL
) {
502 for (i
= 0; i
< 4; i
++) {
503 CFStringRef str
= NULL
;
504 SecKeychainAttrType tag
= 0;
509 tag
= kSecServiceItemAttr
;
513 tag
= kSecLabelItemAttr
;
517 tag
= kSecDescriptionItemAttr
;
521 tag
= kSecAccountItemAttr
;
529 attributes
[n
].tag
= tag
;
530 attributes
[n
].data
= _SC_cfstring_to_cstring(str
, NULL
, 0, kCFStringEncodingUTF8
);
531 attributes
[n
].length
= strlen(attributes
[n
].data
);
535 status
= findKeychainItem(keychain
,
536 attributes
[0].length
,
541 const void *pw
= NULL
;
544 // keychain item exists
545 if (password
!= NULL
) {
546 pw
= CFDataGetBytePtr(password
);
547 pw_len
= CFDataGetLength(password
);
550 attributeList
.count
= n
;
551 status
= SecKeychainItemModifyContent(item
,
558 case errSecItemNotFound
: {
560 if (password
== NULL
) {
561 // creating new keychain item and password not specified
562 status
= kSCStatusInvalidArgument
;
566 attributeList
.count
= n
;
567 status
= SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass
,
569 CFDataGetLength(password
),
570 CFDataGetBytePtr(password
),
584 if (access
!= NULL
) CFRelease(access
);
585 if (item
!= NULL
) CFRelease(item
);
587 for (i
= 0; i
< n
; i
++) {
588 CFAllocatorDeallocate(NULL
, attributes
[i
].data
);
591 if (status
!= noErr
) {
597 #else // !TARGET_OS_IPHONE
598 _SCErrorSet(kSCStatusAccessError
);
600 #endif // !TARGET_OS_IPHONE
605 #pragma mark "System" Keychain APIs (w/SCPreferences)
608 #include "SCHelper_client.h"
612 #include <sys/errno.h>
615 #if !TARGET_OS_IPHONE
617 __SCPreferencesSystemKeychainPasswordItemCopy_helper(SCPreferencesRef prefs
,
618 CFStringRef unique_id
)
620 CFDataRef data
= NULL
;
622 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
623 uint32_t status
= kSCStatusOK
;
624 CFDataRef reply
= NULL
;
626 if (prefsPrivate
->helper
== -1) {
627 ok
= __SCPreferencesCreate_helper(prefs
);
633 ok
= _SCSerializeString(unique_id
, &data
, NULL
, NULL
);
638 // have the helper set the "System" Keychain password
639 ok
= _SCHelperExec(prefsPrivate
->helper
,
640 SCHELPER_MSG_KEYCHAIN_COPY
,
644 if (data
!= NULL
) CFRelease(data
);
649 if (status
!= kSCStatusOK
) {
658 if (prefsPrivate
->helper
!= -1) {
659 _SCHelperClose(prefsPrivate
->helper
);
660 prefsPrivate
->helper
= -1;
663 status
= kSCStatusAccessError
;
668 if (reply
!= NULL
) CFRelease(reply
);
672 #endif // !TARGET_OS_IPHONE
676 _SCPreferencesSystemKeychainPasswordItemCopy(SCPreferencesRef prefs
,
677 CFStringRef unique_id
)
679 #if !TARGET_OS_IPHONE
680 SecKeychainRef keychain
= NULL
;
681 CFDataRef password
= NULL
;
682 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
685 /* sorry, you must provide a session */
686 _SCErrorSet(kSCStatusNoPrefsSession
);
690 if (!isA_CFString(unique_id
)) {
691 _SCErrorSet(kSCStatusInvalidArgument
);
695 if (prefsPrivate
->authorizationData
!= NULL
) {
696 password
= __SCPreferencesSystemKeychainPasswordItemCopy_helper(prefs
, unique_id
);
700 keychain
= _SCSecKeychainCopySystemKeychain();
701 if (keychain
== NULL
) {
705 password
= _SCSecKeychainPasswordItemCopy(keychain
, unique_id
);
709 if (keychain
!= NULL
) CFRelease(keychain
);
711 #else // !TARGET_OS_IPHONE
712 _SCErrorSet(kSCStatusAccessError
);
714 #endif // !TARGET_OS_IPHONE
719 _SCPreferencesSystemKeychainPasswordItemExists(SCPreferencesRef prefs
,
720 CFStringRef unique_id
)
722 #if !TARGET_OS_IPHONE
723 SecKeychainRef keychain
= NULL
;
725 // SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
728 /* sorry, you must provide a session */
729 _SCErrorSet(kSCStatusNoPrefsSession
);
733 if (!isA_CFString(unique_id
)) {
734 _SCErrorSet(kSCStatusInvalidArgument
);
738 // if (prefsPrivate->authorizationData != NULL) {
739 // ok = __SCPreferencesSystemKeychainPasswordItemExists_helper(prefs, unique_id);
743 keychain
= _SCSecKeychainCopySystemKeychain();
744 if (keychain
== NULL
) {
748 ok
= _SCSecKeychainPasswordItemExists(keychain
, unique_id
);
752 if (keychain
!= NULL
) CFRelease(keychain
);
754 #else // !TARGET_OS_IPHONE
755 _SCErrorSet(kSCStatusAccessError
);
757 #endif // !TARGET_OS_IPHONE
761 #if !TARGET_OS_IPHONE
763 __SCPreferencesSystemKeychainPasswordItemRemove_helper(SCPreferencesRef prefs
,
764 CFStringRef unique_id
)
766 CFDataRef data
= NULL
;
768 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
769 uint32_t status
= kSCStatusOK
;
770 CFDataRef reply
= NULL
;
772 if (prefsPrivate
->helper
== -1) {
773 ok
= __SCPreferencesCreate_helper(prefs
);
779 ok
= _SCSerializeString(unique_id
, &data
, NULL
, NULL
);
784 // have the helper set the "System" Keychain password
785 ok
= _SCHelperExec(prefsPrivate
->helper
,
786 SCHELPER_MSG_KEYCHAIN_REMOVE
,
790 if (data
!= NULL
) CFRelease(data
);
795 if (status
!= kSCStatusOK
) {
804 if (prefsPrivate
->helper
!= -1) {
805 _SCHelperClose(prefsPrivate
->helper
);
806 prefsPrivate
->helper
= -1;
809 status
= kSCStatusAccessError
;
814 if (reply
!= NULL
) CFRelease(reply
);
818 #endif // !TARGET_OS_IPHONE
822 _SCPreferencesSystemKeychainPasswordItemRemove(SCPreferencesRef prefs
,
823 CFStringRef unique_id
)
825 #if !TARGET_OS_IPHONE
826 SecKeychainRef keychain
= NULL
;
828 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
831 /* sorry, you must provide a session */
832 _SCErrorSet(kSCStatusNoPrefsSession
);
836 if (!isA_CFString(unique_id
)) {
837 _SCErrorSet(kSCStatusInvalidArgument
);
841 if (prefsPrivate
->authorizationData
!= NULL
) {
842 ok
= __SCPreferencesSystemKeychainPasswordItemRemove_helper(prefs
, unique_id
);
846 keychain
= _SCSecKeychainCopySystemKeychain();
847 if (keychain
== NULL
) {
851 ok
= _SCSecKeychainPasswordItemRemove(keychain
, unique_id
);
855 if (keychain
!= NULL
) CFRelease(keychain
);
857 #else // !TARGET_OS_IPHONE
858 _SCErrorSet(kSCStatusAccessError
);
860 #endif // !TARGET_OS_IPHONE
864 #if !TARGET_OS_IPHONE
866 __SCPreferencesSystemKeychainPasswordItemSet_helper(SCPreferencesRef prefs
,
867 CFStringRef unique_id
,
869 CFStringRef description
,
872 CFDictionaryRef options
)
874 CFDataRef data
= NULL
;
875 CFMutableDictionaryRef newOptions
= NULL
;
877 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
878 uint32_t status
= kSCStatusOK
;
879 CFDataRef reply
= NULL
;
881 if (prefsPrivate
->helper
== -1) {
882 ok
= __SCPreferencesCreate_helper(prefs
);
888 if (isA_CFDictionary(options
)) {
889 CFArrayRef executableURLs
= NULL
;
891 newOptions
= CFDictionaryCreateMutableCopy(NULL
, 0, options
);
893 if (CFDictionaryGetValueIfPresent(newOptions
,
894 kSCKeychainOptionsAllowedExecutables
,
895 (const void **)&executableURLs
)) {
896 CFMutableArrayRef executablePaths
;
901 executablePaths
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
903 path
= copyMyExecutablePath();
905 CFArrayAppendValue(executablePaths
, path
);
909 n
= CFArrayGetCount(executableURLs
);
910 for (i
= 0; i
< n
; i
++) {
911 char fspath
[MAXPATHLEN
];
914 url
= CFArrayGetValueAtIndex(executableURLs
, i
);
915 ok
= CFURLGetFileSystemRepresentation(url
, TRUE
, (UInt8
*)fspath
, sizeof(fspath
));
919 fspath
[sizeof(fspath
) - 1] = '\0';
920 path
= CFDataCreate(NULL
, (UInt8
*)fspath
, strlen(fspath
));
921 CFArrayAppendValue(executablePaths
, path
);
925 CFDictionarySetValue(newOptions
, kSCKeychainOptionsAllowedExecutables
, executablePaths
);
926 CFRelease(executablePaths
);
929 newOptions
= CFDictionaryCreateMutable(NULL
,
931 &kCFTypeDictionaryKeyCallBacks
,
932 &kCFTypeDictionaryValueCallBacks
);
935 if (unique_id
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsUniqueID
, unique_id
);
936 if (label
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsLabel
, label
);
937 if (description
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsDescription
, description
);
938 if (account
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsAccount
, account
);
939 if (password
!= NULL
) CFDictionarySetValue(newOptions
, kSCKeychainOptionsPassword
, password
);
942 // if not AllowRoot and a list of executables was not provided than
943 // pass the current executable
945 if (!CFDictionaryContainsKey(newOptions
, kSCKeychainOptionsAllowRoot
) &&
946 !CFDictionaryContainsKey(newOptions
, kSCKeychainOptionsAllowedExecutables
)) {
949 path
= copyMyExecutablePath();
951 CFArrayRef executablePaths
;
953 executablePaths
= CFArrayCreate(NULL
, (const void **)&path
, 1, &kCFTypeArrayCallBacks
);
955 CFDictionarySetValue(newOptions
, kSCKeychainOptionsAllowedExecutables
, executablePaths
);
956 CFRelease(executablePaths
);
960 ok
= _SCSerialize(newOptions
, &data
, NULL
, NULL
);
961 CFRelease(newOptions
);
966 // have the helper create the "System" Keychain password
967 ok
= _SCHelperExec(prefsPrivate
->helper
,
968 SCHELPER_MSG_KEYCHAIN_SET
,
972 if (data
!= NULL
) CFRelease(data
);
977 if (status
!= kSCStatusOK
) {
986 if (prefsPrivate
->helper
!= -1) {
987 _SCHelperClose(prefsPrivate
->helper
);
988 prefsPrivate
->helper
= -1;
991 status
= kSCStatusAccessError
;
996 if (reply
!= NULL
) CFRelease(reply
);
1000 #endif // !TARGET_OS_IPHONE
1004 _SCPreferencesSystemKeychainPasswordItemSet(SCPreferencesRef prefs
,
1005 CFStringRef unique_id
,
1007 CFStringRef description
,
1008 CFStringRef account
,
1010 CFDictionaryRef options
)
1012 #if !TARGET_OS_IPHONE
1013 SecKeychainRef keychain
= NULL
;
1015 SCPreferencesPrivateRef prefsPrivate
= (SCPreferencesPrivateRef
)prefs
;
1017 if (prefs
== NULL
) {
1018 /* sorry, you must provide a session */
1019 _SCErrorSet(kSCStatusNoPrefsSession
);
1023 if (!isA_CFString(unique_id
) ||
1024 ((label
!= NULL
) && !isA_CFString (label
)) ||
1025 ((description
!= NULL
) && !isA_CFString (description
)) ||
1026 ((account
!= NULL
) && !isA_CFString (account
)) ||
1027 ((password
!= NULL
) && !isA_CFData (password
)) ||
1028 ((options
!= NULL
) && !isA_CFDictionary(options
))) {
1029 _SCErrorSet(kSCStatusInvalidArgument
);
1033 if (prefsPrivate
->authorizationData
!= NULL
) {
1034 ok
= __SCPreferencesSystemKeychainPasswordItemSet_helper(prefs
,
1044 keychain
= _SCSecKeychainCopySystemKeychain();
1045 if (keychain
== NULL
) {
1049 ok
= _SCSecKeychainPasswordItemSet(keychain
,
1059 if (keychain
!= NULL
) CFRelease(keychain
);
1061 #else // !TARGET_OS_IPHONE
1062 _SCErrorSet(kSCStatusAccessError
);
1064 #endif // !TARGET_OS_IPHONE