summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Caldwell <david@porkrind.org>2017-04-04 21:29:55 -0700
committerNikos Mavrogiannopoulos <nmav@redhat.com>2017-04-06 12:41:20 +0200
commit4cf8a0a8447aea6b9cd6e6a84cecbe4fad64726e (patch)
tree7538df271188e8feda52d5a6bc731a335df340fa
parentc904c8728cafb7d4bb8504762996f9fa0b89dba1 (diff)
downloadgnutls-4cf8a0a8447aea6b9cd6e6a84cecbe4fad64726e.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.ac2
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/system/certs.c72
3 files changed, 77 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index c797f28ea3..7efdb45e31 100644
--- a/configure.ac
+++ b/configure.ac
@@ -788,7 +788,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 dc49bc66cd..b9dfb4fe64 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -206,6 +206,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