windows: add build option to use the native CA store

With the same semantics as Apple SecTrust, in both libcurl and the curl
tool, when using non-Schannel TLS backends. In practice it means that
it makes TLS work without manually or implicitly configuring a CA bundle
`.crt` file, such as `curl-ca-bundle.crt`.

To enable:
- autotools: `--enable-ca-native`
- cmake: `-DCURL_CA_NATIVE=ON`
- CPPFLAGS: `-DCURL_CA_NATIVE`

When enabled:
- enables `CURLSSLOPT_NATIVE_CA` (libcurl) / `--ca-native`
  and `--proxy-ca-native` (curl tool) options by default.
- unsafe search for an on-disk CA bundle gets disabled by default.
  Equivalent to `--disable-ca-search` with autotools,
  `-DCURL_DISABLE_CA_SEARCH=ON` with CMake.
- build-time detection of CA bundle and CA path gets disabled. As with
  Apple SecTrust. This was already the default for Windows.
- native CA can be disabled at run-time with the `--no-ca-native`
  and/or `--no-proxy-ca-native` command-line options.

Rationale: This build option:
- has a repeat and active interest from packagers and users.
- helps integrating curl with Windows for those who need this.
- it also applies to macOS: #17525
  Shipped in curl 8.17.0.
- makes it trivial to use custom certs configured on the OS.
- frees applications/packagers/users from the task of securely
  distributing, and keeping up-to-date, a CA bundle.
- frees potentially many curl tool from configuring a CA bundle manually
  to access HTTPS (and other TLS) URLs. This is traditionally difficult
  on Windows because there is no concept of a universal, protected,
  non-world-writable, location on the file system to securely store
  a CA bundle.
- allows using modern features regardless of Windows version. Some of
  these features are not supported with Schannel (e.g. HTTP/3, ECH) on
  any Windows version.
- is necessary for HTTP/3 builds, where bootstrapping a CA bundle is not
  possible with Schannel, because MultiSSL is not an option, and HTTP/3
  is not supported with Schannel.

Ref: #16181 (previous attempt)
Ref: https://github.com/curl/curl/discussions/9348
Ref: https://github.com/curl/curl/issues/9350
Ref: https://github.com/curl/curl/pull/13111
Ref: https://github.com/microsoft/vcpkg/pull/46459#issuecomment-3162068701
Ref: 22652a5a4c #14582
Ref: eefd03c572 #18703

Closes #18279
This commit is contained in:
Viktor Szakats
2025-08-14 00:48:00 +02:00
parent 5aa303f1bf
commit 1730407b74
9 changed files with 83 additions and 13 deletions

View File

