2 * Copyright (c) 2005 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 * SecTrustSettings.cpp - Public interface for manipulation of Trust Settings.
27 * Created May 10 2005 by dmitch.
30 #include "SecBridge.h"
31 #include "SecTrustSettings.h"
32 #include "SecTrustSettingsPriv.h"
33 #include "TrustSettingsUtils.h"
34 #include "TrustSettings.h"
35 #include "TrustSettingsSchema.h"
36 #include "TrustKeychains.h"
38 #include "SecKeychainPriv.h"
40 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
41 #include <security_utilities/threading.h>
42 #include <security_utilities/globalizer.h>
43 #include <security_utilities/errors.h>
44 #include <security_cdsa_utilities/cssmerrors.h>
45 #include <security_utilities/logging.h>
46 #include <security_utilities/debugging.h>
47 #include <security_utilities/simpleprefs.h>
48 #include <securityd_client/dictionary.h>
49 #include <securityd_client/ssclient.h>
52 #include <CommonCrypto/CommonDigest.h>
54 #define trustSettingsDbg(args...) secdebug("trustSettings", ## args)
57 * Ideally we'd like to implement our own lock to protect the state of the cert stores
58 * without grabbing the global Sec API lock, but we deal with SecCFObjects, so we'll have
59 * to bite the bullet and grab the big lock. We also have our own lock protecting the
60 * global trust settings cache which is also used by the keychain callback function
61 * (which does not grab the Sec API lock).
64 #define BEGIN_RCSAPI \
65 OSStatus __secapiresult; \
68 __secapiresult=noErr; \
70 catch (const MacOSError &err) { __secapiresult=err.osStatus(); } \
71 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } \
72 catch (const std::bad_alloc &) { __secapiresult=memFullErr; } \
73 catch (...) { __secapiresult=internalComponentErr; } \
74 return __secapiresult;
81 #pragma mark --- TrustSettings preferences ---
84 * If Colonel Klink wants to disable user-level Trust Settings, he'll have
85 * to restart the apps which will be affected after he does so. We are not
86 * going to consult system prefs every time we do a cert evaluation. We
87 * consult it once per process and cache the results here.
89 static bool tsUserTrustDisableValid
= false; /* true once we consult prefs */
90 static bool tsUserTrustDisable
= false; /* the cached value */
93 * Determine whether user-level Trust Settings disabled.
95 static bool tsUserTrustSettingsDisabled()
97 if(tsUserTrustDisableValid
) {
98 return tsUserTrustDisable
;
100 tsUserTrustDisable
= false;
102 Dictionary
* dictionary
= Dictionary::CreateDictionary(kSecTrustSettingsPrefsDomain
, Dictionary::US_System
);
105 auto_ptr
<Dictionary
> prefsDict(dictionary
);
106 /* this returns false if the pref isn't there, just like we want */
107 tsUserTrustDisable
= prefsDict
->getBoolValue(kSecTrustSettingsDisableUserTrustSettings
);
110 tsUserTrustDisableValid
= true;
111 return tsUserTrustDisable
;
114 #pragma mark --- TrustSettings global cache ---
117 *** cache submodule - keeps per-app copy of zero or one TrustSettings
118 *** for each domain. Used only by SecTrustSettingsEvaluateCert()
119 *** and SecTrustSettingsCopyQualifiedCerts(); results of
120 *** manipulation by public API functions are not cached.
124 * API/client code has to hold this lock when doing anything with any of
125 * the TrustSettings maintained here.
126 * It's recursive to accomodate CodeSigning's need to do cert verification
127 * (while we evaluate app equivalence).
129 static ModuleNexus
<RecursiveMutex
> sutCacheLock
;
131 #define TRUST_SETTINGS_NUM_DOMAINS 3
134 * The three global TrustSettings.
135 * We rely on the fact the the domain enums start with 0; we use
136 * the domain value as an index into the following two arrays.
138 static TrustSettings
*globalTrustSettings
[TRUST_SETTINGS_NUM_DOMAINS
] =
142 * Indicates "the associated global here is currently valid; if there isn't a
143 * globalTrustSettings[domain], don't try to find one"
145 static bool globalTrustSettingsValid
[TRUST_SETTINGS_NUM_DOMAINS
] =
146 {false, false, false};
148 /* remember the fact that we've registered our KC callback */
149 static bool sutRegisteredCallback
= false;
151 static void tsRegisterCallback();
154 * Assign global TrustSetting to new incoming value, which may be NULL.
155 * Caller holds sutCacheLock.
157 static void tsSetGlobalTrustSettings(
159 SecTrustSettingsDomain domain
)
161 assert(((int)domain
>= 0) && ((int)domain
< TRUST_SETTINGS_NUM_DOMAINS
));
163 trustSettingsDbg("tsSetGlobalTrustSettings domain %d: caching TS %p old TS %p",
164 (int)domain
, ts
, globalTrustSettings
[domain
]);
165 delete globalTrustSettings
[domain
];
166 globalTrustSettings
[domain
] = ts
;
167 globalTrustSettingsValid
[domain
] = ts
? true : false;
168 tsRegisterCallback();
172 * Obtain global TrustSettings for specified domain if it exists.
173 * Returns NULL if there is simply no TS for that domain.
174 * The TS, if returned, belongs to this cache module.
175 * Caller holds sutCacheLock.
177 static TrustSettings
*tsGetGlobalTrustSettings(
178 SecTrustSettingsDomain domain
)
180 assert(((int)domain
>= 0) && ((int)domain
< TRUST_SETTINGS_NUM_DOMAINS
));
182 if((domain
== kSecTrustSettingsDomainUser
) && tsUserTrustSettingsDisabled()) {
183 trustSettingsDbg("tsGetGlobalTrustSettings: skipping DISABLED user domain");
187 if(globalTrustSettingsValid
[domain
]) {
188 // ready or not, use this
189 return globalTrustSettings
[domain
];
191 assert(globalTrustSettings
[domain
] == NULL
);
193 /* try to find one */
194 OSStatus result
= noErr
;
195 TrustSettings
*ts
= NULL
;
196 /* don't create; trim if found */
197 result
= TrustSettings::CreateTrustSettings(domain
, CREATE_NO
, TRIM_YES
, ts
);
198 if(result
!= noErr
&& result
!= errSecNoTrustSettings
) {
200 MacOSError::throwMe(result
);
202 else if (result
!= noErr
) {
204 * No TrustSettings for this domain, actually a fairly common case.
205 * Optimize: don't bother trying this again.
207 trustSettingsDbg("tsGetGlobalTrustSettings: flagging known NULL");
208 globalTrustSettingsValid
[domain
] = true;
209 tsRegisterCallback();
213 tsSetGlobalTrustSettings(ts
, domain
);
218 * Purge TrustSettings cache.
219 * Called by Keychain Event callback and by our API functions that
220 * modify trust settings.
221 * Caller can NOT hold sutCacheLock.
223 static void tsPurgeCache()
227 StLock
<Mutex
> _(sutCacheLock());
228 trustSettingsDbg("tsPurgeCache");
229 for(domain
=0; domain
<TRUST_SETTINGS_NUM_DOMAINS
; domain
++) {
230 tsSetGlobalTrustSettings(NULL
, domain
);
235 * Keychain event callback function, for notification by other processes that
236 * user trust list(s) has/have changed.
238 static OSStatus
tsTrustSettingsCallback (
239 SecKeychainEvent keychainEvent
,
240 SecKeychainCallbackInfo
*info
,
243 trustSettingsDbg("tsTrustSettingsCallback, event %d", (int)keychainEvent
);
244 if(keychainEvent
!= kSecTrustSettingsChangedEvent
) {
245 /* should not happen, right? */
248 if(info
->pid
== getpid()) {
250 * Avoid dup cache invalidates: we already dealt with this event.
252 trustSettingsDbg("cacheEventCallback: our pid, skipping");
261 * Ensure that we've registered for kSecTrustSettingsChangedEvent callbacks
263 static void tsRegisterCallback()
265 if(sutRegisteredCallback
) {
268 trustSettingsDbg("tsRegisterCallback: registering callback");
269 OSStatus ortn
= SecKeychainAddCallback(tsTrustSettingsCallback
,
270 kSecTrustSettingsChangedEventMask
, NULL
);
272 trustSettingsDbg("tsRegisterCallback: SecKeychainAddCallback returned %ld", ortn
);
273 /* Not sure how this could ever happen - maybe if there is no run loop active? */
275 sutRegisteredCallback
= true;
278 #pragma mark --- Static functions ---
282 * Called by API code when a trust list has changed; we notify other processes
283 * and purge our own cache.
285 static void tsTrustSettingsChanged()
289 /* The only interesting data is our pid */
290 NameValueDictionary nvd
;
291 pid_t ourPid
= getpid();
292 nvd
.Insert (new NameValuePair (PID_KEY
,
293 CssmData (reinterpret_cast<void*>(&ourPid
), sizeof (pid_t
))));
297 trustSettingsDbg("tsTrustSettingsChanged: posting notification");
298 SecurityServer::ClientSession
cs (Allocator::standard(), Allocator::standard());
299 cs
.postNotification (SecurityServer::kNotificationDomainDatabase
,
300 kSecTrustSettingsChangedEvent
, data
);
305 * Common code for SecTrustSettingsCopyTrustSettings(),
306 * SecTrustSettingsCopyModificationDate().
308 static OSStatus
tsCopyTrustSettings(
309 SecCertificateRef cert
,
310 SecTrustSettingsDomain domain
,
311 CFArrayRef
*trustSettings
, /* optionally RETURNED */
312 CFDateRef
*modDate
) /* optionally RETURNED */
318 /* obtain fresh full copy from disk */
322 result
= TrustSettings::CreateTrustSettings(domain
, CREATE_NO
, TRIM_NO
, ts
);
324 // rather than throw these results, just return them because we are at the top level
325 if (result
== errSecNoTrustSettings
) {
326 return errSecItemNotFound
;
328 else if (result
!= noErr
) {
332 auto_ptr
<TrustSettings
>_(ts
); // make sure this gets deleted just in case something throws underneath
335 *trustSettings
= ts
->copyTrustSettings(cert
);
338 *modDate
= ts
->copyModDate(cert
);
345 * Common code for SecTrustSettingsCopyQualifiedCerts() and
346 * SecTrustSettingsCopyUnrestrictedRoots().
348 static OSStatus
tsCopyCertsCommon(
349 /* usage constraints, all optional */
350 const CSSM_OID
*policyOID
,
351 const char *policyString
,
352 SecTrustSettingsKeyUsage keyUsage
,
353 /* constrain to only roots */
355 /* per-domain enables */
359 CFArrayRef
*certArray
) /* RETURNED */
361 StLock
<Mutex
> _TC(sutCacheLock());
362 StLock
<Mutex
> _TK(SecTrustKeychainsGetMutex());
364 TS_REQUIRED(certArray
)
366 /* this relies on the domain enums being numbered 0..2, user..system */
367 bool domainEnable
[3] = {user
, admin
, system
};
369 /* we'll retain it again before successful exit */
370 CFRef
<CFMutableArrayRef
> outArray(CFArrayCreateMutable(NULL
, 0,
371 &kCFTypeArrayCallBacks
));
374 * Search all keychains - user's, System.keychain, system root store,
375 * system intermdiates as appropriate
377 StorageManager::KeychainList keychains
;
380 globals().storageManager
.getSearchList(keychains
);
383 adminKc
= globals().storageManager
.make(ADMIN_CERT_STORE_PATH
, false);
384 keychains
.push_back(adminKc
);
386 Keychain sysRootKc
= globals().storageManager
.make(SYSTEM_ROOT_STORE_PATH
, false);
387 keychains
.push_back(sysRootKc
);
388 Keychain sysCertKc
= globals().storageManager
.make(SYSTEM_CERT_STORE_PATH
, false);
389 keychains
.push_back(sysCertKc
);
391 assert(kSecTrustSettingsDomainUser
== 0);
392 for(unsigned domain
=0; domain
<TRUST_SETTINGS_NUM_DOMAINS
; domain
++) {
393 if(!domainEnable
[domain
]) {
396 TrustSettings
*ts
= tsGetGlobalTrustSettings(domain
);
400 ts
->findQualifiedCerts(keychains
,
401 false, /* !findAll */
403 policyOID
, policyString
, keyUsage
,
406 *certArray
= outArray
;
407 CFRetain(*certArray
);
408 trustSettingsDbg("tsCopyCertsCommon: %ld certs found",
409 CFArrayGetCount(outArray
));
413 #pragma mark --- SPI functions ---
417 * Fundamental routine used by TP to ascertain status of one cert.
419 * Returns true in *foundMatchingEntry if a trust setting matching
420 * specific constraints was found for the cert. Returns true in
421 * *foundAnyEntry if any entry was found for the cert, even if it
422 * did not match the specified constraints. The TP uses this to
423 * optimize for the case where a cert is being evaluated for
424 * one type of usage, and then later for another type. If
425 * foundAnyEntry is false, the second evaluation need not occur.
427 * Returns the domain in which a setting was found in *foundDomain.
429 * Allowed errors applying to the specified cert evaluation
430 * are returned in a mallocd array in *allowedErrors and must
431 * be freed by caller.
433 * The design of the entire TrustSettings module is centered around
434 * optimizing the performance of this routine (security concerns
435 * aside, that is). It's why the per-cert dictionaries are stored
436 * as a dictionary, keyed off of the cert hash. It's why TrustSettings
437 * are cached in memory by tsGetGlobalTrustSettings(), and why those
438 * cached TrustSettings objects are 'trimmed' of dictionary fields
439 * which are not needed to verify a cert.
441 * The API functions which are used to manipulate Trust Settings
442 * are called infrequently and need not be particularly fast since
443 * they result in user interaction for authentication. Thus they do
444 * not use cached TrustSettings as this function does.
446 OSStatus
SecTrustSettingsEvaluateCert(
447 CFStringRef certHashStr
,
448 /* parameters describing the current cert evalaution */
449 const CSSM_OID
*policyOID
,
450 const char *policyString
, /* optional */
451 uint32 policyStringLen
,
452 SecTrustSettingsKeyUsage keyUsage
, /* optional */
453 bool isRootCert
, /* for checking default setting */
454 /* RETURNED values */
455 SecTrustSettingsDomain
*foundDomain
,
456 CSSM_RETURN
**allowedErrors
, /* mallocd */
457 uint32
*numAllowedErrors
,
458 SecTrustSettingsResult
*resultType
,
459 bool *foundMatchingEntry
,
464 StLock
<Mutex
> _(sutCacheLock());
466 TS_REQUIRED(certHashStr
)
467 TS_REQUIRED(foundDomain
)
468 TS_REQUIRED(allowedErrors
)
469 TS_REQUIRED(numAllowedErrors
)
470 TS_REQUIRED(resultType
)
471 TS_REQUIRED(foundMatchingEntry
)
472 TS_REQUIRED(foundAnyEntry
)
474 /* ensure a NULL_terminated string */
475 auto_array
<char> polStr
;
476 if(policyString
!= NULL
&& policyStringLen
> 0) {
477 polStr
.allocate(policyStringLen
+ 1);
478 memmove(polStr
.get(), policyString
, policyStringLen
);
479 if(policyString
[policyStringLen
- 1] != '\0') {
480 (polStr
.get())[policyStringLen
] = '\0';
484 /* initial condition - this can grow if we inspect multiple TrustSettings */
485 *allowedErrors
= NULL
;
486 *numAllowedErrors
= 0;
489 * This loop relies on the ordering of the SecTrustSettingsDomain enum:
490 * search user first, then admin, then system.
492 assert(kSecTrustSettingsDomainAdmin
== (kSecTrustSettingsDomainUser
+ 1));
493 assert(kSecTrustSettingsDomainSystem
== (kSecTrustSettingsDomainAdmin
+ 1));
494 bool foundAny
= false;
495 for(unsigned domain
=kSecTrustSettingsDomainUser
;
496 domain
<=kSecTrustSettingsDomainSystem
;
498 TrustSettings
*ts
= tsGetGlobalTrustSettings(domain
);
503 /* validate cert returns true if matching entry was found */
504 bool foundAnyHere
= false;
505 bool found
= ts
->evaluateCert(certHashStr
, policyOID
,
506 polStr
.get(), keyUsage
, isRootCert
,
507 allowedErrors
, numAllowedErrors
, resultType
, &foundAnyHere
);
511 * Note this, even though we may overwrite it later if this
512 * is an Unspecified entry and we find a definitive entry
515 *foundDomain
= domain
;
517 if(found
&& (*resultType
!= kSecTrustSettingsResultUnspecified
)) {
518 trustSettingsDbg("SecTrustSettingsEvaluateCert: found in domain %d", domain
);
519 *foundAnyEntry
= true;
520 *foundMatchingEntry
= true;
523 foundAny
|= foundAnyHere
;
525 trustSettingsDbg("SecTrustSettingsEvaluateCert: NOT FOUND");
526 *foundAnyEntry
= foundAny
;
527 *foundMatchingEntry
= false;
533 * Obtain trusted certs which match specified usage.
534 * Only certs with a SecTrustSettingsResult of
535 * kSecTrustSettingsResultTrustRoot or
536 * or kSecTrustSettingsResultTrustAsRoot will be returned.
537 * To be used by SecureTransport for its SSLSetTrustedRoots() call;
538 * I hope nothing else has to use this...
539 * Caller must CFRelease the returned CFArrayRef.
541 OSStatus
SecTrustSettingsCopyQualifiedCerts(
542 const CSSM_OID
*policyOID
,
543 const char *policyString
, /* optional */
544 uint32 policyStringLen
,
545 SecTrustSettingsKeyUsage keyUsage
, /* optional */
546 CFArrayRef
*certArray
) /* RETURNED */
550 /* ensure a NULL_terminated string */
551 auto_array
<char> polStr
;
552 if(policyString
!= NULL
) {
553 polStr
.allocate(policyStringLen
+ 1);
554 memmove(polStr
.get(), policyString
, policyStringLen
);
555 if(policyString
[policyStringLen
- 1] != '\0') {
556 (polStr
.get())[policyStringLen
] = '\0';
560 return tsCopyCertsCommon(policyOID
, polStr
.get(), keyUsage
,
561 false, /* !onlyRoots */
562 true, true, true, /* all domains */
569 * Obtain unrestricted root certs fromt eh specified domain(s).
570 * Only returns roots with no usage constraints.
571 * Caller must CFRelease the returned CFArrayRef.
573 OSStatus
SecTrustSettingsCopyUnrestrictedRoots(
577 CFArrayRef
*certArray
) /* RETURNED */
581 return tsCopyCertsCommon(NULL
, NULL
, NULL
, /* no constraints */
582 true, /* onlyRoots */
589 static const char hexChars
[16] = {
590 '0', '1', '2', '3', '4', '5', '6', '7',
591 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
595 * Obtain a string representing a cert's SHA1 digest. This string is
596 * the key used to look up per-cert trust settings in a TrustSettings record.
598 CFStringRef
SecTrustSettingsCertHashStrFromCert(
599 SecCertificateRef certRef
)
601 if(certRef
== NULL
) {
605 if(certRef
== kSecTrustSettingsDefaultRootCertSetting
) {
606 /* use this string instead of the cert hash as the dictionary key */
607 trustSettingsDbg("SecTrustSettingsCertHashStrFromCert: DefaultSetting");
608 return kSecTrustRecordDefaultRootCert
;
612 OSStatus ortn
= SecCertificateGetData(certRef
, &certData
);
616 return SecTrustSettingsCertHashStrFromData(certData
.Data
, certData
.Length
);
619 CFStringRef
SecTrustSettingsCertHashStrFromData(
623 unsigned char digest
[CC_SHA1_DIGEST_LENGTH
];
624 char asciiDigest
[(2 * CC_SHA1_DIGEST_LENGTH
) + 1];
626 char *outp
= asciiDigest
;
627 unsigned char *inp
= digest
;
633 CC_SHA1(cert
, certLen
, digest
);
635 for(dex
=0; dex
<CC_SHA1_DIGEST_LENGTH
; dex
++) {
637 outp
[1] = hexChars
[c
& 0xf];
639 outp
[0] = hexChars
[c
];
643 return CFStringCreateWithCString(NULL
, asciiDigest
, kCFStringEncodingASCII
);
647 * Add a cert's TrustSettings to a non-persistent TrustSettings record.
648 * No locking or cache flushing here; it's all local to the TrustSettings
651 OSStatus
SecTrustSettingsSetTrustSettingsExternal(
652 CFDataRef settingsIn
, /* optional */
653 SecCertificateRef certRef
, /* optional */
654 CFTypeRef trustSettingsDictOrArray
, /* optional */
655 CFDataRef
*settingsOut
) /* RETURNED */
659 TS_REQUIRED(settingsOut
)
664 result
= TrustSettings::CreateTrustSettings(kSecTrustSettingsDomainMemory
, settingsIn
, ts
);
665 if (result
!= noErr
) {
669 auto_ptr
<TrustSettings
>_(ts
);
671 if(certRef
!= NULL
) {
672 ts
->setTrustSettings(certRef
, trustSettingsDictOrArray
);
674 *settingsOut
= ts
->createExternal();
680 #pragma mark --- API functions ---
682 OSStatus
SecTrustSettingsCopyTrustSettings(
683 SecCertificateRef certRef
,
684 SecTrustSettingsDomain domain
,
685 CFArrayRef
*trustSettings
) /* RETURNED */
687 TS_REQUIRED(trustSettings
)
689 OSStatus result
= tsCopyTrustSettings(certRef
, domain
, trustSettings
, NULL
);
690 if (result
== noErr
&& *trustSettings
== NULL
) {
691 result
= errSecItemNotFound
; /* documented result if no trust settings exist */
696 OSStatus
SecTrustSettingsCopyModificationDate(
697 SecCertificateRef certRef
,
698 SecTrustSettingsDomain domain
,
699 CFDateRef
*modificationDate
) /* RETURNED */
701 TS_REQUIRED(modificationDate
)
703 OSStatus result
= tsCopyTrustSettings(certRef
, domain
, NULL
, modificationDate
);
704 if (result
== noErr
&& *modificationDate
== NULL
) {
705 result
= errSecItemNotFound
; /* documented result if no trust settings exist */
710 /* works with existing and with new cert */
711 OSStatus
SecTrustSettingsSetTrustSettings(
712 SecCertificateRef certRef
,
713 SecTrustSettingsDomain domain
,
714 CFTypeRef trustSettingsDictOrArray
)
720 if(domain
== kSecTrustSettingsDomainSystem
) {
721 return errSecDataNotModifiable
;
727 result
= TrustSettings::CreateTrustSettings(domain
, CREATE_YES
, TRIM_NO
, ts
);
728 if (result
!= noErr
) {
732 auto_ptr
<TrustSettings
>_(ts
);
734 ts
->setTrustSettings(certRef
, trustSettingsDictOrArray
);
736 tsTrustSettingsChanged();
742 OSStatus
SecTrustSettingsRemoveTrustSettings(
743 SecCertificateRef cert
,
744 SecTrustSettingsDomain domain
)
750 if(domain
== kSecTrustSettingsDomainSystem
) {
751 return errSecDataNotModifiable
;
757 result
= TrustSettings::CreateTrustSettings(domain
, CREATE_NO
, TRIM_NO
, ts
);
758 if (result
!= noErr
) {
762 auto_ptr
<TrustSettings
>_(ts
);
764 /* deleteTrustSettings throws if record not found */
765 trustSettingsDbg("SecTrustSettingsRemoveTrustSettings: deleting from domain %d",
767 ts
->deleteTrustSettings(cert
);
769 tsTrustSettingsChanged();
775 /* get all certs listed in specified domain */
776 OSStatus
SecTrustSettingsCopyCertificates(
777 SecTrustSettingsDomain domain
,
778 CFArrayRef
*certArray
)
782 TS_REQUIRED(certArray
)
787 result
= TrustSettings::CreateTrustSettings(domain
, CREATE_NO
, TRIM_NO
, ts
);
788 if (result
!= noErr
) {
792 auto_ptr
<TrustSettings
>_(ts
);
794 CFMutableArrayRef outArray
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
797 * Keychains to search: user's search list, System.keychain, system root store,
798 * system intermdiates, as appropriate
800 StorageManager::KeychainList keychains
;
805 case kSecTrustSettingsDomainUser
:
806 /* user search list */
807 globals().storageManager
.getSearchList(keychains
);
808 /* drop thru to next case */
809 case kSecTrustSettingsDomainAdmin
:
810 /* admin certs in system keychain */
811 adminKc
= globals().storageManager
.make(ADMIN_CERT_STORE_PATH
, false);
812 keychains
.push_back(adminKc
);
813 /* system-wide intermediate certs */
814 sysCertKc
= globals().storageManager
.make(SYSTEM_CERT_STORE_PATH
, false);
815 keychains
.push_back(sysCertKc
);
816 /* drop thru to next case */
817 case kSecTrustSettingsDomainSystem
:
818 /* and, for all cases, immutable system root store */
819 sysRootKc
= globals().storageManager
.make(SYSTEM_ROOT_STORE_PATH
, false);
820 keychains
.push_back(sysRootKc
);
822 /* already validated when we created the TrustSettings */
825 ts
->findCerts(keychains
, outArray
);
826 if(CFArrayGetCount(outArray
) == 0) {
828 return errSecNoTrustSettings
;
830 *certArray
= outArray
;
835 * Obtain an external, portable representation of the specified
836 * domain's TrustSettings. Caller must CFRelease the returned data.
838 OSStatus
SecTrustSettingsCreateExternalRepresentation(
839 SecTrustSettingsDomain domain
,
840 CFDataRef
*trustSettings
)
844 TS_REQUIRED(trustSettings
)
849 result
= TrustSettings::CreateTrustSettings(domain
, CREATE_NO
, TRIM_NO
, ts
);
850 if (result
!= noErr
) {
854 auto_ptr
<TrustSettings
>_(ts
);
856 *trustSettings
= ts
->createExternal();
863 * Import trust settings, obtained via SecTrustSettingsCreateExternalRepresentation,
864 * into the specified domain.
866 OSStatus
SecTrustSettingsImportExternalRepresentation(
867 SecTrustSettingsDomain domain
,
868 CFDataRef trustSettings
) /* optional - NULL means empty settings */
872 if(domain
== kSecTrustSettingsDomainSystem
) {
873 return errSecDataNotModifiable
;
879 result
= TrustSettings::CreateTrustSettings(domain
, trustSettings
, ts
);
880 if (result
!= noErr
) {
884 auto_ptr
<TrustSettings
>_(ts
);
887 tsTrustSettingsChanged();