/* Test basic add delete update copy matching stuff. */ static void tests(void) { SecTrustRef trust; SecCertificateRef cert0, cert1; isnt(cert0 = SecCertificateCreateWithBytes(NULL, _c0, sizeof(_c0)), NULL, "create cert0"); isnt(cert1 = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)), NULL, "create cert1"); const void *v_certs[] = { cert0, cert1 }; SecPolicyRef policy = SecPolicyCreateSSL(false, CFSTR("store.apple.com")); CFArrayRef certs = CFArrayCreate(NULL, v_certs, array_size(v_certs), NULL); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust"); /* Jan 1st 2006. */ CFDateRef date = CFDateCreate(NULL, 157680000.0); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); SecTrustResultType trustResult; ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); CFDataRef exceptions; ok(exceptions = SecTrustCopyExceptions(trust), "create an exceptions"); ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); CFReleaseSafe(trust); CFReleaseSafe(policy); policy = SecPolicyCreateSSL(false, CFSTR("badstore.apple.com")); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust with hostname mismatch"); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); ok(SecTrustSetExceptions(trust, exceptions), "set old exceptions"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); CFReleaseSafe(exceptions); ok(exceptions = SecTrustCopyExceptions(trust), "create a new exceptions"); ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); CFReleaseSafe(trust); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust"); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); CFArrayRef anchors = CFArrayCreate(kCFAllocatorDefault, NULL, 0, &kCFTypeArrayCallBacks); ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set empty anchor list"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); ok_status(SecTrustSetAnchorCertificatesOnly(trust, false), "trust passed in anchors and system anchors"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultProceed, "trust is now kSecTrustResultProceed"); ok_status(SecTrustSetAnchorCertificatesOnly(trust, true), "only trust passed in anchors (default)"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure again"); CFReleaseSafe(exceptions); ok(exceptions = SecTrustCopyExceptions(trust), "create a new exceptions"); ok(SecTrustSetExceptions(trust, exceptions), "set exceptions"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultProceed, "trust is kSecTrustResultProceed"); CFReleaseSafe(date); date = CFDateCreate(NULL, 667680000.0); ok_status(SecTrustSetVerifyDate(trust, date), "set date to far future so certs are expired"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); CFReleaseSafe(anchors); CFReleaseSafe(exceptions); CFReleaseSafe(trust); CFReleaseSafe(policy); CFReleaseSafe(certs); CFReleaseSafe(cert0); CFReleaseSafe(cert1); CFReleaseSafe(date); }
/* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ OSStatus SecTrustSetOptions(SecTrustRef trustRef, SecTrustOptionFlags options) { /* bridge to support API functionality for legacy callers */ OSStatus status = errSecSuccess; CFDataRef encodedExceptions = SecTrustCopyExceptions(trustRef); CFArrayRef exceptions = NULL, oldExceptions = SecTrustGetTrustExceptionsArray(trustRef); if (encodedExceptions) { exceptions = (CFArrayRef)CFPropertyListCreateWithData(kCFAllocatorDefault, encodedExceptions, kCFPropertyListImmutable, NULL, NULL); CFRelease(encodedExceptions); encodedExceptions = NULL; } if (exceptions && CFGetTypeID(exceptions) != CFArrayGetTypeID()) { CFRelease(exceptions); exceptions = NULL; } if (oldExceptions && exceptions && CFArrayGetCount(oldExceptions) > CFArrayGetCount(exceptions)) { oldExceptions = NULL; } /* verify both exceptions are for the same leaf */ if (oldExceptions && exceptions && CFArrayGetCount(oldExceptions) > 0) { CFDictionaryRef oldLeafExceptions = (CFDictionaryRef)CFArrayGetValueAtIndex(oldExceptions, 0); CFDictionaryRef leafExceptions = (CFDictionaryRef)CFArrayGetValueAtIndex(exceptions, 0); CFDataRef oldDigest = (CFDataRef)CFDictionaryGetValue(oldLeafExceptions, CFSTR("SHA1Digest")); CFDataRef digest = (CFDataRef)CFDictionaryGetValue(leafExceptions, CFSTR("SHA1Digest")); if (!oldDigest || !digest || !CFEqual(oldDigest, digest)) { oldExceptions = NULL; } } /* add only those exceptions which are allowed by the supplied options */ if (exceptions) { CFMutableArrayRef filteredExceptions = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); CFIndex i, exceptionCount = (filteredExceptions) ? CFArrayGetCount(exceptions) : 0; for (i = 0; i < exceptionCount; ++i) { CFDictionaryRef exception = (CFDictionaryRef)CFArrayGetValueAtIndex(exceptions, i); CFDictionaryRef oldException = NULL; if (oldExceptions && i < CFArrayGetCount(oldExceptions)) { oldException = (CFDictionaryRef)CFArrayGetValueAtIndex(oldExceptions, i); } CFMutableDictionaryRef filteredException = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (exception && filteredException) { SecExceptionFilterContext filterContext = { options, i, trustRef, filteredException, oldException }; CFDictionaryApplyFunction(exception, filter_exception, &filterContext); CFArrayAppendValue(filteredExceptions, filteredException); CFRelease(filteredException); } } if (filteredExceptions) { CFIndex filteredCount = CFArrayGetCount(filteredExceptions); /* remove empty trailing entries to match iOS behavior */ for (i = filteredCount; i-- > 1;) { CFDictionaryRef exception = (CFDictionaryRef)CFArrayGetValueAtIndex(filteredExceptions, i); if (CFDictionaryGetCount(exception) == 0) { CFArrayRemoveValueAtIndex(filteredExceptions, i); } else { break; } } encodedExceptions = CFPropertyListCreateData(kCFAllocatorDefault, filteredExceptions, kCFPropertyListBinaryFormat_v1_0, 0, NULL); CFRelease(filteredExceptions); SecTrustSetExceptions(trustRef, encodedExceptions); CFRelease(encodedExceptions); } CFRelease(exceptions); } #if SECTRUST_DEPRECATION_WARNINGS bool displayModifyMsg = false; bool displayNetworkMsg = false; bool displayPolicyMsg = false; const char *baseMsg = "WARNING: SecTrustSetOptions called with"; const char *modifyMsg = "Use SecTrustSetExceptions and SecTrustCopyExceptions to modify default trust results."; const char *networkMsg = "Use SecTrustSetNetworkFetchAllowed to specify whether missing certificates can be fetched from the network."; const char *policyMsg = "Use SecPolicyCreateRevocation to specify revocation policy requirements."; if (options & kSecTrustOptionAllowExpired) { syslog(LOG_ERR, "%s %s.", baseMsg, "kSecTrustOptionAllowExpired"); displayModifyMsg = true; } if (options & kSecTrustOptionAllowExpiredRoot) { syslog(LOG_ERR, "%s %s.", baseMsg, "kSecTrustOptionAllowExpiredRoot"); displayModifyMsg = true; } if (options & kSecTrustOptionFetchIssuerFromNet) { syslog(LOG_ERR, "%s %s.", baseMsg, "kSecTrustOptionFetchIssuerFromNet"); displayNetworkMsg = true; } if (options & kSecTrustOptionRequireRevPerCert) { syslog(LOG_ERR, "%s %s.", baseMsg, "kSecTrustOptionRequireRevPerCert"); displayPolicyMsg = true; } if (displayModifyMsg || displayNetworkMsg || displayPolicyMsg) { syslog(LOG_ERR, "%s %s %s", (displayModifyMsg) ? modifyMsg : "", (displayNetworkMsg) ? networkMsg : "", (displayPolicyMsg) ? policyMsg : ""); } #endif return status; }