From 9cf47593542c6f5fb09e5c2651a56706e953d87d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 16 Oct 2023 14:46:36 +0200 Subject: [PATCH] gnutls: support CURLSSLOPT_NATIVE_CA Remove the CURL_CA_FALLBACK logic. That build option was added to allow primarily OpenSSL to use the default paths for loading the CA certs. For GnuTLS it was instead made to load the "system certs", which is different and not desirable. The native CA store loading is now asked for with this option. Follow-up to 7b55279d1d856 Co-authored-by: Jay Satiro Closes #12137 --- docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3 | 13 +-- docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3 | 13 +-- lib/vtls/gtls.c | 84 +++++++++++-------- 3 files changed, 61 insertions(+), 49 deletions(-) diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3 index 3611dbc8c6..bbeca4af1b 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3 +++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3 @@ -62,12 +62,13 @@ library). If combined with \fICURLSSLOPT_NO_REVOKE\fP, the latter takes precedence. (Added in 7.70.0) .IP CURLSSLOPT_NATIVE_CA Tell libcurl to use the operating system's native CA store for certificate -verification. Works only on Windows, Linux (Debian, Ubuntu, Gentoo, Fedora, -RHEL), macOS, Android and iOS when built to use wolfSSL (since 8.3.0) or on -Windows when built to use OpenSSL. If you set this option and also set a CA -certificate file or directory then during verification those certificates -are searched in addition to the native CA store. -(Added in 7.71.0) +verification. If you set this option and also set a CA certificate file or +directory then during verification those certificates are searched in addition +to the native CA store. + +Works with wolfSSL on Windows, Linux (Debian, Ubuntu, Gentoo, Fedora, RHEL), +macOS, Android and iOS (added in 8.3.0), with GnuTLS (added in 8.5.0) or on +Windows when built to use OpenSSL (Added in 7.71.0). .IP CURLSSLOPT_AUTO_CLIENT_CERT Tell libcurl to automatically locate and use a client certificate for authentication, when requested by the server. This option is only supported diff --git a/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3 index fc68238758..59d62b380a 100644 --- a/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3 +++ b/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3 @@ -61,12 +61,13 @@ library). If combined with \fICURLSSLOPT_NO_REVOKE\fP, the latter takes precedence. (Added in 7.70.0) .IP CURLSSLOPT_NATIVE_CA Tell libcurl to use the operating system's native CA store for certificate -verification. Works only on Windows, Linux (Debian, Ubuntu, Gentoo, Fedora, -RHEL), macOS, Android and iOS when built to use wolfSSL (since 8.3.0) or on -Windows when built to use OpenSSL. If you set this option and also set a CA -certificate file or directory then during verification those certificates -are searched in addition to the native CA store. -(Added in 7.71.0) +verification. If you set this option and also set a CA certificate file or +directory then during verification those certificates are searched in addition +to the native CA store. + +Works with wolfSSL on Windows, Linux (Debian, Ubuntu, Gentoo, Fedora, RHEL), +macOS, Android and iOS (added in 8.3.0), with GnuTLS (added in 8.5.0) or on +Windows when built to use OpenSSL (Added in 7.71.0). .IP CURLSSLOPT_AUTO_CLIENT_CERT Tell libcurl to automatically locate and use a client certificate for authentication, when requested by the server. This option is only supported diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index c538a966ec..a7ad454cf9 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.c @@ -460,50 +460,60 @@ CURLcode gtls_client_init(struct Curl_easy *data, } #endif - if(config->CAfile) { - /* set the trusted CA cert bundle file */ - gnutls_certificate_set_verify_flags(gtls->cred, - GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); - - rc = gnutls_certificate_set_x509_trust_file(gtls->cred, - config->CAfile, - GNUTLS_X509_FMT_PEM); - if(rc < 0) { - infof(data, "error reading ca cert file %s (%s)", - config->CAfile, gnutls_strerror(rc)); - if(config->verifypeer) { - *pverifyresult = rc; - return CURLE_SSL_CACERT_BADFILE; + if(config->verifypeer) { + bool imported_native_ca = false; + + if(ssl_config->native_ca_store) { + rc = gnutls_certificate_set_x509_system_trust(gtls->cred); + if(rc < 0) + infof(data, "error reading native ca store (%s), continuing anyway", + gnutls_strerror(rc)); + else { + infof(data, "found %d certificates in native ca store", rc); + if(rc > 0) + imported_native_ca = true; } } - else - infof(data, "found %d certificates in %s", rc, config->CAfile); - } - if(config->CApath) { - /* set the trusted CA cert directory */ - rc = gnutls_certificate_set_x509_trust_dir(gtls->cred, - config->CApath, - GNUTLS_X509_FMT_PEM); - if(rc < 0) { - infof(data, "error reading ca cert file %s (%s)", - config->CApath, gnutls_strerror(rc)); - if(config->verifypeer) { - *pverifyresult = rc; - return CURLE_SSL_CACERT_BADFILE; + if(config->CAfile) { + /* set the trusted CA cert bundle file */ + gnutls_certificate_set_verify_flags(gtls->cred, + GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); + + rc = gnutls_certificate_set_x509_trust_file(gtls->cred, + config->CAfile, + GNUTLS_X509_FMT_PEM); + if(rc < 0) { + infof(data, "error reading ca cert file %s (%s)%s", + config->CAfile, gnutls_strerror(rc), + (imported_native_ca ? ", continuing anyway" : "")); + if(!imported_native_ca) { + *pverifyresult = rc; + return CURLE_SSL_CACERT_BADFILE; + } } + else + infof(data, "found %d certificates in %s", rc, config->CAfile); } - else - infof(data, "found %d certificates in %s", rc, config->CApath); - } -#ifdef CURL_CA_FALLBACK - /* use system ca certificate store as fallback */ - if(config->verifypeer && !(config->CAfile || config->CApath)) { - /* this ignores errors on purpose */ - gnutls_certificate_set_x509_system_trust(gtls->cred); + if(config->CApath) { + /* set the trusted CA cert directory */ + rc = gnutls_certificate_set_x509_trust_dir(gtls->cred, + config->CApath, + GNUTLS_X509_FMT_PEM); + if(rc < 0) { + infof(data, "error reading ca cert file %s (%s)%s", + config->CApath, gnutls_strerror(rc), + (imported_native_ca ? ", continuing anyway" : "")); + if(!imported_native_ca) { + *pverifyresult = rc; + return CURLE_SSL_CACERT_BADFILE; + } + } + else + infof(data, "found %d certificates in %s", rc, config->CApath); + } } -#endif if(config->CRLfile) { /* set the CRL list file */ -- 2.47.3