X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/Security/libsecurity_keychain/lib/SecTrust.cpp?ds=inline diff --git a/Security/libsecurity_keychain/lib/SecTrust.cpp b/Security/libsecurity_keychain/lib/SecTrust.cpp deleted file mode 100644 index 94a58092..00000000 --- a/Security/libsecurity_keychain/lib/SecTrust.cpp +++ /dev/null @@ -1,901 +0,0 @@ -/* - * Copyright (c) 2002-2015 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@ - */ - -#include "SecTrust.h" -#include "SecTrustPriv.h" -#include "Trust.h" -#include -#include "SecBridge.h" -#include "SecInternal.h" -#include "SecInternalP.h" -#include "SecTrustSettings.h" -#include "SecCertificatePriv.h" -#include "SecCertificateP.h" -#include "SecCertificatePrivP.h" -#include -#include -#include - -// forward declarations -CFArrayRef SecTrustCopyDetails(SecTrustRef trust); -static CFDictionaryRef SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust, CFIndex ix); -static void SecTrustCheckException(const void *key, const void *value, void *context); - -typedef struct SecTrustCheckExceptionContext { - CFDictionaryRef exception; - bool exceptionNotFound; -} SecTrustCheckExceptionContext; - -// public trust result constants -CFTypeRef kSecTrustEvaluationDate = CFSTR("TrustEvaluationDate"); -CFTypeRef kSecTrustExtendedValidation = CFSTR("TrustExtendedValidation"); -CFTypeRef kSecTrustOrganizationName = CFSTR("Organization"); -CFTypeRef kSecTrustResultValue = CFSTR("TrustResultValue"); -CFTypeRef kSecTrustRevocationChecked = CFSTR("TrustRevocationChecked"); -CFTypeRef kSecTrustRevocationValidUntilDate = CFSTR("TrustExpirationDate"); -CFTypeRef kSecTrustResultDetails = CFSTR("TrustResultDetails"); - -// -// CF boilerplate -// -CFTypeID SecTrustGetTypeID(void) -{ - BEGIN_SECAPI - - return gTypes().Trust.typeID; - - END_SECAPI1(_kCFRuntimeNotATypeID) -} - - -// -// Sec* API bridge functions -// -OSStatus SecTrustCreateWithCertificates( - CFTypeRef certificates, - CFTypeRef policies, - SecTrustRef *trustRef) -{ - BEGIN_SECAPI - Required(trustRef); - *trustRef = (new Trust(certificates, policies))->handle(); - END_SECAPI -} - -OSStatus -SecTrustSetPolicies(SecTrustRef trustRef, CFTypeRef policies) -{ - BEGIN_SECAPI - Trust::required(trustRef)->policies(policies); - END_SECAPI -} - -OSStatus -SecTrustSetOptions(SecTrustRef trustRef, SecTrustOptionFlags options) -{ - BEGIN_SECAPI - CSSM_APPLE_TP_ACTION_DATA actionData = { - CSSM_APPLE_TP_ACTION_VERSION, - (CSSM_APPLE_TP_ACTION_FLAGS)options - }; - Trust *trust = Trust::required(trustRef); - CFDataRef actionDataRef = CFDataCreate(NULL, - (const UInt8 *)&actionData, - (CFIndex)sizeof(CSSM_APPLE_TP_ACTION_DATA)); - trust->action(CSSM_TP_ACTION_DEFAULT); - trust->actionData(actionDataRef); - if (actionDataRef) CFRelease(actionDataRef); - END_SECAPI -} - -OSStatus SecTrustSetParameters( - SecTrustRef trustRef, - CSSM_TP_ACTION action, - CFDataRef actionData) -{ - BEGIN_SECAPI - Trust *trust = Trust::required(trustRef); - trust->action(action); - trust->actionData(actionData); - END_SECAPI -} - - -OSStatus SecTrustSetAnchorCertificates(SecTrustRef trust, CFArrayRef anchorCertificates) -{ - BEGIN_SECAPI - Trust::required(trust)->anchors(anchorCertificates); - END_SECAPI -} - -OSStatus SecTrustSetAnchorCertificatesOnly(SecTrustRef trust, Boolean anchorCertificatesOnly) -{ - BEGIN_SECAPI - Trust::AnchorPolicy policy = (anchorCertificatesOnly) ? Trust::useAnchorsOnly : Trust::useAnchorsAndBuiltIns; - Trust::required(trust)->anchorPolicy(policy); - END_SECAPI -} - -OSStatus SecTrustSetKeychains(SecTrustRef trust, CFTypeRef keychainOrArray) -{ - BEGIN_SECAPI - StorageManager::KeychainList keychains; - // avoid unnecessary global initializations if an empty array is passed in - if (!( (keychainOrArray != NULL) && - (CFGetTypeID(keychainOrArray) == CFArrayGetTypeID()) && - (CFArrayGetCount((CFArrayRef)keychainOrArray) == 0) )) { - globals().storageManager.optionalSearchList(keychainOrArray, keychains); - } - Trust::required(trust)->searchLibs(keychains); - END_SECAPI -} - - -OSStatus SecTrustSetVerifyDate(SecTrustRef trust, CFDateRef verifyDate) -{ - BEGIN_SECAPI - Trust::required(trust)->time(verifyDate); - END_SECAPI -} - - -CFAbsoluteTime SecTrustGetVerifyTime(SecTrustRef trust) -{ - CFAbsoluteTime verifyTime = 0; - OSStatus __secapiresult = errSecSuccess; - try { - CFRef verifyDate = Trust::required(trust)->time(); - verifyTime = CFDateGetAbsoluteTime(verifyDate); - } - 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 verifyTime; -} - - -OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType *resultP) -{ - SecTrustResultType trustResult = kSecTrustResultInvalid; - CFArrayRef exceptions = NULL; - OSStatus __secapiresult = errSecSuccess; - try { - Trust *trustObj = Trust::required(trust); - trustObj->evaluate(); - trustResult = trustObj->result(); - exceptions = trustObj->exceptions(); - } - 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; } - - if (__secapiresult) { - return __secapiresult; - } - - /* post-process trust result based on exceptions */ - if (trustResult == kSecTrustResultUnspecified) { - /* If leaf is in exceptions -> proceed, otherwise unspecified. */ - if (SecTrustGetExceptionForCertificateAtIndex(trust, 0)) - trustResult = kSecTrustResultProceed; - } - else if (trustResult == kSecTrustResultRecoverableTrustFailure && exceptions) { - /* If we have exceptions get details and match to exceptions. */ - CFArrayRef details = SecTrustCopyDetails(trust); - if (details) { - CFIndex pathLength = CFArrayGetCount(details); - struct SecTrustCheckExceptionContext context = {}; - CFIndex ix; - for (ix = 0; ix < pathLength; ++ix) { - CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix); - // if ((ix == 0) && CFDictionaryContainsKey(detail, kSecPolicyCheckBlackListedLeaf)) - // trustResult = kSecTrustResultFatalTrustFailure; - context.exception = SecTrustGetExceptionForCertificateAtIndex(trust, ix); - CFDictionaryApplyFunction(detail, SecTrustCheckException, &context); - if (context.exceptionNotFound) { - break; - } - } - if (!context.exceptionNotFound) - trustResult = kSecTrustResultProceed; - } - } - - - secdebug("SecTrustEvaluate", "SecTrustEvaluate trust result = %d", (int)trustResult); - if (resultP) { - *resultP = trustResult; - } - return __secapiresult; -} - -OSStatus SecTrustEvaluateAsync(SecTrustRef trust, - dispatch_queue_t queue, SecTrustCallback result) -{ - BEGIN_SECAPI - dispatch_async(queue, ^{ - try { - Trust *trustObj = Trust::required(trust); - trustObj->evaluate(); - SecTrustResultType trustResult = trustObj->result(); - result(trust, trustResult); - } - catch (...) { - result(trust, kSecTrustResultInvalid); - }; - }); - END_SECAPI -} - -// -// Construct the "official" result evidence and return it -// -OSStatus SecTrustGetResult( - SecTrustRef trustRef, - SecTrustResultType *result, - CFArrayRef *certChain, CSSM_TP_APPLE_EVIDENCE_INFO **statusChain) -{ - BEGIN_SECAPI - Trust *trust = Trust::required(trustRef); - if (result) - *result = trust->result(); - if (certChain && statusChain) - trust->buildEvidence(*certChain, TPEvidenceInfo::overlayVar(*statusChain)); - END_SECAPI -} - -// -// Retrieve result of trust evaluation only -// -OSStatus SecTrustGetTrustResult(SecTrustRef trustRef, - SecTrustResultType *result) -{ - BEGIN_SECAPI - Trust *trust = Trust::required(trustRef); - if (result) *result = trust->result(); - END_SECAPI -} - -// -// Retrieve extended validation trust results -// -OSStatus SecTrustCopyExtendedResult(SecTrustRef trust, CFDictionaryRef *result) -{ - BEGIN_SECAPI - Trust *trustObj = Trust::required(trust); - if (result == nil) - return errSecParam; - trustObj->extendedResult(*result); - END_SECAPI -} - -// -// Retrieve CSSM-level information for those who want to dig down -// -OSStatus SecTrustGetCssmResult(SecTrustRef trust, CSSM_TP_VERIFY_CONTEXT_RESULT_PTR *result) -{ - BEGIN_SECAPI - Required(result) = Trust::required(trust)->cssmResult(); - END_SECAPI -} - -// -// Retrieve CSSM_LEVEL TP return code -// -OSStatus SecTrustGetCssmResultCode(SecTrustRef trustRef, OSStatus *result) -{ - BEGIN_SECAPI - Trust *trust = Trust::required(trustRef); - if (trust->result() == kSecTrustResultInvalid) - return errSecParam; - else - Required(result) = trust->cssmResultCode(); - END_SECAPI -} - -OSStatus SecTrustGetTPHandle(SecTrustRef trust, CSSM_TP_HANDLE *handle) -{ - BEGIN_SECAPI - Required(handle) = Trust::required(trust)->getTPHandle(); - END_SECAPI -} - -OSStatus SecTrustCopyPolicies(SecTrustRef trust, CFArrayRef *policies) -{ - BEGIN_SECAPI - CFArrayRef currentPolicies = Trust::required(trust)->policies(); - if (currentPolicies != NULL) - { - CFRetain(currentPolicies); - } - - Required(policies) = currentPolicies; - END_SECAPI -} - -OSStatus SecTrustSetNetworkFetchAllowed(SecTrustRef trust, Boolean allowFetch) -{ - BEGIN_SECAPI - Trust *trustObj = Trust::required(trust); - Trust::NetworkPolicy netPolicy = (allowFetch) ? - Trust::useNetworkEnabled : Trust::useNetworkDisabled; - trustObj->networkPolicy(netPolicy); - END_SECAPI -} - -OSStatus SecTrustGetNetworkFetchAllowed(SecTrustRef trust, Boolean *allowFetch) -{ - BEGIN_SECAPI - Boolean allowed = false; - Trust *trustObj = Trust::required(trust); - Trust::NetworkPolicy netPolicy = trustObj->networkPolicy(); - if (netPolicy == Trust::useNetworkDefault) { - // network fetch is enabled by default for SSL only - allowed = trustObj->policySpecified(trustObj->policies(), CSSMOID_APPLE_TP_SSL); - } else { - // caller has explicitly set the network policy - allowed = (netPolicy == Trust::useNetworkEnabled); - } - Required(allowFetch) = allowed; - END_SECAPI -} - -OSStatus SecTrustSetOCSPResponse(SecTrustRef trust, CFTypeRef responseData) -{ - BEGIN_SECAPI - Trust::required(trust)->responses(responseData); - END_SECAPI -} - -OSStatus SecTrustCopyCustomAnchorCertificates(SecTrustRef trust, CFArrayRef *anchorCertificates) -{ - BEGIN_SECAPI - CFArrayRef customAnchors = Trust::required(trust)->anchors(); - Required(anchorCertificates) = (customAnchors) ? - (const CFArrayRef)CFRetain(customAnchors) : (const CFArrayRef)NULL; - END_SECAPI -} - -// -// Get the user's default anchor certificate set -// -OSStatus SecTrustCopyAnchorCertificates(CFArrayRef *anchorCertificates) -{ - BEGIN_SECAPI - - return SecTrustSettingsCopyUnrestrictedRoots( - true, true, true, /* all domains */ - anchorCertificates); - - END_SECAPI -} - -/* new in 10.6 */ -SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust) -{ - SecKeyRef pubKey = NULL; - CFArrayRef certChain = NULL; - CFArrayRef evidenceChain = NULL; - CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL; - OSStatus __secapiresult = errSecSuccess; - try { - Trust *trustObj = Trust::required(trust); - if (trustObj->result() == kSecTrustResultInvalid) { - // Trust hasn't been evaluated; attempt to retrieve public key from leaf. - SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, 0); - __secapiresult = SecCertificateCopyPublicKey(cert, &pubKey); - if (pubKey) { - return pubKey; - } - // Otherwise, we must evaluate first. - trustObj->evaluate(); - if (trustObj->result() == kSecTrustResultInvalid) { - MacOSError::throwMe(errSecTrustNotAvailable); - } - } - if (trustObj->evidence() == nil) { - trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain)); - } - evidenceChain = trustObj->evidence(); - } - 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; } - - if (certChain) - CFRelease(certChain); - - if (evidenceChain) { - if (CFArrayGetCount(evidenceChain) > 0) { - SecCertificateRef cert = (SecCertificateRef) CFArrayGetValueAtIndex(evidenceChain, 0); - __secapiresult = SecCertificateCopyPublicKey(cert, &pubKey); - } - // do not release evidenceChain, as it is owned by the trust object. - } - return pubKey; -} - -/* new in 10.6 */ -CFIndex SecTrustGetCertificateCount(SecTrustRef trust) -{ - CFIndex chainLen = 0; - CFArrayRef certChain = NULL; - CFArrayRef evidenceChain = NULL; - CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL; - OSStatus __secapiresult = errSecSuccess; - try { - Trust *trustObj = Trust::required(trust); - if (trustObj->result() == kSecTrustResultInvalid) { - trustObj->evaluate(); - if (trustObj->result() == kSecTrustResultInvalid) - MacOSError::throwMe(errSecTrustNotAvailable); - } - if (trustObj->evidence() == nil) - trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain)); - evidenceChain = trustObj->evidence(); - } - 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; } - - if (certChain) - CFRelease(certChain); - - if (evidenceChain) - chainLen = CFArrayGetCount(evidenceChain); // don't release, trust object owns it. - - return chainLen; -} - -/* new in 10.6 */ -SecCertificateRef SecTrustGetCertificateAtIndex(SecTrustRef trust, CFIndex ix) -{ - SecCertificateRef certificate = NULL; - CFArrayRef certChain = NULL; - CFArrayRef evidenceChain = NULL; - CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL; - OSStatus __secapiresult = errSecSuccess; - try { - Trust *trustObj = Trust::required(trust); - if (trustObj->result() == kSecTrustResultInvalid) { - // If caller is asking for the leaf, we can return it without - // having to evaluate the entire chain. Note that we don't retain - // the cert as it's owned by the trust and this is a 'Get' API. - if (ix == 0) { - CFArrayRef certs = trustObj->certificates(); - if (certs && (CFArrayGetCount(certs) > 0)) { - certificate = (SecCertificateRef) CFArrayGetValueAtIndex(certs, 0); - if (certificate) { - return certificate; - } - } - } - // Otherwise, we must evaluate first. - trustObj->evaluate(); - if (trustObj->result() == kSecTrustResultInvalid) { - MacOSError::throwMe(errSecTrustNotAvailable); - } - } - if (trustObj->evidence() == nil) { - trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain)); - } - evidenceChain = trustObj->evidence(); - } - 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; } - - if (certChain) - CFRelease(certChain); - - if (evidenceChain) { - if (ix < CFArrayGetCount(evidenceChain)) { - certificate = (SecCertificateRef) CFArrayGetValueAtIndex(evidenceChain, ix); - // note: we do not retain this certificate. The assumption here is - // that the certificate is retained by the trust object, so it is - // valid unil the trust is released (or until re-evaluated.) - // also note: we do not release the evidenceChain, as it is owned - // by the trust object. - } - } - return certificate; -} - - -static CFStringRef kSecCertificateDetailSHA1Digest = CFSTR("SHA1Digest"); -static CFStringRef kSecCertificateDetailStatusCodes = CFSTR("StatusCodes"); - -static void -_AppendStatusCode(CFMutableArrayRef array, OSStatus statusCode) -{ - if (!array) - return; - SInt32 num = statusCode; - CFNumberRef numRef = CFNumberCreate(NULL, kCFNumberSInt32Type, &num); - if (!numRef) - return; - CFArrayAppendValue(array, numRef); - CFRelease(numRef); -} - -CFArrayRef SecTrustCopyDetails(SecTrustRef trust) -{ - // This function returns an array of dictionaries, one per certificate, - // holding status info for each certificate in the evaluated chain. - // - CFIndex count, chainLen = 0; - CFArrayRef certChain = NULL; - CFMutableArrayRef details = NULL; - CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL; - OSStatus __secapiresult = errSecSuccess; - try { - Trust *trustObj = Trust::required(trust); - if (trustObj->result() == kSecTrustResultInvalid) { - trustObj->evaluate(); - if (trustObj->result() == kSecTrustResultInvalid) - MacOSError::throwMe(errSecTrustNotAvailable); - } - trustObj->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain)); - } - 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; } - - if (certChain) { - chainLen = CFArrayGetCount(certChain); - CFRelease(certChain); - } - if (statusChain) { - details = CFArrayCreateMutable(NULL, chainLen, &kCFTypeArrayCallBacks); - for (count = 0; count < chainLen; count++) { - CFMutableDictionaryRef certDict = CFDictionaryCreateMutable(kCFAllocatorDefault, - 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFMutableArrayRef statusCodes = CFArrayCreateMutable(kCFAllocatorDefault, - 0, &kCFTypeArrayCallBacks); - CSSM_TP_APPLE_EVIDENCE_INFO *evInfo = &statusChain[count]; - CSSM_TP_APPLE_CERT_STATUS statBits = evInfo->StatusBits; - - // translate status bits - if (statBits & CSSM_CERT_STATUS_EXPIRED) - _AppendStatusCode(statusCodes, errSecCertificateExpired); - if (statBits & CSSM_CERT_STATUS_NOT_VALID_YET) - _AppendStatusCode(statusCodes, errSecCertificateNotValidYet); - if (statBits & CSSM_CERT_STATUS_TRUST_SETTINGS_DENY) - _AppendStatusCode(statusCodes, errSecTrustSettingDeny); - - // translate status codes - unsigned int i; - for (i = 0; i < evInfo->NumStatusCodes; i++) { - CSSM_RETURN scode = evInfo->StatusCodes[i]; - _AppendStatusCode(statusCodes, (OSStatus)scode); - } - - CFDictionarySetValue(certDict, kSecCertificateDetailStatusCodes, statusCodes); - CFRelease(statusCodes); - CFArrayAppendValue(details, certDict); - CFRelease(certDict); - } - } - return details; -} - -static CFDictionaryRef SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust, CFIndex ix) -{ - CFArrayRef exceptions = NULL; - OSStatus __secapiresult = errSecSuccess; - try { - exceptions = Trust::required(trust)->exceptions(); - } - 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; } - - if (!exceptions || ix >= CFArrayGetCount(exceptions)) - return NULL; - CFDictionaryRef exception = (CFDictionaryRef)CFArrayGetValueAtIndex(exceptions, ix); - if (CFGetTypeID(exception) != CFDictionaryGetTypeID()) - return NULL; - - SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, ix); - if (!certificate) - return NULL; - - /* If the exception contains the current certificate's sha1Digest in the - kSecCertificateDetailSHA1Digest key then we use it otherwise we ignore it. */ - CFDataRef sha1Digest = SecCertificateGetSHA1Digest(certificate); - CFTypeRef digestValue = CFDictionaryGetValue(exception, kSecCertificateDetailSHA1Digest); - if (!digestValue || !CFEqual(sha1Digest, digestValue)) - exception = NULL; - - return exception; -} - -static void SecTrustCheckException(const void *key, const void *value, void *context) -{ - struct SecTrustCheckExceptionContext *cec = (struct SecTrustCheckExceptionContext *)context; - if (cec->exception) { - CFTypeRef exceptionValue = CFDictionaryGetValue(cec->exception, key); - if (!exceptionValue || !CFEqual(value, exceptionValue)) { - cec->exceptionNotFound = true; - } - } else { - cec->exceptionNotFound = true; - } -} - -/* new in 10.9 */ -CFDataRef SecTrustCopyExceptions(SecTrustRef trust) -{ - CFArrayRef details = SecTrustCopyDetails(trust); - CFIndex pathLength = details ? CFArrayGetCount(details) : 0; - CFMutableArrayRef exceptions = CFArrayCreateMutable(kCFAllocatorDefault, - pathLength, &kCFTypeArrayCallBacks); - CFIndex ix; - for (ix = 0; ix < pathLength; ++ix) { - CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix); - CFIndex detailCount = CFDictionaryGetCount(detail); - CFMutableDictionaryRef exception; - if (ix == 0 || detailCount > 0) { - exception = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, - detailCount + 1, detail); - SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, ix); - CFDataRef digest = SecCertificateGetSHA1Digest(certificate); - if (digest) { - CFDictionaryAddValue(exception, kSecCertificateDetailSHA1Digest, digest); - } - } else { - /* Add empty exception dictionaries for non leaf certs which have no exceptions - * to save space. - */ - exception = (CFMutableDictionaryRef)CFDictionaryCreate(kCFAllocatorDefault, - NULL, NULL, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - } - CFArrayAppendValue(exceptions, exception); - CFReleaseNull(exception); - } - CFReleaseSafe(details); - - /* Remove any trailing empty dictionaries to save even more space (we skip the leaf - since it will never be empty). */ - for (ix = pathLength; ix-- > 1;) { - CFDictionaryRef exception = (CFDictionaryRef)CFArrayGetValueAtIndex(exceptions, ix); - if (CFDictionaryGetCount(exception) == 0) { - CFArrayRemoveValueAtIndex(exceptions, ix); - } else { - break; - } - } - - CFDataRef encodedExceptions = CFPropertyListCreateData(kCFAllocatorDefault, - exceptions, kCFPropertyListBinaryFormat_v1_0, 0, NULL); - CFRelease(exceptions); - - return encodedExceptions; -} - -/* new in 10.9 */ -bool SecTrustSetExceptions(SecTrustRef trust, CFDataRef encodedExceptions) -{ - CFArrayRef exceptions; - exceptions = (CFArrayRef)CFPropertyListCreateWithData(kCFAllocatorDefault, - encodedExceptions, kCFPropertyListImmutable, NULL, NULL); - if (exceptions && CFGetTypeID(exceptions) != CFArrayGetTypeID()) { - CFRelease(exceptions); - exceptions = NULL; - } - - OSStatus __secapiresult = errSecSuccess; - try { - Trust::required(trust)->exceptions(exceptions); - } - 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; } - - /* If there is a valid exception entry for our current leaf we're golden. */ - if (SecTrustGetExceptionForCertificateAtIndex(trust, 0)) - return true; - - /* The passed in exceptions didn't match our current leaf, so we discard it. */ - try { - Trust::required(trust)->exceptions(NULL); - __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 false; -} - -/* new in 10.9 */ -CFDictionaryRef -SecTrustCopyResult(SecTrustRef trust) -{ - CFDictionaryRef result = NULL; - try { - result = Trust::required(trust)->results(); - // merge details into result - CFArrayRef details = SecTrustCopyDetails(trust); - if (details) { - CFDictionarySetValue((CFMutableDictionaryRef)result, - kSecTrustResultDetails, details); - CFRelease(details); - } - } - catch (...) { - if (result) { - CFRelease(result); - result = NULL; - } - } - return result; -} - -/* new in 10.7 */ -CFArrayRef -SecTrustCopyProperties(SecTrustRef trust) -{ - /* can't use SECAPI macros, since this function does not return OSStatus */ - CFArrayRef result = NULL; - try { - result = Trust::required(trust)->properties(); - } - catch (...) { - if (result) { - CFRelease(result); - result = NULL; - } - } - return result; -} - - -/* deprecated in 10.5 */ -OSStatus SecTrustGetCSSMAnchorCertificates(const CSSM_DATA **cssmAnchors, - uint32 *cssmAnchorCount) -{ - BEGIN_SECAPI - CertGroup certs; - Trust::gStore().getCssmRootCertificates(certs); - Required(cssmAnchors) = certs.blobCerts(); - Required(cssmAnchorCount) = certs.count(); - END_SECAPI -} - - -// -// Get and set user trust settings. Deprecated in 10.5. -// User Trust getter, deprecated, works as it always has. -// -OSStatus SecTrustGetUserTrust(SecCertificateRef certificate, - SecPolicyRef policy, SecTrustUserSetting *trustSetting) -{ - BEGIN_SECAPI - StorageManager::KeychainList searchList; - globals().storageManager.getSearchList(searchList); - Required(trustSetting) = Trust::gStore().find( - Certificate::required(certificate), - Policy::required(policy), - searchList); - END_SECAPI -} - -// -// The public setter, also deprecated; it maps to the appropriate -// Trust Settings call if possible, else throws errSecUnimplemented. -// -OSStatus SecTrustSetUserTrust(SecCertificateRef certificate, - SecPolicyRef policy, SecTrustUserSetting trustSetting) -{ - SecTrustSettingsResult tsResult = kSecTrustSettingsResultInvalid; - OSStatus ortn; - Boolean isRoot; - - Policy::required(policy); - switch(trustSetting) { - case kSecTrustResultProceed: - /* different SecTrustSettingsResult depending in root-ness */ - ortn = SecCertificateIsSelfSigned(certificate, &isRoot); - if(ortn) { - return ortn; - } - if(isRoot) { - tsResult = kSecTrustSettingsResultTrustRoot; - } - else { - tsResult = kSecTrustSettingsResultTrustAsRoot; - } - break; - case kSecTrustResultDeny: - tsResult = kSecTrustSettingsResultDeny; - break; - default: - return errSecUnimplemented; - } - - /* make a usage constraints dictionary */ - CFRef usageDict(CFDictionaryCreateMutable(NULL, - 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); - CFDictionaryAddValue(usageDict, kSecTrustSettingsPolicy, policy); - if(tsResult != kSecTrustSettingsResultTrustRoot) { - /* skip if we're specifying the default */ - SInt32 result = tsResult; - CFNumberRef cfNum = CFNumberCreate(NULL, kCFNumberSInt32Type, &result); - CFDictionarySetValue(usageDict, kSecTrustSettingsResult, cfNum); - CFRelease(cfNum); - } - return SecTrustSettingsSetTrustSettings(certificate, kSecTrustSettingsDomainUser, - usageDict); -} - -// -// This one is the now-private version of what SecTrustSetUserTrust() used to -// be. The public API can no longer manipulate User Trust settings, only -// view them. -// -OSStatus SecTrustSetUserTrustLegacy(SecCertificateRef certificate, - SecPolicyRef policy, SecTrustUserSetting trustSetting) -{ - BEGIN_SECAPI - switch (trustSetting) { - case kSecTrustResultProceed: - case kSecTrustResultConfirm: - case kSecTrustResultDeny: - case kSecTrustResultUnspecified: - break; - default: - MacOSError::throwMe(errSecInvalidTrustSetting); - } - Trust::gStore().assign( - Certificate::required(certificate), - Policy::required(policy), - trustSetting); - END_SECAPI -} - -/* SecGetAppleTPHandle - @@@NOT EXPORTED YET; copied from SecurityInterface, - but could be useful in the future. -*/ -/* -CSSM_TP_HANDLE -SecGetAppleTPHandle() -{ - BEGIN_SECAPI - return TP(gGuidAppleX509TP)->handle(); - END_SECAPI1(NULL); -} -*/ - -