diff options
author | David Caldwell <david@porkrind.org> | 2017-04-04 21:29:55 -0700 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2017-04-06 12:36:22 +0200 |
commit | c0eb46d3463cd21b3f822ac377ff37f067f66b8d (patch) | |
tree | a38d08221ed692db5723a2831860b5ef8fd84a10 /lib/system | |
parent | 5659d09e3760c8d1986ba9852204c6942bc7d510 (diff) | |
download | gnutls-c0eb46d3463cd21b3f822ac377ff37f067f66b8d.tar.gz |
gnutls_x509_trust_list_add_system_trust: Add macOS keychain support
Also don't check for a default_trust_store_file in configure when building on
macOS (unless explicitly asked to with --with-default-trust-store-file=xxx),
because otherwise it finds /etc/ssl/cert.pem: This file is new (since
10.12.2?), which means libraries built on the newest OS version wouldn't work
the same way on an older versions (and vice versa). "/etc/ssl/cert.pem" also
doesn't seem to reflect additions and deletions from the user's or system's
trusted roots keychain (in my limited testing).
Signed-off-by: David Caldwell <david@porkrind.org>
Diffstat (limited to 'lib/system')
-rw-r--r-- | lib/system/certs.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/lib/system/certs.c b/lib/system/certs.c index 5136275a62..53eb561d00 100644 --- a/lib/system/certs.c +++ b/lib/system/certs.c @@ -44,6 +44,12 @@ # endif #endif +#ifdef __APPLE__ +# include <CoreFoundation/CoreFoundation.h> +# include <Security/Security.h> +# include <Availability.h> +#endif + /* System specific function wrappers for certificate stores. */ @@ -270,6 +276,72 @@ int add_system_trust(gnutls_x509_trust_list_t list, unsigned int tl_flags, return r; } +#elif defined(__APPLE__) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 +static +int osstatus_error(status) +{ + CFStringRef err_str = SecCopyErrorMessageString(status, NULL); + _gnutls_debug_log("Error loading system root certificates: %s\n", + CFStringGetCStringPtr(err_str, kCFStringEncodingUTF8)); + CFRelease(err_str); + return GNUTLS_E_FILE_ERROR; +} + +static +int add_system_trust(gnutls_x509_trust_list_t list, unsigned int tl_flags, + unsigned int tl_vflags) +{ + int r=0; + + SecTrustSettingsDomain domain[] = { kSecTrustSettingsDomainUser, + kSecTrustSettingsDomainAdmin, + kSecTrustSettingsDomainSystem }; + for (size_t d=0; d<sizeof(domain)/sizeof(*domain); d++) { + CFArrayRef certs = NULL; + OSStatus status = SecTrustSettingsCopyCertificates(domain[d], + &certs); + if (status == errSecNoTrustSettings) + continue; + if (status != errSecSuccess) + return osstatus_error(status); + + int cert_count = CFArrayGetCount(certs); + for (int i=0; i<cert_count; i++) { + SecCertificateRef cert = + (void*)CFArrayGetValueAtIndex(certs, i); + CFDataRef der; + status = SecItemExport(cert, kSecFormatX509Cert, 0, + NULL, &der); + if (status != errSecSuccess) { + CFRelease(der); + CFRelease(certs); + return osstatus_error(status); + } + + if (gnutls_x509_trust_list_add_trust_mem(list, + &(gnutls_datum_t) { + .data = (void*)CFDataGetBytePtr(der), + .size = CFDataGetLength(der), + }, + NULL, + GNUTLS_X509_FMT_DER, + tl_flags, + tl_vflags) > 0) + r++; + CFRelease(der); + } + CFRelease(certs); + } + +#ifdef DEFAULT_BLACKLIST_FILE + ret = gnutls_x509_trust_list_remove_trust_file(list, DEFAULT_BLACKLIST_FILE, GNUTLS_X509_FMT_PEM); + if (ret < 0) { + _gnutls_debug_log("Could not load blacklist file '%s'\n", DEFAULT_BLACKLIST_FILE); + } +#endif + + return r; +} #else #define add_system_trust(x,y,z) GNUTLS_E_UNIMPLEMENTED_FEATURE |