From 3a2ae23daa7eb2410a4beadd21fa75ad74ef5a84 Mon Sep 17 00:00:00 2001 From: Jorge Niedbalski Date: Fri, 25 Oct 2024 14:58:32 +0200 Subject: [PATCH] tls: macos_load_system_certificates using security framework. Load certificates from SecTrustSettingsCopyCertificates using the security framework to avoid relying on local certificates. Signed-off-by: Jorge Niedbalski --- src/CMakeLists.txt | 1 + src/tls/openssl.c | 121 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 114 insertions(+), 8 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e24666484a7..82c958dde4a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -284,6 +284,7 @@ if(FLB_SYSTEM_MACOS) ${FLB_DEPS} "-framework Foundation" "-framework IOKit" + "-framework Security" ) endif() diff --git a/src/tls/openssl.c b/src/tls/openssl.c index 99cd9eee9a8..c2ae4b3ac61 100644 --- a/src/tls/openssl.c +++ b/src/tls/openssl.c @@ -27,6 +27,12 @@ #include #include +#ifdef FLB_SYSTEM_MACOS +#include +#include +#include +#endif + #ifdef FLB_SYSTEM_WINDOWS #define strtok_r(str, delimiter, context) \ strtok_s(str, delimiter, context) @@ -235,6 +241,7 @@ static int tls_context_server_alpn_select_callback(SSL *ssl, return result; } + #ifdef _MSC_VER static int windows_load_system_certificates(struct tls_context *ctx) { @@ -246,22 +253,22 @@ static int windows_load_system_certificates(struct tls_context *ctx) X509_STORE *ossl_store = SSL_CTX_get_cert_store(ctx->ctx); X509 *ossl_cert; - // Check if OpenSSL certificate store is available + /* Check if OpenSSL certificate store is available */ if (!ossl_store) { flb_error("[tls] failed to retrieve openssl certificate store."); return -1; } - // Open the Windows system certificate store + /* Open the Windows system certificate store */ win_store = CertOpenSystemStoreA(0, "Root"); if (win_store == NULL) { flb_error("[tls] cannot open windows certificate store: %lu", GetLastError()); return -1; } - // Iterate over certificates in the store + /* Iterate over certificates in the store */ while ((win_cert = CertEnumCertificatesInStore(win_store, win_cert)) != NULL) { - // Check if the certificate is encoded in ASN.1 DER format + /* Check if the certificate is encoded in ASN.1 DER format */ if (win_cert->dwCertEncodingType & X509_ASN_ENCODING) { /* * Decode the certificate into X509 struct. @@ -280,7 +287,7 @@ static int windows_load_system_certificates(struct tls_context *ctx) /* Add X509 struct to the openssl cert store */ ret = X509_STORE_add_cert(ossl_store, ossl_cert); if (!ret) { - unsigned long err = ERR_get_error(); + err = ERR_get_error(); if (err == X509_R_CERT_ALREADY_IN_HASH_TABLE) { flb_debug("[tls] certificate already exists in the store, skipping."); } @@ -293,14 +300,14 @@ static int windows_load_system_certificates(struct tls_context *ctx) } } - // Check for errors during enumeration + /* Check for errors during enumeration */ if (GetLastError() != CRYPT_E_NOT_FOUND) { flb_error("[tls] error occurred while enumerating certificates: %lu", GetLastError()); CertCloseStore(win_store, 0); return -1; } - // Close the Windows system certificate store + /* Close the Windows system certificate store */ if (!CertCloseStore(win_store, 0)) { flb_error("[tls] cannot close windows certificate store: %lu", GetLastError()); return -1; @@ -309,7 +316,101 @@ static int windows_load_system_certificates(struct tls_context *ctx) flb_debug("[tls] successfully loaded certificates from windows system store."); return 0; } +#endif + +#ifdef __APPLE__ +/* macOS-specific system certificate loading */ +static int macos_load_system_certificates(struct tls_context *ctx) +{ + X509_STORE *store = NULL; + X509 *x509 = NULL; + SecCertificateRef cert = NULL; + CFArrayRef certs = NULL; + CFDataRef certData = NULL; + const unsigned char *data = NULL; + char *subject = NULL; + char *issuer = NULL; + OSStatus status; + unsigned long err; + int ret = -1; + int loaded_cert_count = 0; + + /* Retrieve system certificates from macOS Keychain */ + status = SecTrustSettingsCopyCertificates(kSecTrustSettingsDomainSystem, &certs); + if (status != errSecSuccess || !certs) { + flb_debug("[tls] failed to load system certificates from keychain, status: %d", status); + return -1; + } + + flb_debug("[tls] attempting to load macOS keychain system certificates"); + + /* Get the SSL context's certificate store */ + store = SSL_CTX_get_cert_store(ctx->ctx); + if (!store) { + flb_debug("[tls] failed to get certificate store from SSL context"); + CFRelease(certs); + return -1; + } + + /* Load each certificate into the X509 store */ + for (CFIndex i = 0; i < CFArrayGetCount(certs); i++) { + cert = (SecCertificateRef) CFArrayGetValueAtIndex(certs, i); + if (!cert) { + flb_debug("[tls] invalid certificate reference at index %ld, skipping", i); + continue; + } + + certData = SecCertificateCopyData(cert); + if (!certData) { + flb_debug("[tls] failed to retrieve data for certificate %ld from keychain, skipping", i); + continue; + } + + /* Convert certificate data to X509 */ + data = CFDataGetBytePtr(certData); + x509 = d2i_X509(NULL, &data, CFDataGetLength(certData)); + CFRelease(certData); + if (!x509) { + flb_debug("[tls] failed to parse certificate %ld from keychain, skipping", i); + continue; + } + + subject = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0); + issuer = X509_NAME_oneline(X509_get_issuer_name(x509), NULL, 0); + if (subject && issuer) { + flb_debug("[tls] certificate %ld details - subject: %s, issuer: %s", i, subject, issuer); + } + + /* Attempt to add certificate to trusted store */ + ret = X509_STORE_add_cert(store, x509); + if (ret != 1) { + err = ERR_get_error(); + if (ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) { + flb_debug("[tls] certificate %ld already exists in the trusted store (duplicate)", i); + } else { + flb_debug("[tls] failed to add certificate %ld to trusted store, error code: %lu", i, err); + } + X509_free(x509); + continue; + } + + loaded_cert_count++; + flb_debug("[tls] successfully loaded and added certificate %ld to trusted store", i); + + if (subject) { + OPENSSL_free(subject); + } + if (issuer) { + OPENSSL_free(issuer); + } + X509_free(x509); + } + + CFRelease(certs); + flb_debug("[tls] finished loading keychain certificates, total loaded: %d", loaded_cert_count); + return 0; +} #endif static int load_system_certificates(struct tls_context *ctx) @@ -320,7 +421,9 @@ static int load_system_certificates(struct tls_context *ctx) /* For Windows use specific API to read the certs store */ #ifdef _MSC_VER return windows_load_system_certificates(ctx); -#endif +#elif defined(__APPLE__) + return macos_load_system_certificates(ctx); +#else if (access(ca_file, R_OK) != 0) { ca_file = NULL; } @@ -331,8 +434,10 @@ static int load_system_certificates(struct tls_context *ctx) ERR_print_errors_fp(stderr); } return 0; +#endif } + static void *tls_context_create(int verify, int debug, int mode,