2 * Copyright (c) 2005,2011-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 * SecTrustSettings.cpp - Public interface for manipulation of Trust Settings.
29 #include "SecBridge.h"
30 #include "SecTrustSettings.h"
31 #include "SecTrustSettingsPriv.h"
32 #include "TrustSettingsUtils.h"
33 #include "TrustSettings.h"
34 #include "TrustSettingsSchema.h"
35 #include "TrustKeychains.h"
37 #include "SecKeychainPriv.h"
39 #include <security_utilities/threading.h>
40 #include <security_utilities/globalizer.h>
41 #include <security_utilities/errors.h>
42 #include <security_cdsa_utilities/cssmerrors.h>
43 #include <security_utilities/logging.h>
44 #include <security_utilities/debugging.h>
45 #include <security_utilities/simpleprefs.h>
46 #include <securityd_client/dictionary.h>
47 #include <securityd_client/ssclient.h>
50 #include <CommonCrypto/CommonDigest.h>
52 #define trustSettingsDbg(args...) secdebug("trustSettings", ## args)
55 * Ideally we'd like to implement our own lock to protect the state of the cert stores
56 * without grabbing the global Sec API lock, but we deal with SecCFObjects, so we'll have
57 * to bite the bullet and grab the big lock. We also have our own lock protecting the
58 * global trust settings cache which is also used by the keychain callback function
59 * (which does not grab the Sec API lock).
62 #define BEGIN_RCSAPI \
63 OSStatus __secapiresult; \
66 __secapiresult=errSecSuccess; \
68 catch (const MacOSError &err) { __secapiresult=err.osStatus(); } \
69 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } \
70 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } \
71 catch (...) { __secapiresult=errSecInternalComponent; } \
72 return __secapiresult;
79 #pragma mark --- TrustSettings preferences ---
82 * If Colonel Klink wants to disable user-level Trust Settings, he'll have
83 * to restart the apps which will be affected after he does so. We are not
84 * going to consult system prefs every time we do a cert evaluation. We
85 * consult it once per process and cache the results here.
87 static bool tsUserTrustDisableValid
= false; /* true once we consult prefs */
88 static bool tsUserTrustDisable
= false; /* the cached value */
91 * Determine whether user-level Trust Settings disabled.
93 static bool tsUserTrustSettingsDisabled()
95 if(tsUserTrustDisableValid
) {
96 return tsUserTrustDisable
;
98 tsUserTrustDisable
= false;
100 Dictionary
* dictionary
= Dictionary::CreateDictionary(kSecTrustSettingsPrefsDomain
, Dictionary::US_System
);
103 auto_ptr
<Dictionary
> prefsDict(dictionary
);
104 /* this returns false if the pref isn't there, just like we want */
105 tsUserTrustDisable
= prefsDict
->getBoolValue(kSecTrustSettingsDisableUserTrustSettings
);
108 tsUserTrustDisableValid
= true;
109 return tsUserTrustDisable
;
112 #pragma mark --- TrustSettings global cache ---
115 *** cache submodule - keeps per-app copy of zero or one TrustSettings
116 *** for each domain. Used only by SecTrustSettingsEvaluateCert()
117 *** and SecTrustSettingsCopyQualifiedCerts(); results of
118 *** manipulation by public API functions are not cached.
122 * API/client code has to hold this lock when doing anything with any of
123 * the TrustSettings maintained here.
124 * It's recursive to accomodate CodeSigning's need to do cert verification
125 * (while we evaluate app equivalence).
127 static ModuleNexus
<RecursiveMutex
> sutCacheLock
;
129 #define TRUST_SETTINGS_NUM_DOMAINS 3
132 * The three global TrustSettings.
133 * We rely on the fact the the domain enums start with 0; we use
134 * the domain value as an index into the following two arrays.
136 static TrustSettings
*globalTrustSettings
[TRUST_SETTINGS_NUM_DOMAINS
] =
140 * Indicates "the associated global here is currently valid; if there isn't a
141 * globalTrustSettings[domain], don't try to find one"
143 static bool globalTrustSettingsValid
[TRUST_SETTINGS_NUM_DOMAINS
] =
144 {false, false, false};
146 /* remember the fact that we've registered our KC callback */
147 static bool sutRegisteredCallback
= false;
149 static void tsRegisterCallback();
152 * Assign global TrustSetting to new incoming value, which may be NULL.
153 * Caller holds sutCacheLock.
155 static void tsSetGlobalTrustSettings(
157 SecTrustSettingsDomain domain
)
159 assert(((int)domain
>= 0) && ((int)domain
< TRUST_SETTINGS_NUM_DOMAINS
));
161 trustSettingsDbg("tsSetGlobalTrustSettings domain %d: caching TS %p old TS %p",
162 (int)domain
, ts
, globalTrustSettings
[domain
]);
163 delete globalTrustSettings
[domain
];
164 globalTrustSettings
[domain
] = ts
;
165 globalTrustSettingsValid
[domain
] = ts
? true : false;
166 tsRegisterCallback();
170 * Obtain global TrustSettings for specified domain if it exists.
171 * Returns NULL if there is simply no TS for that domain.
172 * The TS, if returned, belongs to this cache module.
173 * Caller holds sutCacheLock.
175 static TrustSettings
*tsGetGlobalTrustSettings(
176 SecTrustSettingsDomain domain
)
178 assert(((int)domain
>= 0) && ((int)domain
< TRUST_SETTINGS_NUM_DOMAINS
));
180 if((domain
== kSecTrustSettingsDomainUser
) && tsUserTrustSettingsDisabled()) {
181 trustSettingsDbg("tsGetGlobalTrustSettings: skipping DISABLED user domain");
185 if(globalTrustSettingsValid
[domain
]) {
186 // ready or not, use this
187 return globalTrustSettings
[domain
];
189 assert(globalTrustSettings
[domain
] == NULL
);
191 /* try to find one */
192 OSStatus result
= errSecSuccess
;
193 TrustSettings
*ts
= NULL
;
194 /* don't create; trim if found */
195 result
= TrustSettings::CreateTrustSettings(domain
, CREATE_NO
, TRIM_YES
, ts
);
196 if ( (domain
!= kSecTrustSettingsDomainSystem
)
197 && (result
== errSecInternalComponent
)) {
199 * Could not connect to ocspd to get the user/admin domain trust settings
200 * This happens in single user mode for example.
201 * Valid flag is set to false and continue.
203 trustSettingsDbg("tsGetGlobalTrustSettings: could not connect to ocspd for domain (%d)",(int)domain
);
204 globalTrustSettingsValid
[domain
] = false;
205 tsRegisterCallback();
208 else if (result
== errSecNoTrustSettings
) {
210 * No TrustSettings for this domain, actually a fairly common case.
211 * Optimize: don't bother trying this again.
213 trustSettingsDbg("tsGetGlobalTrustSettings: flagging known NULL");
214 globalTrustSettingsValid
[domain
] = true;
215 tsRegisterCallback();
218 else if(result
!= errSecSuccess
) {
220 MacOSError::throwMe(result
);
223 tsSetGlobalTrustSettings(ts
, domain
);
228 * Purge TrustSettings cache.
229 * Called by Keychain Event callback and by our API functions that
230 * modify trust settings.
231 * Caller can NOT hold sutCacheLock.
233 static void tsPurgeCache()
237 StLock
<Mutex
> _(sutCacheLock());
238 trustSettingsDbg("tsPurgeCache");
239 for(domain
=0; domain
<TRUST_SETTINGS_NUM_DOMAINS
; domain
++) {
240 tsSetGlobalTrustSettings(NULL
, domain
);
245 * Keychain event callback function, for notification by other processes that
246 * user trust list(s) has/have changed.
248 static OSStatus
tsTrustSettingsCallback (
249 SecKeychainEvent keychainEvent
,
250 SecKeychainCallbackInfo
*info
,
253 trustSettingsDbg("tsTrustSettingsCallback, event %d", (int)keychainEvent
);
254 if(keychainEvent
!= kSecTrustSettingsChangedEvent
) {
255 /* should not happen, right? */
256 return errSecSuccess
;
258 if(info
->pid
== getpid()) {
260 * Avoid dup cache invalidates: we already dealt with this event.
262 trustSettingsDbg("cacheEventCallback: our pid, skipping");
267 return errSecSuccess
;
271 * Ensure that we've registered for kSecTrustSettingsChangedEvent callbacks
273 static void tsRegisterCallback()
275 if(sutRegisteredCallback
) {
278 trustSettingsDbg("tsRegisterCallback: registering callback");
279 OSStatus ortn
= SecKeychainAddCallback(tsTrustSettingsCallback
,
280 kSecTrustSettingsChangedEventMask
, NULL
);
282 trustSettingsDbg("tsRegisterCallback: SecKeychainAddCallback returned %d", (int)ortn
);
283 /* Not sure how this could ever happen - maybe if there is no run loop active? */
285 sutRegisteredCallback
= true;
288 #pragma mark --- Static functions ---
292 * Called by API code when a trust list has changed; we notify other processes
293 * and purge our own cache.
295 static void tsTrustSettingsChanged()
299 /* The only interesting data is our pid */
300 NameValueDictionary nvd
;
301 pid_t ourPid
= getpid();
302 nvd
.Insert (new NameValuePair (PID_KEY
,
303 CssmData (reinterpret_cast<void*>(&ourPid
), sizeof (pid_t
))));
307 trustSettingsDbg("tsTrustSettingsChanged: posting notification");
308 SecurityServer::ClientSession
cs (Allocator::standard(), Allocator::standard());
309 cs
.postNotification (SecurityServer::kNotificationDomainDatabase
,
310 kSecTrustSettingsChangedEvent
, data
);
315 * Common code for SecTrustSettingsCopyTrustSettings(),
316 * SecTrustSettingsCopyModificationDate().
318 static OSStatus
tsCopyTrustSettings(
319 SecCertificateRef cert
,
320 SecTrustSettingsDomain domain
,
321 CFArrayRef
*trustSettings
, /* optionally RETURNED */
322 CFDateRef
*modDate
) /* optionally RETURNED */
328 /* obtain fresh full copy from disk */
332 result
= TrustSettings::CreateTrustSettings(domain
, CREATE_NO
, TRIM_NO
, ts
);
334 // rather than throw these results, just return them because we are at the top level
335 if (result
== errSecNoTrustSettings
) {
336 return errSecItemNotFound
;
338 else if (result
!= errSecSuccess
) {
342 auto_ptr
<TrustSettings
>_(ts
); // make sure this gets deleted just in case something throws underneath
345 *trustSettings
= ts
->copyTrustSettings(cert
);
348 *modDate
= ts
->copyModDate(cert
);
355 * Common code for SecTrustSettingsCopyQualifiedCerts() and
356 * SecTrustSettingsCopyUnrestrictedRoots().
358 static OSStatus
tsCopyCertsCommon(
359 /* usage constraints, all optional */
360 const CSSM_OID
*policyOID
,
361 const char *policyString
,
362 SecTrustSettingsKeyUsage keyUsage
,
363 /* constrain to only roots */
365 /* per-domain enables */
369 CFArrayRef
*certArray
) /* RETURNED */
371 StLock
<Mutex
> _TC(sutCacheLock());
372 StLock
<Mutex
> _TK(SecTrustKeychainsGetMutex());
374 TS_REQUIRED(certArray
)
376 /* this relies on the domain enums being numbered 0..2, user..system */
377 bool domainEnable
[3] = {user
, admin
, system
};
379 /* we'll retain it again before successful exit */
380 CFRef
<CFMutableArrayRef
> outArray(CFArrayCreateMutable(NULL
, 0,
381 &kCFTypeArrayCallBacks
));
384 * Search all keychains - user's, System.keychain, system root store,
385 * system intermdiates as appropriate
387 StorageManager::KeychainList keychains
;
390 globals().storageManager
.getSearchList(keychains
);
393 adminKc
= globals().storageManager
.make(ADMIN_CERT_STORE_PATH
, false);
394 keychains
.push_back(adminKc
);
396 Keychain sysRootKc
= globals().storageManager
.make(SYSTEM_ROOT_STORE_PATH
, false);
397 keychains
.push_back(sysRootKc
);
398 Keychain sysCertKc
= globals().storageManager
.make(SYSTEM_CERT_STORE_PATH
, false);
399 keychains
.push_back(sysCertKc
);
401 assert(kSecTrustSettingsDomainUser
== 0);
402 for(unsigned domain
=0; domain
<TRUST_SETTINGS_NUM_DOMAINS
; domain
++) {
403 if(!domainEnable
[domain
]) {
406 TrustSettings
*ts
= tsGetGlobalTrustSettings(domain
);
410 ts
->findQualifiedCerts(keychains
,
411 false, /* !findAll */
413 policyOID
, policyString
, keyUsage
,
416 *certArray
= outArray
;
417 CFRetain(*certArray
);
418 trustSettingsDbg("tsCopyCertsCommon: %ld certs found",
419 CFArrayGetCount(outArray
));
420 return errSecSuccess
;
423 #pragma mark --- SPI functions ---
427 * Fundamental routine used by TP to ascertain status of one cert.
429 * Returns true in *foundMatchingEntry if a trust setting matching
430 * specific constraints was found for the cert. Returns true in
431 * *foundAnyEntry if any entry was found for the cert, even if it
432 * did not match the specified constraints. The TP uses this to
433 * optimize for the case where a cert is being evaluated for
434 * one type of usage, and then later for another type. If
435 * foundAnyEntry is false, the second evaluation need not occur.
437 * Returns the domain in which a setting was found in *foundDomain.
439 * Allowed errors applying to the specified cert evaluation
440 * are returned in a mallocd array in *allowedErrors and must
441 * be freed by caller.
443 * The design of the entire TrustSettings module is centered around
444 * optimizing the performance of this routine (security concerns
445 * aside, that is). It's why the per-cert dictionaries are stored
446 * as a dictionary, keyed off of the cert hash. It's why TrustSettings
447 * are cached in memory by tsGetGlobalTrustSettings(), and why those
448 * cached TrustSettings objects are 'trimmed' of dictionary fields
449 * which are not needed to verify a cert.
451 * The API functions which are used to manipulate Trust Settings
452 * are called infrequently and need not be particularly fast since
453 * they result in user interaction for authentication. Thus they do
454 * not use cached TrustSettings as this function does.
456 OSStatus
SecTrustSettingsEvaluateCert(
457 CFStringRef certHashStr
,
458 /* parameters describing the current cert evalaution */
459 const CSSM_OID
*policyOID
,
460 const char *policyString
, /* optional */
461 uint32 policyStringLen
,
462 SecTrustSettingsKeyUsage keyUsage
, /* optional */
463 bool isRootCert
, /* for checking default setting */
464 /* RETURNED values */
465 SecTrustSettingsDomain
*foundDomain
,
466 CSSM_RETURN
**allowedErrors
, /* mallocd */
467 uint32
*numAllowedErrors
,
468 SecTrustSettingsResult
*resultType
,
469 bool *foundMatchingEntry
,
474 StLock
<Mutex
> _(sutCacheLock());
476 TS_REQUIRED(certHashStr
)
477 TS_REQUIRED(foundDomain
)
478 TS_REQUIRED(allowedErrors
)
479 TS_REQUIRED(numAllowedErrors
)
480 TS_REQUIRED(resultType
)
481 TS_REQUIRED(foundMatchingEntry
)
482 TS_REQUIRED(foundAnyEntry
)
484 /* ensure a NULL_terminated string */
485 auto_array
<char> polStr
;
486 if(policyString
!= NULL
&& policyStringLen
> 0) {
487 polStr
.allocate(policyStringLen
+ 1);
488 memmove(polStr
.get(), policyString
, policyStringLen
);
489 if(policyString
[policyStringLen
- 1] != '\0') {
490 (polStr
.get())[policyStringLen
] = '\0';
494 /* initial condition - this can grow if we inspect multiple TrustSettings */
495 *allowedErrors
= NULL
;
496 *numAllowedErrors
= 0;
499 * This loop relies on the ordering of the SecTrustSettingsDomain enum:
500 * search user first, then admin, then system.
502 assert(kSecTrustSettingsDomainAdmin
== (kSecTrustSettingsDomainUser
+ 1));
503 assert(kSecTrustSettingsDomainSystem
== (kSecTrustSettingsDomainAdmin
+ 1));
504 bool foundAny
= false;
505 for(unsigned domain
=kSecTrustSettingsDomainUser
;
506 domain
<=kSecTrustSettingsDomainSystem
;
508 TrustSettings
*ts
= tsGetGlobalTrustSettings(domain
);
513 /* validate cert returns true if matching entry was found */
514 bool foundAnyHere
= false;
515 bool found
= ts
->evaluateCert(certHashStr
, policyOID
,
516 polStr
.get(), keyUsage
, isRootCert
,
517 allowedErrors
, numAllowedErrors
, resultType
, &foundAnyHere
);
521 * Note this, even though we may overwrite it later if this
522 * is an Unspecified entry and we find a definitive entry
525 *foundDomain
= domain
;
527 if(found
&& (*resultType
!= kSecTrustSettingsResultUnspecified
)) {
528 trustSettingsDbg("SecTrustSettingsEvaluateCert: found in domain %d", domain
);
529 *foundAnyEntry
= true;
530 *foundMatchingEntry
= true;
531 return errSecSuccess
;
533 foundAny
|= foundAnyHere
;
535 trustSettingsDbg("SecTrustSettingsEvaluateCert: NOT FOUND");
536 *foundAnyEntry
= foundAny
;
537 *foundMatchingEntry
= false;
538 return errSecSuccess
;
543 * Obtain trusted certs which match specified usage.
544 * Only certs with a SecTrustSettingsResult of
545 * kSecTrustSettingsResultTrustRoot or
546 * or kSecTrustSettingsResultTrustAsRoot will be returned.
547 * To be used by SecureTransport for its SSLSetTrustedRoots() call;
548 * I hope nothing else has to use this...
549 * Caller must CFRelease the returned CFArrayRef.
551 OSStatus
SecTrustSettingsCopyQualifiedCerts(
552 const CSSM_OID
*policyOID
,
553 const char *policyString
, /* optional */
554 uint32 policyStringLen
,
555 SecTrustSettingsKeyUsage keyUsage
, /* optional */
556 CFArrayRef
*certArray
) /* RETURNED */
560 /* ensure a NULL_terminated string */
561 auto_array
<char> polStr
;
562 if(policyString
!= NULL
) {
563 polStr
.allocate(policyStringLen
+ 1);
564 memmove(polStr
.get(), policyString
, policyStringLen
);
565 if(policyString
[policyStringLen
- 1] != '\0') {
566 (polStr
.get())[policyStringLen
] = '\0';
570 return tsCopyCertsCommon(policyOID
, polStr
.get(), keyUsage
,
571 false, /* !onlyRoots */
572 true, true, true, /* all domains */
579 * Obtain unrestricted root certs fromt eh specified domain(s).
580 * Only returns roots with no usage constraints.
581 * Caller must CFRelease the returned CFArrayRef.
583 OSStatus
SecTrustSettingsCopyUnrestrictedRoots(
587 CFArrayRef
*certArray
) /* RETURNED */
591 return tsCopyCertsCommon(NULL
, NULL
, NULL
, /* no constraints */
592 true, /* onlyRoots */
599 static const char hexChars
[16] = {
600 '0', '1', '2', '3', '4', '5', '6', '7',
601 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
605 * Obtain a string representing a cert's SHA1 digest. This string is
606 * the key used to look up per-cert trust settings in a TrustSettings record.
608 CFStringRef
SecTrustSettingsCertHashStrFromCert(
609 SecCertificateRef certRef
)
611 if(certRef
== NULL
) {
615 if(certRef
== kSecTrustSettingsDefaultRootCertSetting
) {
616 /* use this string instead of the cert hash as the dictionary key */
617 trustSettingsDbg("SecTrustSettingsCertHashStrFromCert: DefaultSetting");
618 return kSecTrustRecordDefaultRootCert
;
622 OSStatus ortn
= SecCertificateGetData(certRef
, &certData
);
626 return SecTrustSettingsCertHashStrFromData(certData
.Data
, certData
.Length
);
629 CFStringRef
SecTrustSettingsCertHashStrFromData(
633 unsigned char digest
[CC_SHA1_DIGEST_LENGTH
];
634 char asciiDigest
[(2 * CC_SHA1_DIGEST_LENGTH
) + 1];
636 char *outp
= asciiDigest
;
637 unsigned char *inp
= digest
;
643 CC_SHA1(cert
, (CC_LONG
)certLen
, digest
);
645 for(dex
=0; dex
<CC_SHA1_DIGEST_LENGTH
; dex
++) {
647 outp
[1] = hexChars
[c
& 0xf];
649 outp
[0] = hexChars
[c
];
653 return CFStringCreateWithCString(NULL
, asciiDigest
, kCFStringEncodingASCII
);
657 * Add a cert's TrustSettings to a non-persistent TrustSettings record.
658 * No locking or cache flushing here; it's all local to the TrustSettings
661 OSStatus
SecTrustSettingsSetTrustSettingsExternal(
662 CFDataRef settingsIn
, /* optional */
663 SecCertificateRef certRef
, /* optional */
664 CFTypeRef trustSettingsDictOrArray
, /* optional */
665 CFDataRef
*settingsOut
) /* RETURNED */
669 TS_REQUIRED(settingsOut
)
674 result
= TrustSettings::CreateTrustSettings(kSecTrustSettingsDomainMemory
, settingsIn
, ts
);
675 if (result
!= errSecSuccess
) {
679 auto_ptr
<TrustSettings
>_(ts
);
681 if(certRef
!= NULL
) {
682 ts
->setTrustSettings(certRef
, trustSettingsDictOrArray
);
684 *settingsOut
= ts
->createExternal();
685 return errSecSuccess
;
690 #pragma mark --- API functions ---
692 OSStatus
SecTrustSettingsCopyTrustSettings(
693 SecCertificateRef certRef
,
694 SecTrustSettingsDomain domain
,
695 CFArrayRef
*trustSettings
) /* RETURNED */
697 TS_REQUIRED(trustSettings
)
699 OSStatus result
= tsCopyTrustSettings(certRef
, domain
, trustSettings
, NULL
);
700 if (result
== errSecSuccess
&& *trustSettings
== NULL
) {
701 result
= errSecItemNotFound
; /* documented result if no trust settings exist */
706 OSStatus
SecTrustSettingsCopyModificationDate(
707 SecCertificateRef certRef
,
708 SecTrustSettingsDomain domain
,
709 CFDateRef
*modificationDate
) /* RETURNED */
711 TS_REQUIRED(modificationDate
)
713 OSStatus result
= tsCopyTrustSettings(certRef
, domain
, NULL
, modificationDate
);
714 if (result
== errSecSuccess
&& *modificationDate
== NULL
) {
715 result
= errSecItemNotFound
; /* documented result if no trust settings exist */
720 /* works with existing and with new cert */
721 OSStatus
SecTrustSettingsSetTrustSettings(
722 SecCertificateRef certRef
,
723 SecTrustSettingsDomain domain
,
724 CFTypeRef trustSettingsDictOrArray
)
730 if(domain
== kSecTrustSettingsDomainSystem
) {
731 return errSecDataNotModifiable
;
737 result
= TrustSettings::CreateTrustSettings(domain
, CREATE_YES
, TRIM_NO
, ts
);
738 if (result
!= errSecSuccess
) {
742 auto_ptr
<TrustSettings
>_(ts
);
744 ts
->setTrustSettings(certRef
, trustSettingsDictOrArray
);
746 tsTrustSettingsChanged();
747 return errSecSuccess
;
752 OSStatus
SecTrustSettingsRemoveTrustSettings(
753 SecCertificateRef cert
,
754 SecTrustSettingsDomain domain
)
760 if(domain
== kSecTrustSettingsDomainSystem
) {
761 return errSecDataNotModifiable
;
767 result
= TrustSettings::CreateTrustSettings(domain
, CREATE_NO
, TRIM_NO
, ts
);
768 if (result
!= errSecSuccess
) {
772 auto_ptr
<TrustSettings
>_(ts
);
774 /* deleteTrustSettings throws if record not found */
775 trustSettingsDbg("SecTrustSettingsRemoveTrustSettings: deleting from domain %d",
777 ts
->deleteTrustSettings(cert
);
779 tsTrustSettingsChanged();
780 return errSecSuccess
;
785 /* get all certs listed in specified domain */
786 OSStatus
SecTrustSettingsCopyCertificates(
787 SecTrustSettingsDomain domain
,
788 CFArrayRef
*certArray
)
792 TS_REQUIRED(certArray
)
797 result
= TrustSettings::CreateTrustSettings(domain
, CREATE_NO
, TRIM_NO
, ts
);
798 if (result
!= errSecSuccess
) {
802 auto_ptr
<TrustSettings
>_(ts
);
804 CFMutableArrayRef outArray
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
807 * Keychains to search: user's search list, System.keychain, system root store,
808 * system intermdiates, as appropriate
810 StorageManager::KeychainList keychains
;
815 case kSecTrustSettingsDomainUser
:
816 /* user search list */
817 globals().storageManager
.getSearchList(keychains
);
818 /* drop thru to next case */
819 case kSecTrustSettingsDomainAdmin
:
820 /* admin certs in system keychain */
821 adminKc
= globals().storageManager
.make(ADMIN_CERT_STORE_PATH
, false);
822 keychains
.push_back(adminKc
);
823 /* system-wide intermediate certs */
824 sysCertKc
= globals().storageManager
.make(SYSTEM_CERT_STORE_PATH
, false);
825 keychains
.push_back(sysCertKc
);
826 /* drop thru to next case */
827 case kSecTrustSettingsDomainSystem
:
828 /* and, for all cases, immutable system root store */
829 sysRootKc
= globals().storageManager
.make(SYSTEM_ROOT_STORE_PATH
, false);
830 keychains
.push_back(sysRootKc
);
832 /* already validated when we created the TrustSettings */
835 ts
->findCerts(keychains
, outArray
);
836 if(CFArrayGetCount(outArray
) == 0) {
838 return errSecNoTrustSettings
;
840 *certArray
= outArray
;
845 * Obtain an external, portable representation of the specified
846 * domain's TrustSettings. Caller must CFRelease the returned data.
848 OSStatus
SecTrustSettingsCreateExternalRepresentation(
849 SecTrustSettingsDomain domain
,
850 CFDataRef
*trustSettings
)
854 TS_REQUIRED(trustSettings
)
859 result
= TrustSettings::CreateTrustSettings(domain
, CREATE_NO
, TRIM_NO
, ts
);
860 if (result
!= errSecSuccess
) {
864 auto_ptr
<TrustSettings
>_(ts
);
866 *trustSettings
= ts
->createExternal();
867 return errSecSuccess
;
873 * Import trust settings, obtained via SecTrustSettingsCreateExternalRepresentation,
874 * into the specified domain.
876 OSStatus
SecTrustSettingsImportExternalRepresentation(
877 SecTrustSettingsDomain domain
,
878 CFDataRef trustSettings
) /* optional - NULL means empty settings */
882 if(domain
== kSecTrustSettingsDomainSystem
) {
883 return errSecDataNotModifiable
;
889 result
= TrustSettings::CreateTrustSettings(domain
, trustSettings
, ts
);
890 if (result
!= errSecSuccess
) {
894 auto_ptr
<TrustSettings
>_(ts
);
897 tsTrustSettingsChanged();
898 return errSecSuccess
;