]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
gnutls_x509_trust_list_add_system_trust: Add macOS keychain support
authorDavid Caldwell <david@porkrind.org>
Wed, 5 Apr 2017 04:29:55 +0000 (21:29 -0700)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Thu, 6 Apr 2017 10:36:22 +0000 (12:36 +0200)
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>
configure.ac
lib/Makefile.am
lib/system/certs.c

index 2e94e1693ecab81747e461dd15b68d5b3fce9e6e..84c9500edad575ea0908b0a2ef6754841e3b2040 100644 (file)
@@ -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 \
index bf07ecf6f5d251feda787611372e12c3ad1fc46e..98364cb5d2b5b30b8dd6dd761e79edbf5cd4459c 100644 (file)
@@ -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
index 5136275a62e54fba7bf3c0ded04b02fddf715f62..53eb561d0077eabb4648d19759edee757eca83ec 100644 (file)
 # 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