@@ -200,7 +200,7 @@ jobs:
- { build: 'autotools', sys: 'msys' , env: 'x86_64' , tflags: '' , config: '--with-openssl', install: 'openssl-devel libssh2-devel', name: 'default R' }
# MinGW
- { build: 'autotools', sys: 'mingw64' , env: 'x86_64' , tflags: 'skiprun' , config: '--enable-debug --with-openssl --disable-threaded-resolver --disable-curldebug --enable-static --without-zlib', install: 'mingw-w64-x86_64-openssl mingw-w64-x86_64-libssh2', name: 'default' }
- { build: 'autotools', sys: 'mingw64' , env: 'x86_64' , tflags: '' , config: '--enable-debug --with-openssl --enable-windows-unicode --enable-ares --with-openssl-quic --enable-static --disable-shared', install: 'mingw-w64-x86_64-c-ares mingw-w64-x86_64-openssl mingw-w64-x86_64-nghttp3 mingw-w64-x86_64-libssh2', name: 'c-ares U' }
- { build: 'autotools', sys: 'mingw64' , env: 'x86_64' , tflags: '' , config: '--enable-debug --with-openssl --enable-windows-unicode --enable-ares --with-openssl-quic --enable-static --disable-shared --enable-ca-native', install: 'mingw-w64-x86_64-c-ares mingw-w64-x86_64-openssl mingw-w64-x86_64-nghttp3 mingw-w64-x86_64-libssh2', name: 'c-ares U' }
- { build: 'cmake' , sys: 'mingw64' , env: 'x86_64' , tflags: '--min=1650', config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON -DENABLE_ARES=ON', install: 'mingw-w64-x86_64-c-ares mingw-w64-x86_64-libssh2', type: 'Debug', name: 'schannel c-ares U' }
# MinGW torture
- { build: 'cmake' , sys: 'mingw64' , env: 'x86_64' , tflags: '-t --shallow=13 --min=700 1 to 950' , config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON -DENABLE_ARES=ON', install: 'mingw-w64-x86_64-c-ares mingw-w64-x86_64-libssh2', type: 'Debug', name: 'schannel U torture 1' }
@@ -764,6 +764,7 @@ jobs:
-DNGTCP2_INCLUDE_DIR=/ucrt64/include
-DNGTCP2_LIBRARY=/ucrt64/lib/libngtcp2.dll.a
-DNGTCP2_CRYPTO_OSSL_LIBRARY=/ucrt64/lib/libngtcp2_crypto_ossl.dll.a
-DCURL_CA_NATIVE=ON
- name: 'schannel U'
install-vcpkg: 'zlib libssh2[core,zlib]'

View File

@@ -1325,6 +1325,13 @@ endif()
#
# CA handling
#
option(CURL_CA_NATIVE "Use native CA store" OFF)
if(CURL_CA_NATIVE)
set(_curl_disable_ca_search_default ON)
else()
set(_curl_disable_ca_search_default OFF)
endif()
if(_curl_ca_bundle_supported)
set(_ca_opt_desc "Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
@@ -1347,7 +1354,7 @@ if(_curl_ca_bundle_supported)
unset(CURL_CA_BUNDLE CACHE)
elseif(CURL_CA_BUNDLE STREQUAL "auto")
unset(CURL_CA_BUNDLE CACHE)
if(NOT CMAKE_CROSSCOMPILING AND NOT WIN32 AND NOT USE_APPLE_SECTRUST)
if(NOT CMAKE_CROSSCOMPILING AND NOT WIN32 AND NOT USE_APPLE_SECTRUST AND NOT CURL_CA_NATIVE)
set(_curl_ca_bundle_autodetect TRUE)
endif()
else()
@@ -1361,7 +1368,7 @@ if(_curl_ca_bundle_supported)
unset(CURL_CA_PATH CACHE)
elseif(CURL_CA_PATH STREQUAL "auto")
unset(CURL_CA_PATH CACHE)
if(NOT CMAKE_CROSSCOMPILING AND NOT WIN32 AND NOT USE_APPLE_SECTRUST)
if(NOT CMAKE_CROSSCOMPILING AND NOT WIN32 AND NOT USE_APPLE_SECTRUST AND NOT CURL_CA_NATIVE)
set(_curl_ca_path_autodetect TRUE)
endif()
else()
@@ -1418,7 +1425,7 @@ if(_curl_ca_bundle_supported)
endif()
if(WIN32)
option(CURL_DISABLE_CA_SEARCH "Disable unsafe CA bundle search in PATH on Windows" OFF)
option(CURL_DISABLE_CA_SEARCH "Disable unsafe CA bundle search in PATH on Windows" ${_curl_disable_ca_search_default})
option(CURL_CA_SEARCH_SAFE "Enable safe CA bundle search (within the curl tool directory) on Windows" OFF)
endif()
@@ -1998,6 +2005,7 @@ curl_add_if("PSL" USE_LIBPSL)
curl_add_if("CAcert" CURL_CA_EMBED_SET)
curl_add_if("SSLS-EXPORT" _ssl_enabled AND USE_SSLS_EXPORT)
curl_add_if("AppleSecTrust" USE_APPLE_SECTRUST AND _ssl_enabled AND (USE_OPENSSL OR USE_GNUTLS))
curl_add_if("NativeCA" NOT USE_APPLE_SECTRUST AND _ssl_enabled AND CURL_CA_NATIVE)
if(_items)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.13)
list(SORT _items CASE INSENSITIVE)

View File

@@ -1151,6 +1151,8 @@ AS_HELP_STRING([--without-ca-path], [Do not use a default CA path]),
if test "$APPLE_SECTRUST_ENABLED" = "1"; then
ca_native="Apple SecTrust"
elif test "$ca_native_opt" = "1"; then
ca_native="yes"
else
ca_native="no"
fi

View File

@@ -2093,6 +2093,28 @@ elif test "$VALID_DEFAULT_SSL_BACKEND" = "yes"; then
AC_DEFINE_UNQUOTED([CURL_DEFAULT_SSL_BACKEND], ["$DEFAULT_SSL_BACKEND"], [Default SSL backend])
fi
dnl ---------------------
dnl check native CA store
dnl ---------------------
ca_native_opt=0
AC_MSG_CHECKING([whether to use native CA store])
AC_ARG_ENABLE(ca-native,
AS_HELP_STRING([--enable-ca-native],[Enable native CA store])
AS_HELP_STRING([--disable-ca-native],[Disable native CA store (default)]),
[ case "$enableval" in
yes)
AC_MSG_RESULT([yes])
AC_DEFINE(CURL_CA_NATIVE, 1, [If native CA store is enabled])
ca_native_opt=1
;;
*)
AC_MSG_RESULT([no])
;;
esac ],
AC_MSG_RESULT([no])
)
dnl **********************************************************************
dnl Check for the CA bundle
dnl **********************************************************************
@@ -2109,21 +2131,38 @@ dnl check unsafe CA search
dnl ----------------------
if test "$curl_cv_native_windows" = "yes"; then
ca_search=1
AC_MSG_CHECKING([whether to enable unsafe CA bundle search in PATH on Windows])
AC_ARG_ENABLE(ca-search,
AS_HELP_STRING([--enable-ca-search],[Enable unsafe CA bundle search in PATH on Windows (default)])
AS_HELP_STRING([--enable-ca-search],[Enable unsafe CA bundle search in PATH on Windows])
AS_HELP_STRING([--disable-ca-search],[Disable unsafe CA bundle search in PATH on Windows]),
[ case "$enableval" in
no)
AC_MSG_RESULT([no])
AC_DEFINE(CURL_DISABLE_CA_SEARCH, 1, [If unsafe CA bundle search in PATH on Windows is disabled])
ca_search=0
;;
yes)
AC_MSG_RESULT([yes])
;;
*)
AC_MSG_RESULT([yes])
if test "$ca_native_opt" = "1"; then
AC_MSG_RESULT([no])
ca_search=0
else
AC_MSG_RESULT([yes])
fi
;;
esac ],
AC_MSG_RESULT([yes])
if test "$ca_native_opt" = "1"; then
AC_MSG_RESULT([no])
ca_search=0
else
AC_MSG_RESULT([yes])
fi
)
if test "$ca_search" = "0"; then
AC_DEFINE(CURL_DISABLE_CA_SEARCH, 1, [If unsafe CA bundle search in PATH on Windows is disabled])
fi
fi
dnl --------------------
@@ -5286,8 +5325,12 @@ if test "$OPENSSL_ENABLED" = "1" || test -n "$SSL_ENABLED"; then
fi
fi
if test "$APPLE_SECTRUST_ENABLED" = "1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES AppleSecTrust"
if test -n "$SSL_ENABLED"; then
if test "$APPLE_SECTRUST_ENABLED" = "1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES AppleSecTrust"
elif test "$ca_native_opt" = "1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES NativeCA"
fi
fi
if test "$want_httpsrr" != "no"; then

