X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/Security/libsecurity_keychain/lib/SecTrustSettings.cpp?ds=inline diff --git a/Security/libsecurity_keychain/lib/SecTrustSettings.cpp b/Security/libsecurity_keychain/lib/SecTrustSettings.cpp deleted file mode 100644 index ed7485ad..00000000 --- a/Security/libsecurity_keychain/lib/SecTrustSettings.cpp +++ /dev/null @@ -1,902 +0,0 @@ -/* - * Copyright (c) 2005,2011-2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * SecTrustSettings.cpp - Public interface for manipulation of Trust Settings. - * - */ - -#include "SecBridge.h" -#include "SecTrustSettings.h" -#include "SecTrustSettingsPriv.h" -#include "TrustSettingsUtils.h" -#include "TrustSettings.h" -#include "TrustSettingsSchema.h" -#include "TrustKeychains.h" -#include "Trust.h" -#include "SecKeychainPriv.h" -#include "Globals.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define trustSettingsDbg(args...) secdebug("trustSettings", ## args) - -/* - * Ideally we'd like to implement our own lock to protect the state of the cert stores - * without grabbing the global Sec API lock, but we deal with SecCFObjects, so we'll have - * to bite the bullet and grab the big lock. We also have our own lock protecting the - * global trust settings cache which is also used by the keychain callback function - * (which does not grab the Sec API lock). - */ - -#define BEGIN_RCSAPI \ - OSStatus __secapiresult; \ - try { -#define END_RCSAPI \ - __secapiresult=errSecSuccess; \ - } \ - catch (const MacOSError &err) { __secapiresult=err.osStatus(); } \ - catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } \ - catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } \ - catch (...) { __secapiresult=errSecInternalComponent; } \ - return __secapiresult; - -#define END_RCSAPI0 \ - catch (...) {} \ - return; - - -#pragma mark --- TrustSettings preferences --- - -/* - * If Colonel Klink wants to disable user-level Trust Settings, he'll have - * to restart the apps which will be affected after he does so. We are not - * going to consult system prefs every time we do a cert evaluation. We - * consult it once per process and cache the results here. - */ -static bool tsUserTrustDisableValid = false; /* true once we consult prefs */ -static bool tsUserTrustDisable = false; /* the cached value */ - -/* - * Determine whether user-level Trust Settings disabled. - */ -static bool tsUserTrustSettingsDisabled() -{ - if(tsUserTrustDisableValid) { - return tsUserTrustDisable; - } - tsUserTrustDisable = false; - - Dictionary* dictionary = Dictionary::CreateDictionary(kSecTrustSettingsPrefsDomain, Dictionary::US_System); - if (dictionary) - { - auto_ptr prefsDict(dictionary); - /* this returns false if the pref isn't there, just like we want */ - tsUserTrustDisable = prefsDict->getBoolValue(kSecTrustSettingsDisableUserTrustSettings); - } - - tsUserTrustDisableValid = true; - return tsUserTrustDisable; -} - -#pragma mark --- TrustSettings global cache --- - -/*** - *** cache submodule - keeps per-app copy of zero or one TrustSettings - *** for each domain. Used only by SecTrustSettingsEvaluateCert() - *** and SecTrustSettingsCopyQualifiedCerts(); results of - *** manipulation by public API functions are not cached. - ***/ - -/* - * API/client code has to hold this lock when doing anything with any of - * the TrustSettings maintained here. - * It's recursive to accomodate CodeSigning's need to do cert verification - * (while we evaluate app equivalence). - */ -static ModuleNexus sutCacheLock; - -#define TRUST_SETTINGS_NUM_DOMAINS 3 - -/* - * The three global TrustSettings. - * We rely on the fact the the domain enums start with 0; we use - * the domain value as an index into the following two arrays. - */ -static TrustSettings *globalTrustSettings[TRUST_SETTINGS_NUM_DOMAINS] = - {NULL, NULL, NULL}; - -/* - * Indicates "the associated global here is currently valid; if there isn't a - * globalTrustSettings[domain], don't try to find one" - */ -static bool globalTrustSettingsValid[TRUST_SETTINGS_NUM_DOMAINS] = - {false, false, false}; - -/* remember the fact that we've registered our KC callback */ -static bool sutRegisteredCallback = false; - -static void tsRegisterCallback(); - -/* - * Assign global TrustSetting to new incoming value, which may be NULL. - * Caller holds sutCacheLock. - */ -static void tsSetGlobalTrustSettings( - TrustSettings *ts, - SecTrustSettingsDomain domain) -{ - assert(((int)domain >= 0) && ((int)domain < TRUST_SETTINGS_NUM_DOMAINS)); - - trustSettingsDbg("tsSetGlobalTrustSettings domain %d: caching TS %p old TS %p", - (int)domain, ts, globalTrustSettings[domain]); - delete globalTrustSettings[domain]; - globalTrustSettings[domain] = ts; - globalTrustSettingsValid[domain] = ts ? true : false; - tsRegisterCallback(); -} - -/* - * Obtain global TrustSettings for specified domain if it exists. - * Returns NULL if there is simply no TS for that domain. - * The TS, if returned, belongs to this cache module. - * Caller holds sutCacheLock. - */ -static TrustSettings *tsGetGlobalTrustSettings( - SecTrustSettingsDomain domain) -{ - assert(((int)domain >= 0) && ((int)domain < TRUST_SETTINGS_NUM_DOMAINS)); - - if((domain == kSecTrustSettingsDomainUser) && tsUserTrustSettingsDisabled()) { - trustSettingsDbg("tsGetGlobalTrustSettings: skipping DISABLED user domain"); - return NULL; - } - - if(globalTrustSettingsValid[domain]) { - // ready or not, use this - return globalTrustSettings[domain]; - } - assert(globalTrustSettings[domain] == NULL); - - /* try to find one */ - OSStatus result = errSecSuccess; - TrustSettings *ts = NULL; - /* don't create; trim if found */ - result = TrustSettings::CreateTrustSettings(domain, CREATE_NO, TRIM_YES, ts); - if ( (domain != kSecTrustSettingsDomainSystem) - && (result == errSecInternalComponent)) { - /* - * Could not connect to ocspd to get the user/admin domain trust settings - * This happens in single user mode for example. - * Valid flag is set to false and continue. - */ - trustSettingsDbg("tsGetGlobalTrustSettings: could not connect to ocspd for domain (%d)",(int)domain); - globalTrustSettingsValid[domain] = false; - tsRegisterCallback(); - return NULL; - } - else if (result == errSecNoTrustSettings) { - /* - * No TrustSettings for this domain, actually a fairly common case. - * Optimize: don't bother trying this again. - */ - trustSettingsDbg("tsGetGlobalTrustSettings: flagging known NULL"); - globalTrustSettingsValid[domain] = true; - tsRegisterCallback(); - return NULL; - } - else if(result != errSecSuccess) { - /* gross error */ - MacOSError::throwMe(result); - } - - tsSetGlobalTrustSettings(ts, domain); - return ts; -} - -/* - * Purge TrustSettings cache. - * Called by Keychain Event callback and by our API functions that - * modify trust settings. - * Caller can NOT hold sutCacheLock. - */ -static void tsPurgeCache() -{ - int domain; - - StLock _(sutCacheLock()); - trustSettingsDbg("tsPurgeCache"); - for(domain=0; domainpid == getpid()) { - /* - * Avoid dup cache invalidates: we already dealt with this event. - */ - trustSettingsDbg("cacheEventCallback: our pid, skipping"); - } - else { - tsPurgeCache(); - } - return errSecSuccess; -} - -/* - * Ensure that we've registered for kSecTrustSettingsChangedEvent callbacks - */ -static void tsRegisterCallback() -{ - if(sutRegisteredCallback) { - return; - } - trustSettingsDbg("tsRegisterCallback: registering callback"); - OSStatus ortn = SecKeychainAddCallback(tsTrustSettingsCallback, - kSecTrustSettingsChangedEventMask, NULL); - if(ortn) { - trustSettingsDbg("tsRegisterCallback: SecKeychainAddCallback returned %d", (int)ortn); - /* Not sure how this could ever happen - maybe if there is no run loop active? */ - } - sutRegisteredCallback = true; -} - -#pragma mark --- Static functions --- - - -/* - * Called by API code when a trust list has changed; we notify other processes - * and purge our own cache. - */ -static void tsTrustSettingsChanged() -{ - tsPurgeCache(); - - /* The only interesting data is our pid */ - NameValueDictionary nvd; - pid_t ourPid = getpid(); - nvd.Insert (new NameValuePair (PID_KEY, - CssmData (reinterpret_cast(&ourPid), sizeof (pid_t)))); - CssmData data; - nvd.Export (data); - - trustSettingsDbg("tsTrustSettingsChanged: posting notification"); - SecurityServer::ClientSession cs (Allocator::standard(), Allocator::standard()); - cs.postNotification (SecurityServer::kNotificationDomainDatabase, - kSecTrustSettingsChangedEvent, data); - free (data.data ()); -} - -/* - * Common code for SecTrustSettingsCopyTrustSettings(), - * SecTrustSettingsCopyModificationDate(). - */ -static OSStatus tsCopyTrustSettings( - SecCertificateRef cert, - SecTrustSettingsDomain domain, - CFArrayRef *trustSettings, /* optionally RETURNED */ - CFDateRef *modDate) /* optionally RETURNED */ -{ - BEGIN_RCSAPI - - TS_REQUIRED(cert) - - /* obtain fresh full copy from disk */ - OSStatus result; - TrustSettings* ts; - - result = TrustSettings::CreateTrustSettings(domain, CREATE_NO, TRIM_NO, ts); - - // rather than throw these results, just return them because we are at the top level - if (result == errSecNoTrustSettings) { - return errSecItemNotFound; - } - else if (result != errSecSuccess) { - return result; - } - - auto_ptr_(ts); // make sure this gets deleted just in case something throws underneath - - if(trustSettings) { - *trustSettings = ts->copyTrustSettings(cert); - } - if(modDate) { - *modDate = ts->copyModDate(cert); - } - - END_RCSAPI -} - -/* - * Common code for SecTrustSettingsCopyQualifiedCerts() and - * SecTrustSettingsCopyUnrestrictedRoots(). - */ -static OSStatus tsCopyCertsCommon( - /* usage constraints, all optional */ - const CSSM_OID *policyOID, - const char *policyString, - SecTrustSettingsKeyUsage keyUsage, - /* constrain to only roots */ - bool onlyRoots, - /* per-domain enables */ - bool user, - bool admin, - bool system, - CFArrayRef *certArray) /* RETURNED */ -{ - StLock _TC(sutCacheLock()); - StLock _TK(SecTrustKeychainsGetMutex()); - - TS_REQUIRED(certArray) - - /* this relies on the domain enums being numbered 0..2, user..system */ - bool domainEnable[3] = {user, admin, system}; - - /* we'll retain it again before successful exit */ - CFRef outArray(CFArrayCreateMutable(NULL, 0, - &kCFTypeArrayCallBacks)); - - /* - * Search all keychains - user's, System.keychain, system root store, - * system intermdiates as appropriate - */ - StorageManager::KeychainList keychains; - Keychain adminKc; - if(user) { - globals().storageManager.getSearchList(keychains); - } - if(user || admin) { - adminKc = globals().storageManager.make(ADMIN_CERT_STORE_PATH, false); - keychains.push_back(adminKc); - } - Keychain sysRootKc = globals().storageManager.make(SYSTEM_ROOT_STORE_PATH, false); - keychains.push_back(sysRootKc); - Keychain sysCertKc = globals().storageManager.make(SYSTEM_CERT_STORE_PATH, false); - keychains.push_back(sysCertKc); - - assert(kSecTrustSettingsDomainUser == 0); - for(unsigned domain=0; domainfindQualifiedCerts(keychains, - false, /* !findAll */ - onlyRoots, - policyOID, policyString, keyUsage, - outArray); - } - *certArray = outArray; - CFRetain(*certArray); - trustSettingsDbg("tsCopyCertsCommon: %ld certs found", - CFArrayGetCount(outArray)); - return errSecSuccess; -} - -#pragma mark --- SPI functions --- - - -/* - * Fundamental routine used by TP to ascertain status of one cert. - * - * Returns true in *foundMatchingEntry if a trust setting matching - * specific constraints was found for the cert. Returns true in - * *foundAnyEntry if any entry was found for the cert, even if it - * did not match the specified constraints. The TP uses this to - * optimize for the case where a cert is being evaluated for - * one type of usage, and then later for another type. If - * foundAnyEntry is false, the second evaluation need not occur. - * - * Returns the domain in which a setting was found in *foundDomain. - * - * Allowed errors applying to the specified cert evaluation - * are returned in a mallocd array in *allowedErrors and must - * be freed by caller. - * - * The design of the entire TrustSettings module is centered around - * optimizing the performance of this routine (security concerns - * aside, that is). It's why the per-cert dictionaries are stored - * as a dictionary, keyed off of the cert hash. It's why TrustSettings - * are cached in memory by tsGetGlobalTrustSettings(), and why those - * cached TrustSettings objects are 'trimmed' of dictionary fields - * which are not needed to verify a cert. - * - * The API functions which are used to manipulate Trust Settings - * are called infrequently and need not be particularly fast since - * they result in user interaction for authentication. Thus they do - * not use cached TrustSettings as this function does. - */ -OSStatus SecTrustSettingsEvaluateCert( - CFStringRef certHashStr, - /* parameters describing the current cert evalaution */ - const CSSM_OID *policyOID, - const char *policyString, /* optional */ - uint32 policyStringLen, - SecTrustSettingsKeyUsage keyUsage, /* optional */ - bool isRootCert, /* for checking default setting */ - /* RETURNED values */ - SecTrustSettingsDomain *foundDomain, - CSSM_RETURN **allowedErrors, /* mallocd */ - uint32 *numAllowedErrors, - SecTrustSettingsResult *resultType, - bool *foundMatchingEntry, - bool *foundAnyEntry) -{ - BEGIN_RCSAPI - - StLock _(sutCacheLock()); - - TS_REQUIRED(certHashStr) - TS_REQUIRED(foundDomain) - TS_REQUIRED(allowedErrors) - TS_REQUIRED(numAllowedErrors) - TS_REQUIRED(resultType) - TS_REQUIRED(foundMatchingEntry) - TS_REQUIRED(foundAnyEntry) - - /* ensure a NULL_terminated string */ - auto_array polStr; - if(policyString != NULL && policyStringLen > 0) { - polStr.allocate(policyStringLen + 1); - memmove(polStr.get(), policyString, policyStringLen); - if(policyString[policyStringLen - 1] != '\0') { - (polStr.get())[policyStringLen] = '\0'; - } - } - - /* initial condition - this can grow if we inspect multiple TrustSettings */ - *allowedErrors = NULL; - *numAllowedErrors = 0; - - /* - * This loop relies on the ordering of the SecTrustSettingsDomain enum: - * search user first, then admin, then system. - */ - assert(kSecTrustSettingsDomainAdmin == (kSecTrustSettingsDomainUser + 1)); - assert(kSecTrustSettingsDomainSystem == (kSecTrustSettingsDomainAdmin + 1)); - bool foundAny = false; - for(unsigned domain=kSecTrustSettingsDomainUser; - domain<=kSecTrustSettingsDomainSystem; - domain++) { - TrustSettings *ts = tsGetGlobalTrustSettings(domain); - if(ts == NULL) { - continue; - } - - /* validate cert returns true if matching entry was found */ - bool foundAnyHere = false; - bool found = ts->evaluateCert(certHashStr, policyOID, - polStr.get(), keyUsage, isRootCert, - allowedErrors, numAllowedErrors, resultType, &foundAnyHere); - - if(found) { - /* - * Note this, even though we may overwrite it later if this - * is an Unspecified entry and we find a definitive entry - * later - */ - *foundDomain = domain; - } - if(found && (*resultType != kSecTrustSettingsResultUnspecified)) { - trustSettingsDbg("SecTrustSettingsEvaluateCert: found in domain %d", domain); - *foundAnyEntry = true; - *foundMatchingEntry = true; - return errSecSuccess; - } - foundAny |= foundAnyHere; - } - trustSettingsDbg("SecTrustSettingsEvaluateCert: NOT FOUND"); - *foundAnyEntry = foundAny; - *foundMatchingEntry = false; - return errSecSuccess; - END_RCSAPI -} - -/* - * Obtain trusted certs which match specified usage. - * Only certs with a SecTrustSettingsResult of - * kSecTrustSettingsResultTrustRoot or - * or kSecTrustSettingsResultTrustAsRoot will be returned. - * To be used by SecureTransport for its SSLSetTrustedRoots() call; - * I hope nothing else has to use this... - * Caller must CFRelease the returned CFArrayRef. - */ -OSStatus SecTrustSettingsCopyQualifiedCerts( - const CSSM_OID *policyOID, - const char *policyString, /* optional */ - uint32 policyStringLen, - SecTrustSettingsKeyUsage keyUsage, /* optional */ - CFArrayRef *certArray) /* RETURNED */ -{ - BEGIN_RCSAPI - - /* ensure a NULL_terminated string */ - auto_array polStr; - if(policyString != NULL) { - polStr.allocate(policyStringLen + 1); - memmove(polStr.get(), policyString, policyStringLen); - if(policyString[policyStringLen - 1] != '\0') { - (polStr.get())[policyStringLen] = '\0'; - } - } - - return tsCopyCertsCommon(policyOID, polStr.get(), keyUsage, - false, /* !onlyRoots */ - true, true, true, /* all domains */ - certArray); - - END_RCSAPI -} - -/* - * Obtain unrestricted root certs fromt eh specified domain(s). - * Only returns roots with no usage constraints. - * Caller must CFRelease the returned CFArrayRef. - */ -OSStatus SecTrustSettingsCopyUnrestrictedRoots( - Boolean user, - Boolean admin, - Boolean system, - CFArrayRef *certArray) /* RETURNED */ -{ - BEGIN_RCSAPI - - return tsCopyCertsCommon(NULL, NULL, NULL, /* no constraints */ - true, /* onlyRoots */ - user, admin, system, - certArray); - - END_RCSAPI -} - -static const char hexChars[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' -}; - -/* - * Obtain a string representing a cert's SHA1 digest. This string is - * the key used to look up per-cert trust settings in a TrustSettings record. - */ -CFStringRef SecTrustSettingsCertHashStrFromCert( - SecCertificateRef certRef) -{ - if(certRef == NULL) { - return NULL; - } - - if(certRef == kSecTrustSettingsDefaultRootCertSetting) { - /* use this string instead of the cert hash as the dictionary key */ - trustSettingsDbg("SecTrustSettingsCertHashStrFromCert: DefaultSetting"); - return kSecTrustRecordDefaultRootCert; - } - - CSSM_DATA certData; - OSStatus ortn = SecCertificateGetData(certRef, &certData); - if(ortn) { - return NULL; - } - return SecTrustSettingsCertHashStrFromData(certData.Data, certData.Length); -} - -CFStringRef SecTrustSettingsCertHashStrFromData( - const void *cert, - size_t certLen) -{ - unsigned char digest[CC_SHA1_DIGEST_LENGTH]; - char asciiDigest[(2 * CC_SHA1_DIGEST_LENGTH) + 1]; - unsigned dex; - char *outp = asciiDigest; - unsigned char *inp = digest; - - if(cert == NULL) { - return NULL; - } - - CC_SHA1(cert, (CC_LONG)certLen, digest); - - for(dex=0; dex>= 4; - outp[0] = hexChars[c]; - outp += 2; - } - *outp = 0; - return CFStringCreateWithCString(NULL, asciiDigest, kCFStringEncodingASCII); -} - -/* - * Add a cert's TrustSettings to a non-persistent TrustSettings record. - * No locking or cache flushing here; it's all local to the TrustSettings - * we construct here. - */ -OSStatus SecTrustSettingsSetTrustSettingsExternal( - CFDataRef settingsIn, /* optional */ - SecCertificateRef certRef, /* optional */ - CFTypeRef trustSettingsDictOrArray, /* optional */ - CFDataRef *settingsOut) /* RETURNED */ -{ - BEGIN_RCSAPI - - TS_REQUIRED(settingsOut) - - OSStatus result; - TrustSettings* ts; - - result = TrustSettings::CreateTrustSettings(kSecTrustSettingsDomainMemory, settingsIn, ts); - if (result != errSecSuccess) { - return result; - } - - auto_ptr_(ts); - - if(certRef != NULL) { - ts->setTrustSettings(certRef, trustSettingsDictOrArray); - } - *settingsOut = ts->createExternal(); - return errSecSuccess; - - END_RCSAPI -} - -#pragma mark --- API functions --- - -OSStatus SecTrustSettingsCopyTrustSettings( - SecCertificateRef certRef, - SecTrustSettingsDomain domain, - CFArrayRef *trustSettings) /* RETURNED */ -{ - TS_REQUIRED(trustSettings) - - OSStatus result = tsCopyTrustSettings(certRef, domain, trustSettings, NULL); - if (result == errSecSuccess && *trustSettings == NULL) { - result = errSecItemNotFound; /* documented result if no trust settings exist */ - } - return result; -} - -OSStatus SecTrustSettingsCopyModificationDate( - SecCertificateRef certRef, - SecTrustSettingsDomain domain, - CFDateRef *modificationDate) /* RETURNED */ -{ - TS_REQUIRED(modificationDate) - - OSStatus result = tsCopyTrustSettings(certRef, domain, NULL, modificationDate); - if (result == errSecSuccess && *modificationDate == NULL) { - result = errSecItemNotFound; /* documented result if no trust settings exist */ - } - return result; -} - -/* works with existing and with new cert */ -OSStatus SecTrustSettingsSetTrustSettings( - SecCertificateRef certRef, - SecTrustSettingsDomain domain, - CFTypeRef trustSettingsDictOrArray) -{ - BEGIN_RCSAPI - - TS_REQUIRED(certRef) - - if(domain == kSecTrustSettingsDomainSystem) { - return errSecDataNotModifiable; - } - - OSStatus result; - TrustSettings* ts; - - result = TrustSettings::CreateTrustSettings(domain, CREATE_YES, TRIM_NO, ts); - if (result != errSecSuccess) { - return result; - } - - auto_ptr_(ts); - - ts->setTrustSettings(certRef, trustSettingsDictOrArray); - ts->flushToDisk(); - tsTrustSettingsChanged(); - return errSecSuccess; - - END_RCSAPI -} - -OSStatus SecTrustSettingsRemoveTrustSettings( - SecCertificateRef cert, - SecTrustSettingsDomain domain) -{ - BEGIN_RCSAPI - - TS_REQUIRED(cert) - - if(domain == kSecTrustSettingsDomainSystem) { - return errSecDataNotModifiable; - } - - OSStatus result; - TrustSettings* ts; - - result = TrustSettings::CreateTrustSettings(domain, CREATE_NO, TRIM_NO, ts); - if (result != errSecSuccess) { - return result; - } - - auto_ptr_(ts); - - /* deleteTrustSettings throws if record not found */ - trustSettingsDbg("SecTrustSettingsRemoveTrustSettings: deleting from domain %d", - (int)domain); - ts->deleteTrustSettings(cert); - ts->flushToDisk(); - tsTrustSettingsChanged(); - return errSecSuccess; - - END_RCSAPI -} - -/* get all certs listed in specified domain */ -OSStatus SecTrustSettingsCopyCertificates( - SecTrustSettingsDomain domain, - CFArrayRef *certArray) -{ - BEGIN_RCSAPI - - TS_REQUIRED(certArray) - - OSStatus result; - TrustSettings* ts; - - result = TrustSettings::CreateTrustSettings(domain, CREATE_NO, TRIM_NO, ts); - if (result != errSecSuccess) { - return result; - } - - auto_ptr_(ts); - - CFMutableArrayRef outArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - - /* - * Keychains to search: user's search list, System.keychain, system root store, - * system intermdiates, as appropriate - */ - StorageManager::KeychainList keychains; - Keychain adminKc; - Keychain sysCertKc; - Keychain sysRootKc; - switch(domain) { - case kSecTrustSettingsDomainUser: - /* user search list */ - globals().storageManager.getSearchList(keychains); - /* drop thru to next case */ - case kSecTrustSettingsDomainAdmin: - /* admin certs in system keychain */ - adminKc = globals().storageManager.make(ADMIN_CERT_STORE_PATH, false); - keychains.push_back(adminKc); - /* system-wide intermediate certs */ - sysCertKc = globals().storageManager.make(SYSTEM_CERT_STORE_PATH, false); - keychains.push_back(sysCertKc); - /* drop thru to next case */ - case kSecTrustSettingsDomainSystem: - /* and, for all cases, immutable system root store */ - sysRootKc = globals().storageManager.make(SYSTEM_ROOT_STORE_PATH, false); - keychains.push_back(sysRootKc); - default: - /* already validated when we created the TrustSettings */ - break; - } - ts->findCerts(keychains, outArray); - if(CFArrayGetCount(outArray) == 0) { - CFRelease(outArray); - return errSecNoTrustSettings; - } - *certArray = outArray; - END_RCSAPI -} - -/* - * Obtain an external, portable representation of the specified - * domain's TrustSettings. Caller must CFRelease the returned data. - */ -OSStatus SecTrustSettingsCreateExternalRepresentation( - SecTrustSettingsDomain domain, - CFDataRef *trustSettings) -{ - BEGIN_RCSAPI - - TS_REQUIRED(trustSettings) - - OSStatus result; - TrustSettings* ts; - - result = TrustSettings::CreateTrustSettings(domain, CREATE_NO, TRIM_NO, ts); - if (result != errSecSuccess) { - return result; - } - - auto_ptr_(ts); - - *trustSettings = ts->createExternal(); - return errSecSuccess; - - END_RCSAPI -} - -/* - * Import trust settings, obtained via SecTrustSettingsCreateExternalRepresentation, - * into the specified domain. - */ -OSStatus SecTrustSettingsImportExternalRepresentation( - SecTrustSettingsDomain domain, - CFDataRef trustSettings) /* optional - NULL means empty settings */ -{ - BEGIN_RCSAPI - - if(domain == kSecTrustSettingsDomainSystem) { - return errSecDataNotModifiable; - } - - OSStatus result; - TrustSettings* ts; - - result = TrustSettings::CreateTrustSettings(domain, trustSettings, ts); - if (result != errSecSuccess) { - return result; - } - - auto_ptr_(ts); - - ts->flushToDisk(); - tsTrustSettingsChanged(); - return errSecSuccess; - - END_RCSAPI -} -