#include "SecTrustOSXEntryPoints.h"
+#include <CoreFoundation/CoreFoundation.h>
+#include <dispatch/dispatch.h>
+#include <AssertMacros.h>
+#include <notify.h>
+#include <mach/mach_time.h>
+
#include <Security/Security.h>
#include <Security/cssmtype.h>
#include <Security/SecKeychain.h>
#include <Security/SecImportExport.h>
#include <security_keychain/SecImportExportPem.h>
#include <security_utilities/debugging.h>
+#include <Security/SecItemInternal.h>
#include <security_ocspd/ocspdClient.h>
#include <security_ocspd/ocspdUtils.h>
-#include <CoreFoundation/CoreFoundation.h>
-#include <CoreFoundation/CFRunLoop.h>
-#include <dispatch/dispatch.h>
-#include <AssertMacros.h>
-#include <pthread.h>
-
-/*
- * MARK: CFRunloop
- */
-
-static OSStatus SecLegacySourceChanged(SecKeychainEvent keychainEvent, SecKeychainCallbackInfo *info, __unused void *context) {
- if (keychainEvent == kSecAddEvent || keychainEvent == kSecDeleteEvent || keychainEvent == kSecUpdateEvent) {
- /* We don't need to purge the cache if the item changed wasn't a cert */
- SecKeychainItemRef item = info->item;
- if (item && CFGetTypeID(item) != SecCertificateGetTypeID()) {
- return 0;
- }
- }
- // Purge keychain parent cache
- SecItemParentCachePurge();
- // Purge unrestricted roots cache
- SecTrustSettingsPurgeUserAdminCertsCache();
- return 0;
-}
-
-static void *SecTrustOSXCFRunloop(__unused void *unused) {
- CFRunLoopTimerRef timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, (CFTimeInterval) UINT_MAX, 0, 0, 0, ^(__unused CFRunLoopTimerRef _timer) {
- /* do nothing */
- });
-
- /* add a timer to force the runloop to stay running */
- CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode);
- /* add keychain callback before we initiate a runloop to avoid it exiting due to no sources */
- SecKeychainEventMask trustdMask = (kSecAddEventMask | kSecDeleteEventMask | kSecUpdateEventMask |
- kSecDefaultChangedEventMask | kSecKeychainListChangedMask |
- kSecTrustSettingsChangedEventMask);
- SecKeychainAddCallback(SecLegacySourceChanged, trustdMask, NULL);
+void SecTrustLegacySourcesListenForKeychainEvents(void) {
+ /* Register for CertificateTrustNotification */
+ int out_token = 0;
+ notify_register_dispatch(kSecServerCertificateTrustNotification, &out_token,
+ dispatch_get_main_queue(),
+ ^(int token __unused) {
+ // Purge keychain parent cache
+ SecItemParentCachePurge();
+ // Purge unrestricted roots cache
+ SecTrustSettingsPurgeUserAdminCertsCache();
- try {
- CFRunLoopRun();
- }
- catch (...) {
- /* An exception was rethrown from the runloop. Since we can't reliably
- * obtain info about changes to keychains or trust settings anymore,
- * just exit and respawn the process when needed. */
-
- secerror("Exception occurred in CFRunLoopRun; exiting");
- exit(0);
- }
- CFRelease(timer);
- return NULL;
-}
-
-void SecTrustLegacySourcesEventRunloopCreate(void) {
- /* A runloop is currently necessary to receive notifications about changes in the
- * legacy keychains and trust settings. */
- static dispatch_once_t once;
-
- dispatch_once(&once, ^{
- pthread_attr_t attrs;
- pthread_t thread;
-
- pthread_attr_init(&attrs);
- pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
-
- /* we do this with traditional pthread to avoid impacting our 512 WQ thread limit since this is a parked thread */
- pthread_create(&thread, &attrs, SecTrustOSXCFRunloop, NULL);
- });
+ });
}
/*
}
#define PEM_STRING_X509 "CERTIFICATE"
-static CFDataRef serializedPathToPemSequences(CFArrayRef certs) {
+static CFDataRef CF_RETURNS_RETAINED serializedPathToPemSequences(CFArrayRef certs) {
CFMutableDataRef result = NULL;
CFIndex certIX, certCount;
require_quiet(certs, out);
/* serialNumber is a CSSM_DATA with the value from the TBS Certificate. */
CSSM_DATA serialNumber = { 0, NULL };
- serialData = SecCertificateCopySerialNumber(cert, NULL);
+ serialData = SecCertificateCopySerialNumberData(cert, NULL);
if (serialData) {
serialNumber.Data = (uint8_t *)CFDataGetBytePtr(serialData);
serialNumber.Length = CFDataGetLength(serialData);
bool SecTrustLegacyCRLFetch(async_ocspd_t *ocspd,
CFURLRef currCRLDP, CFAbsoluteTime verifyTime,
SecCertificateRef cert, CFArrayRef chain) {
+ ocspd->start_time = mach_absolute_time();
dispatch_async(ocspd->queue, ^ {
OSStatus status = fetchCRL(currCRLDP, verifyTime);
switch (status) {