View File

@@ -260,6 +260,8 @@ target_link_libraries(my_target PRIVATE CURL::libcurl)
- `CURL_CA_BUNDLE`: Absolute path to the CA bundle. Set `none` to disable or `auto` for auto-detection. Default: `auto`
- `CURL_CA_EMBED`: Absolute path to the CA bundle to embed in the curl tool. Default: (disabled)
- `CURL_CA_FALLBACK`: Use built-in CA store of OpenSSL. Default: `OFF`
- `CURL_CA_NATIVE`: Use native CA store. Default: `OFF`
Supported by GnuTLS, OpenSSL (including forks) on Windows, wolfSSL.
- `CURL_CA_PATH`: Absolute path to a directory containing CA certificates stored individually. Set `none` to disable or `auto` for auto-detection. Default: `auto`
- `CURL_CA_SEARCH_SAFE`: Enable safe CA bundle search (within the curl tool directory) on Windows. Default: `OFF`
@@ -283,7 +285,7 @@ target_link_libraries(my_target PRIVATE CURL::libcurl)
- `CURL_DISABLE_BASIC_AUTH`: Disable Basic authentication. Default: `OFF`
- `CURL_DISABLE_BEARER_AUTH`: Disable Bearer authentication. Default: `OFF`
- `CURL_DISABLE_BINDLOCAL`: Disable local binding support. Default: `OFF`
- `CURL_DISABLE_CA_SEARCH`: Disable unsafe CA bundle search in PATH on Windows. Default: `OFF`
- `CURL_DISABLE_CA_SEARCH`: Disable unsafe CA bundle search in PATH on Windows. Default: `OFF` (turns to `ON`, when `CURL_CA_NATIVE=ON`)
- `CURL_DISABLE_COOKIES`: Disable cookies support. Default: `OFF`
- `CURL_DISABLE_DICT`: Disable DICT. Default: `OFF`
- `CURL_DISABLE_DIGEST_AUTH`: Disable Digest authentication. Default: `OFF`

