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 | |
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>
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | lib/Makefile.am | 4 | ||||
-rw-r--r-- | lib/system/certs.c | 72 |
3 files changed, 77 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac index 2e94e1693e..84c9500eda 100644 --- a/configure.ac +++ b/configure.ac @@ -780,7 +780,7 @@ dnl auto detect http://lists.gnu.org/archive/html/help-gnutls/2012-05/msg00004.h AC_ARG_WITH([default-trust-store-file], [AS_HELP_STRING([--with-default-trust-store-file=FILE], [use the given file default trust store])], with_default_trust_store_file="$withval", - [if test "$build" = "$host" && test x$with_default_trust_store_pkcs11 = x && test x$with_default_trust_store_dir = x;then + [if test "$build" = "$host" && test x$with_default_trust_store_pkcs11 = x && test x$with_default_trust_store_dir = x && test x$have_macosx = x;then for i in \ /etc/ssl/ca-bundle.pem \ /etc/ssl/certs/ca-certificates.crt \ diff --git a/lib/Makefile.am b/lib/Makefile.am index bf07ecf6f5..98364cb5d2 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -204,6 +204,10 @@ if WINDOWS thirdparty_libadd += -lcrypt32 endif +if MACOSX +libgnutls_la_LDFLAGS += -framework Security -framework CoreFoundation +endif + libgnutls_la_LIBADD += $(thirdparty_libadd) # C++ library 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 |