View File

@@ -286,6 +286,13 @@ supports HTTP deflate using libz
libcurl was built with multiple SSL backends. For details, see
curl_global_sslset(3).
## `NativeCA`
*features* mask bit: non-existent
libcurl was built to enable native CA store, to verify server certificates
(Added in 8.19.0).
## `NTLM`
*features* mask bit: CURL_VERSION_NTLM

View File

@@ -34,6 +34,9 @@
/* Default SSL backend */
#cmakedefine CURL_DEFAULT_SSL_BACKEND "${CURL_DEFAULT_SSL_BACKEND}"
/* Use native CA store */
#cmakedefine CURL_CA_NATIVE 1
/* disables alt-svc */
#cmakedefine CURL_DISABLE_ALTSVC 1

View File

@@ -513,9 +513,13 @@ static const struct feat features_table[] = {
#ifdef USE_LIBPSL
FEATURE("PSL", NULL, CURL_VERSION_PSL),
#endif
#ifdef USE_SSL
#ifdef USE_APPLE_SECTRUST
FEATURE("AppleSecTrust", NULL, 0),
#elif defined(CURL_CA_NATIVE)
FEATURE("NativeCA", NULL, 0),
#endif
#endif /* USE_SSL */
#ifdef USE_SPNEGO
FEATURE("SPNEGO", NULL, CURL_VERSION_SPNEGO),
#endif

View File

@@ -295,7 +295,7 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data)
#endif
if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
#ifdef USE_APPLE_SECTRUST
#if defined(USE_APPLE_SECTRUST) || defined(CURL_CA_NATIVE)
if(!sslc->custom_capath && !sslc->custom_cafile && !sslc->custom_cablob)
sslc->native_ca_store = TRUE;
#endif
@@ -341,7 +341,7 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data)
#ifndef CURL_DISABLE_PROXY
sslc = &data->set.proxy_ssl;
if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
#ifdef USE_APPLE_SECTRUST
#if defined(USE_APPLE_SECTRUST) || defined(CURL_CA_NATIVE)
if(!sslc->custom_capath && !sslc->custom_cafile && !sslc->custom_cablob)
sslc->native_ca_store = TRUE;
#endif