mirror of
https://github.com/curl/curl.git
synced 2026-01-26 15:03:21 +00:00
ssl: support Apple SecTrust configurations
- configure/cmake support for enabling the option - supported in OpenSSL and GnuTLS backends - when configured, Apple SecTrust is the default trust store for peer verification. When one of the CURLOPT_* for adding certificates is used, that default does not apply. - add documentation of build options and SSL use Closes #18703
This commit is contained in:
parent
9cc1ee55a4
commit
eefd03c572
1
.github/scripts/spellcheck.words
vendored
1
.github/scripts/spellcheck.words
vendored
@ -743,6 +743,7 @@ scp
|
||||
SDK
|
||||
se
|
||||
SEB
|
||||
SecTrust
|
||||
SEK
|
||||
selectable
|
||||
Serv
|
||||
|
||||
4
.github/workflows/configure-vs-cmake.yml
vendored
4
.github/workflows/configure-vs-cmake.yml
vendored
@ -92,13 +92,13 @@ jobs:
|
||||
run: |
|
||||
autoreconf -fi
|
||||
export PKG_CONFIG_DEBUG_SPEW=1
|
||||
mkdir bld-am && cd bld-am && ../configure --enable-static=no --with-openssl --without-libpsl --disable-ldap --with-brotli --with-zstd
|
||||
mkdir bld-am && cd bld-am && ../configure --enable-static=no --with-openssl --without-libpsl --disable-ldap --with-brotli --with-zstd --with-apple-sectrust
|
||||
|
||||
- name: 'run cmake'
|
||||
run: |
|
||||
cmake -B bld-cm -DCURL_WERROR=ON -DCURL_USE_LIBPSL=OFF -DCURL_DISABLE_LDAP=ON \
|
||||
-DCMAKE_C_COMPILER_TARGET="$(uname -m | sed 's/arm64/aarch64/')-apple-darwin$(uname -r)" \
|
||||
-DCURL_USE_LIBSSH2=OFF
|
||||
-DCURL_USE_LIBSSH2=OFF -DUSE_APPLE_SECTRUST=ON
|
||||
|
||||
- name: 'configure log'
|
||||
run: cat bld-am/config.log 2>/dev/null || true
|
||||
|
||||
9
.github/workflows/macos.yml
vendored
9
.github/workflows/macos.yml
vendored
@ -265,6 +265,11 @@ jobs:
|
||||
install: libnghttp3 libngtcp2
|
||||
install_steps: pytest
|
||||
configure: --enable-debug --with-openssl=/opt/homebrew/opt/openssl --with-ngtcp2
|
||||
- name: 'OpenSSL SecTrust'
|
||||
compiler: clang
|
||||
install: libnghttp3 libngtcp2
|
||||
install_steps: pytest
|
||||
configure: --enable-debug --with-openssl=/opt/homebrew/opt/openssl --with-ngtcp2 --with-apple-sectrust
|
||||
- name: 'OpenSSL event-based'
|
||||
compiler: clang
|
||||
configure: --enable-debug --with-openssl=/opt/homebrew/opt/openssl
|
||||
@ -275,9 +280,9 @@ jobs:
|
||||
configure: --enable-debug --disable-ldap --with-openssl=/opt/homebrew/opt/quictls LDFLAGS=-L/opt/homebrew/opt/quictls/lib
|
||||
macos-version-min: '10.15'
|
||||
# cmake
|
||||
- name: 'OpenSSL gsasl rtmp AppleIDN'
|
||||
- name: 'OpenSSL gsasl rtmp AppleIDN SecTrust'
|
||||
install: libnghttp3 libngtcp2 gsasl rtmpdump
|
||||
generate: -DOPENSSL_ROOT_DIR=/opt/homebrew/opt/openssl -DCURL_USE_GSASL=ON -DUSE_LIBRTMP=ON -DUSE_APPLE_IDN=ON -DUSE_NGTCP2=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON
|
||||
generate: -DOPENSSL_ROOT_DIR=/opt/homebrew/opt/openssl -DCURL_USE_GSASL=ON -DUSE_LIBRTMP=ON -DUSE_APPLE_IDN=ON -DUSE_NGTCP2=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DUSE_APPLE_SECTRUST=ON
|
||||
- name: 'MultiSSL AppleIDN clang-tidy +examples'
|
||||
compiler: clang
|
||||
install: llvm brotli zstd gnutls nettle libressl krb5 mbedtls gsasl rustls-ffi rtmpdump libssh fish
|
||||
|
||||
@ -764,6 +764,23 @@ if(CURL_WINDOWS_SSPI AND NOT WINDOWS_STORE)
|
||||
set(USE_WINDOWS_SSPI ON)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
option(USE_APPLE_SECTRUST "Use Apple OS-native certificate verification" OFF)
|
||||
if(USE_APPLE_SECTRUST)
|
||||
find_library(COREFOUNDATION_FRAMEWORK NAMES "Security")
|
||||
mark_as_advanced(COREFOUNDATION_FRAMEWORK)
|
||||
if(NOT COREFOUNDATION_FRAMEWORK)
|
||||
message(FATAL_ERROR "Security framework not found")
|
||||
endif()
|
||||
list(APPEND CURL_LIBS "-framework Security")
|
||||
|
||||
set(_use_core_foundation_and_core_services ON)
|
||||
message(STATUS "Apple OS-native certificate verification enabled")
|
||||
endif()
|
||||
else()
|
||||
set(USE_APPLE_SECTRUST OFF)
|
||||
endif()
|
||||
|
||||
if(_use_core_foundation_and_core_services)
|
||||
find_library(COREFOUNDATION_FRAMEWORK NAMES "CoreFoundation")
|
||||
mark_as_advanced(COREFOUNDATION_FRAMEWORK)
|
||||
@ -1531,7 +1548,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)
|
||||
if(NOT CMAKE_CROSSCOMPILING AND NOT WIN32 AND NOT USE_APPLE_SECTRUST)
|
||||
set(_curl_ca_bundle_autodetect TRUE)
|
||||
endif()
|
||||
else()
|
||||
|
||||
10
acinclude.m4
10
acinclude.m4
@ -1149,6 +1149,12 @@ AS_HELP_STRING([--without-ca-path], [Don't use a default CA path]),
|
||||
capath_warning=" (warning: certs not found)"
|
||||
check_capath=""
|
||||
|
||||
if test "x$APPLE_SECTRUST_ENABLED" = "x1"; then
|
||||
ca_native="Apple SecTrust"
|
||||
else
|
||||
ca_native="no"
|
||||
fi
|
||||
|
||||
if test "x$want_ca" != "xno" -a "x$want_ca" != "xunset" -a \
|
||||
"x$want_capath" != "xno" -a "x$want_capath" != "xunset"; then
|
||||
dnl both given
|
||||
@ -1162,6 +1168,10 @@ AS_HELP_STRING([--without-ca-path], [Don't use a default CA path]),
|
||||
dnl --with-ca-path given
|
||||
capath="$want_capath"
|
||||
ca="no"
|
||||
elif test "x$ca_native" != "xno"; then
|
||||
# native ca configured, do not look further
|
||||
ca="no"
|
||||
capath="no"
|
||||
else
|
||||
dnl First try auto-detecting a CA bundle, then a CA path.
|
||||
dnl Both auto-detections can be skipped by --without-ca-*
|
||||
|
||||
@ -277,6 +277,12 @@ AS_HELP_STRING([--with-rustls=PATH],[where to look for Rustls, PATH points to th
|
||||
fi
|
||||
])
|
||||
|
||||
OPT_APPLE_SECTRUST=$curl_cv_apple
|
||||
AC_ARG_WITH(apple-sectrust,dnl
|
||||
AS_HELP_STRING([--with-apple-sectrust],[enable Apple OS native certificate verification]),[
|
||||
OPT_APPLE_SECTRUST=$withval
|
||||
])
|
||||
|
||||
AC_PATH_PROG(PERL, perl,, $PATH:/usr/local/bin/perl:/usr/bin/:/usr/local/bin)
|
||||
AC_SUBST(PERL)
|
||||
AM_CONDITIONAL(PERL, test -n "$PERL")
|
||||
@ -2016,6 +2022,7 @@ CURL_WITH_GNUTLS
|
||||
CURL_WITH_MBEDTLS
|
||||
CURL_WITH_WOLFSSL
|
||||
CURL_WITH_RUSTLS
|
||||
CURL_WITH_APPLE_SECTRUST
|
||||
|
||||
dnl link required libraries for USE_WIN32_CRYPTO or SCHANNEL_ENABLED
|
||||
if test "x$USE_WIN32_CRYPTO" = "x1" -o "x$SCHANNEL_ENABLED" = "x1"; then
|
||||
@ -5588,6 +5595,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
|
||||
Verbose errors: ${curl_verbose_msg}
|
||||
Code coverage: ${curl_coverage_msg}
|
||||
SSPI: ${curl_sspi_msg}
|
||||
ca native: ${ca_native}
|
||||
ca cert bundle: ${ca}${ca_warning}
|
||||
ca cert path: ${capath}${capath_warning}
|
||||
ca cert embed: ${CURL_CA_EMBED_msg}
|
||||
|
||||
@ -368,6 +368,7 @@ Details via CMake
|
||||
- `CURL_ZSTD`: Use zstd (`ON`, `OFF` or `AUTO`). Default: `AUTO`
|
||||
- `ENABLE_ARES`: Enable c-ares support. Default: `OFF`
|
||||
- `USE_APPLE_IDN`: Use Apple built-in IDN support. Default: `OFF`
|
||||
- `USE_APPLE_SECTRUST`: Use Apple OS-native certificate verification. Default: `OFF`
|
||||
- `USE_LIBIDN2`: Use libidn2 for IDN support. Default: `ON`
|
||||
- `USE_LIBRTMP`: Enable librtmp from rtmpdump. Default: `OFF`
|
||||
- `USE_NGHTTP2`: Use nghttp2 library. Default: `ON`
|
||||
|
||||
@ -153,6 +153,25 @@ conflicting identical symbol names.
|
||||
When you build with multiple TLS backends, you can select the active one at
|
||||
runtime when curl starts up.
|
||||
|
||||
### Selecting TLS Trust Anchors Defaults
|
||||
|
||||
Verifying a server certificate established a chain of trust that needs to
|
||||
start somewhere. Those "root" certificates make the set of Trust Anchors.
|
||||
|
||||
While the build system tries to find good defaults on the platform you
|
||||
use, you may specify these explicitly. The following options are provided:
|
||||
|
||||
- `--with-ca-bundle=FILE`: the file that libcurl loads default root
|
||||
certificates from.
|
||||
- `--with-ca-path=DIRECTORY`: a directory in which root certificates files
|
||||
are found.
|
||||
- `--with-ca-embed=FILE`: a file read *at build time* and added to `libcurl`.
|
||||
- `--with-ca-fallback`: an OpenSSL specific option for delegating default
|
||||
trust anchor selection to what OpenSSL thinks is best, *if* there are
|
||||
no other certificates configured by the application.
|
||||
- `--with-apple-sectrust`: use the system "SecTrust" service on Apple
|
||||
operating systems for verification. (Added in 8.17.0)
|
||||
|
||||
## MultiSSL and HTTP/3
|
||||
|
||||
HTTP/3 needs QUIC and QUIC needs TLS. Building libcurl with HTTP/3 and QUIC
|
||||
|
||||
@ -8,8 +8,10 @@ SPDX-License-Identifier: curl
|
||||
|
||||
## Native vs file based
|
||||
|
||||
If curl was built with Schannel support, then curl uses the system native CA
|
||||
store for verification. All other TLS libraries use a file based CA store by
|
||||
If curl was built with Schannel support, then curl uses the Windows native CA
|
||||
store for verification. On Apple operating systems, it is possible to use Apple's
|
||||
"SecTrust" services for certain TLS backends, details below.
|
||||
All other TLS libraries use a file based CA store by
|
||||
default.
|
||||
|
||||
## Verification
|
||||
@ -71,8 +73,10 @@ another option to restrict search to the application's directory.
|
||||
|
||||
### Use the native store
|
||||
|
||||
In several environments, in particular on Windows, you can ask curl to use the
|
||||
system's native CA store when verifying the certificate.
|
||||
In several environments, in particular on Microsoft and Apple operating
|
||||
systems, you can ask curl to use the system's native CA store when verifying
|
||||
the certificate. Depending on how curl was built, this may already be the
|
||||
default.
|
||||
|
||||
With the curl command line tool: `--ca-native`.
|
||||
|
||||
@ -102,14 +106,46 @@ latest Firefox bundle.
|
||||
|
||||
## Native CA store
|
||||
|
||||
If curl was built with Schannel or was instructed to use the native CA Store,
|
||||
then curl uses the certificates that are built into the OS. These are the same
|
||||
certificates that appear in the Internet Options control panel (under Windows)
|
||||
or Keychain Access application (under macOS). Any custom security rules for
|
||||
certificates are honored.
|
||||
### Windows + Schannel
|
||||
|
||||
If curl was built with Schannel, then curl uses the certificates that are
|
||||
built into the OS. These are the same certificates that appear in the
|
||||
Internet Options control panel (under Windows).
|
||||
Any custom security rules for certificates are honored.
|
||||
|
||||
Schannel runs CRL checks on certificates unless peer verification is disabled.
|
||||
|
||||
### Apple + OpenSSL/GnuTLS
|
||||
|
||||
When curl is built with Apple SecTrust enabled and uses an OpenSSL compatible
|
||||
TLS backend or GnuTLS, the default verification is handled by that Apple
|
||||
service. As in:
|
||||
|
||||
curl https://example.com
|
||||
|
||||
You may still provide your own certificates on the command line, such as:
|
||||
|
||||
curl --cacert mycerts.pem https://example.com
|
||||
|
||||
In this situation, Apple SecTrust is **not** used and verification is done
|
||||
**only** with the trust anchors found in `mycerts.pem`. If you want **both**
|
||||
Apple SecTrust and your own file to be considered, use:
|
||||
|
||||
curl --ca-native --cacert mycerts.pem https://example.com
|
||||
|
||||
|
||||
#### Other Combinations
|
||||
|
||||
How well the use of native CA stores work in all other combinations depends
|
||||
on the TLS backend and the OS. Many TLS backends offer functionality to access
|
||||
the native CA on a range of operating systems. Some provide this only on specific
|
||||
configurations.
|
||||
|
||||
Specific support in curl exists for Windows and OpenSSL compatible TLS backends.
|
||||
It tries to load the certificates from the Windows "CA" and "ROOT" stores for
|
||||
transfers requesting the native CA. Due to Window's delayed population of those
|
||||
stores, this might not always find all certificates.
|
||||
|
||||
## HTTPS proxy
|
||||
|
||||
curl can do HTTPS to the proxy separately from the connection to the server.
|
||||
|
||||
@ -25,12 +25,14 @@ This option is independent of other CA certificate locations set at run time or
|
||||
build time. Those locations are searched in addition to the native CA store.
|
||||
|
||||
This option works with OpenSSL and its forks (LibreSSL, BoringSSL, etc) on
|
||||
Windows. (Added in 7.71.0)
|
||||
Windows (Added in 7.71.0) and on Apple OS when libcurl is built with
|
||||
Apple SecTrust enabled. (Added in 8.17.0)
|
||||
|
||||
This option works with wolfSSL on Windows, Linux (Debian, Ubuntu, Gentoo,
|
||||
Fedora, RHEL), macOS, Android and iOS. (Added in 8.3.0)
|
||||
|
||||
This option works with GnuTLS. (Added in 8.5.0)
|
||||
This option works with GnuTLS (Added in 8.5.0) and also uses Apple
|
||||
SecTrust when libcurl is built with it. (Added in 8.17.0)
|
||||
|
||||
This option works with rustls on Windows, macOS, Android and iOS. On Linux it
|
||||
is equivalent to using the Mozilla CA certificate bundle. When used with rustls
|
||||
|
||||
@ -77,6 +77,7 @@ LIB_VAUTH_HFILES = \
|
||||
vauth/vauth.h
|
||||
|
||||
LIB_VTLS_CFILES = \
|
||||
vtls/apple.c \
|
||||
vtls/cipher_suite.c \
|
||||
vtls/gtls.c \
|
||||
vtls/hostcheck.c \
|
||||
@ -94,6 +95,7 @@ LIB_VTLS_CFILES = \
|
||||
vtls/x509asn1.c
|
||||
|
||||
LIB_VTLS_HFILES = \
|
||||
vtls/apple.h \
|
||||
vtls/cipher_suite.h \
|
||||
vtls/gtls.h \
|
||||
vtls/hostcheck.h \
|
||||
|
||||
@ -788,6 +788,9 @@ ${SIZEOF_TIME_T_CODE}
|
||||
/* to enable Apple IDN */
|
||||
#cmakedefine USE_APPLE_IDN 1
|
||||
|
||||
/* to enable Apple OS-native certificate verification */
|
||||
#cmakedefine USE_APPLE_SECTRUST 1
|
||||
|
||||
/* Define to 1 if OpenSSL has the SSL_CTX_set_srp_username function. */
|
||||
#cmakedefine HAVE_OPENSSL_SRP 1
|
||||
|
||||
|
||||
14
lib/setopt.c
14
lib/setopt.c
@ -2206,6 +2206,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
|
||||
/*
|
||||
* Set CA info for SSL connection. Specify filename of the CA certificate
|
||||
*/
|
||||
s->ssl.custom_cafile = TRUE;
|
||||
return Curl_setstropt(&s->str[STRING_SSL_CAFILE], ptr);
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
@ -2214,6 +2215,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
|
||||
* Set CA info SSL connection for proxy. Specify filename of the
|
||||
* CA certificate
|
||||
*/
|
||||
s->proxy_ssl.custom_cafile = TRUE;
|
||||
return Curl_setstropt(&s->str[STRING_SSL_CAFILE_PROXY], ptr);
|
||||
|
||||
#endif
|
||||
@ -2223,9 +2225,11 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
|
||||
* certificates which have been prepared using openssl c_rehash utility.
|
||||
*/
|
||||
#ifdef USE_SSL
|
||||
if(Curl_ssl_supports(data, SSLSUPP_CA_PATH))
|
||||
if(Curl_ssl_supports(data, SSLSUPP_CA_PATH)) {
|
||||
/* This does not work on Windows. */
|
||||
s->ssl.custom_capath = TRUE;
|
||||
return Curl_setstropt(&s->str[STRING_SSL_CAPATH], ptr);
|
||||
}
|
||||
#endif
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
@ -2235,9 +2239,11 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
|
||||
* CA certificates which have been prepared using openssl c_rehash utility.
|
||||
*/
|
||||
#ifdef USE_SSL
|
||||
if(Curl_ssl_supports(data, SSLSUPP_CA_PATH))
|
||||
if(Curl_ssl_supports(data, SSLSUPP_CA_PATH)) {
|
||||
/* This does not work on Windows. */
|
||||
s->proxy_ssl.custom_capath = TRUE;
|
||||
return Curl_setstropt(&s->str[STRING_SSL_CAPATH_PROXY], ptr);
|
||||
}
|
||||
#endif
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
#endif
|
||||
@ -2900,8 +2906,10 @@ static CURLcode setopt_blob(struct Curl_easy *data, CURLoption option,
|
||||
* Specify entire PEM of the CA certificate
|
||||
*/
|
||||
#ifdef USE_SSL
|
||||
if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
|
||||
if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) {
|
||||
s->ssl.custom_cablob = TRUE;
|
||||
return Curl_setblobopt(&s->blobs[BLOB_CAINFO], blob);
|
||||
}
|
||||
#endif
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
case CURLOPT_ISSUERCERT_BLOB:
|
||||
|
||||
30
lib/url.c
30
lib/url.c
@ -435,36 +435,6 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
|
||||
set->socks5_gssapi_nec = FALSE;
|
||||
#endif
|
||||
|
||||
/* Set the default CA cert bundle/path detected/specified at build time.
|
||||
*
|
||||
* If Schannel is the selected SSL backend then these locations are ignored.
|
||||
* We allow setting CA location for Schannel when explicitly specified by
|
||||
* the user via CURLOPT_CAINFO / --cacert.
|
||||
*/
|
||||
if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
|
||||
#ifdef CURL_CA_BUNDLE
|
||||
result = Curl_setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
|
||||
if(result)
|
||||
return result;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY],
|
||||
CURL_CA_BUNDLE);
|
||||
if(result)
|
||||
return result;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CURL_CA_PATH
|
||||
result = Curl_setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
|
||||
if(result)
|
||||
return result;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
|
||||
if(result)
|
||||
return result;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* set default minimum TLS version */
|
||||
#ifdef USE_SSL
|
||||
Curl_setopt_SSLVERSION(data, CURLOPT_SSLVERSION, CURL_SSLVERSION_DEFAULT);
|
||||
|
||||
@ -285,6 +285,9 @@ struct ssl_config_data {
|
||||
BIT(native_ca_store); /* use the native ca store of operating system */
|
||||
BIT(auto_client_cert); /* automatically locate and use a client
|
||||
certificate for authentication (Schannel) */
|
||||
BIT(custom_cafile); /* application has set custom CA file */
|
||||
BIT(custom_capath); /* application has set custom CA path */
|
||||
BIT(custom_cablob); /* application has set custom CA blob */
|
||||
};
|
||||
|
||||
struct ssl_general_config {
|
||||
|
||||
@ -130,7 +130,7 @@ CURLcode Curl_vquic_tls_before_recv(struct curl_tls_ctx *ctx,
|
||||
{
|
||||
#ifdef USE_OPENSSL
|
||||
if(!ctx->ossl.x509_store_setup) {
|
||||
CURLcode result = Curl_ssl_setup_x509_store(cf, data, ctx->ossl.ssl_ctx);
|
||||
CURLcode result = Curl_ssl_setup_x509_store(cf, data, &ctx->ossl);
|
||||
if(result)
|
||||
return result;
|
||||
ctx->ossl.x509_store_setup = TRUE;
|
||||
@ -170,7 +170,7 @@ CURLcode Curl_vquic_tls_verify_peer(struct curl_tls_ctx *ctx,
|
||||
result = Curl_ossl_check_peer_cert(cf, data, &ctx->ossl, peer);
|
||||
#elif defined(USE_GNUTLS)
|
||||
if(conn_config->verifyhost) {
|
||||
result = Curl_gtls_verifyserver(data, ctx->gtls.session,
|
||||
result = Curl_gtls_verifyserver(cf, data, ctx->gtls.session,
|
||||
conn_config, &data->set.ssl, peer,
|
||||
data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
|
||||
if(result)
|
||||
|
||||
297
lib/vtls/apple.c
Normal file
297
lib/vtls/apple.c
Normal file
@ -0,0 +1,297 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/* This file is for implementing all "generic" SSL functions that all libcurl
|
||||
internals should use. It is then responsible for calling the proper
|
||||
"backend" function.
|
||||
|
||||
SSL-functions in libcurl should call functions in this source file, and not
|
||||
to any specific SSL-layer.
|
||||
|
||||
Curl_ssl_ - prefix for generic ones
|
||||
|
||||
Note that this source code uses the functions of the configured SSL
|
||||
backend via the global Curl_ssl instance.
|
||||
|
||||
"SSL/TLS Strong Encryption: An Introduction"
|
||||
https://httpd.apache.org/docs/2.0/ssl/ssl_intro.html
|
||||
*/
|
||||
|
||||
#include "../curl_setup.h"
|
||||
|
||||
#include "../urldata.h"
|
||||
#include "../cfilters.h"
|
||||
#include "../curl_trc.h"
|
||||
#include "vtls.h"
|
||||
#include "apple.h"
|
||||
|
||||
#if defined(USE_SSL) && defined(USE_APPLE_SECTRUST)
|
||||
#include <Security/Security.h>
|
||||
#endif /* USE_SSL && USE_APPLE_SECTRUST */
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "../curl_memory.h"
|
||||
#include "../memdebug.h"
|
||||
|
||||
|
||||
#if defined(USE_SSL) && defined(USE_APPLE_SECTRUST)
|
||||
#define SSL_SYSTEM_VERIFIER
|
||||
|
||||
#if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) \
|
||||
&& MAC_OS_X_VERSION_MAX_ALLOWED >= 101400) \
|
||||
|| (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) \
|
||||
&& __IPHONE_OS_VERSION_MAX_ALLOWED >= 120000)
|
||||
#define SUPPORTS_SecTrustEvaluateWithError 1
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORTS_SecTrustEvaluateWithError) \
|
||||
&& ((defined(MAC_OS_X_VERSION_MIN_REQUIRED) \
|
||||
&& MAC_OS_X_VERSION_MIN_REQUIRED >= 101400) \
|
||||
|| (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) \
|
||||
&& __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000))
|
||||
#define REQUIRES_SecTrustEvaluateWithError 1
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORTS_SecTrustEvaluateWithError) \
|
||||
&& !defined(HAVE_BUILTIN_AVAILABLE) \
|
||||
&& !defined(REQUIRES_SecTrustEvaluateWithError)
|
||||
#undef SUPPORTS_SecTrustEvaluateWithError
|
||||
#endif
|
||||
|
||||
#if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) \
|
||||
&& MAC_OS_X_VERSION_MAX_ALLOWED >= 100900) \
|
||||
|| (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) \
|
||||
&& __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000)
|
||||
#define SUPPORTS_SecOCSP 1
|
||||
#endif
|
||||
|
||||
CURLcode Curl_vtls_apple_verify(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct ssl_peer *peer,
|
||||
size_t num_certs,
|
||||
Curl_vtls_get_cert_der *der_cb,
|
||||
void *cb_user_data,
|
||||
const unsigned char *ocsp_buf,
|
||||
size_t ocsp_len)
|
||||
{
|
||||
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
|
||||
CURLcode result = CURLE_OK;
|
||||
SecTrustRef trust = NULL;
|
||||
SecPolicyRef policy = NULL;
|
||||
CFMutableArrayRef policies = NULL;
|
||||
CFMutableArrayRef cert_array = NULL;
|
||||
CFStringRef host_str = NULL;
|
||||
CFErrorRef error = NULL;
|
||||
OSStatus status = noErr;
|
||||
CFStringRef error_ref = NULL;
|
||||
char *err_desc = NULL;
|
||||
size_t i;
|
||||
|
||||
if(conn_config->verifyhost) {
|
||||
host_str = CFStringCreateWithCString(NULL,
|
||||
peer->sni ? peer->sni : peer->hostname, kCFStringEncodingUTF8);
|
||||
if(!host_str) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
policies = CFArrayCreateMutable(NULL, 2, &kCFTypeArrayCallBacks);
|
||||
if(!policies) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
policy = SecPolicyCreateSSL(true, host_str);
|
||||
if(!policy) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
CFArrayAppendValue(policies, policy);
|
||||
CFRelease(policy);
|
||||
policy = NULL;
|
||||
|
||||
#if defined(HAVE_BUILTIN_AVAILABLE) && defined(SUPPORTS_SecOCSP)
|
||||
{
|
||||
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
|
||||
if(!ssl_config->no_revoke) {
|
||||
if(__builtin_available(macOS 10.9, iOS 7, tvOS 9, watchOS 2, *)) {
|
||||
/* Even without this set, validation will seemingly-unavoidably fail
|
||||
* for certificates that trustd already knows to be revoked.
|
||||
* This policy further allows trustd to consult CRLs and OCSP data
|
||||
* to determine revocation status (which it may then cache). */
|
||||
CFOptionFlags revocation_flags = kSecRevocationUseAnyAvailableMethod;
|
||||
#if 0
|
||||
/* `revoke_best_effort` is off by default in libcurl. When we
|
||||
* add `kSecRevocationRequirePositiveResponse` to the Apple
|
||||
* Trust policies, it interprets this as it NEEDs a confirmation
|
||||
* of a cert being NOT REVOKED. Which not in general available for
|
||||
* certificates on the internet.
|
||||
* It seems that applications using this policy are expected to PIN
|
||||
* their certificate public keys or verification will fail.
|
||||
* This does not seem to be what we want here. */
|
||||
if(!ssl_config->revoke_best_effort) {
|
||||
revocation_flags |= kSecRevocationRequirePositiveResponse;
|
||||
}
|
||||
#endif
|
||||
policy = SecPolicyCreateRevocation(revocation_flags);
|
||||
if(!policy) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
CFArrayAppendValue(policies, policy);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
cert_array = CFArrayCreateMutable(NULL, num_certs, &kCFTypeArrayCallBacks);
|
||||
if(!cert_array) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for(i = 0; i < num_certs; i++) {
|
||||
SecCertificateRef cert;
|
||||
CFDataRef certdata;
|
||||
unsigned char *der;
|
||||
size_t der_len;
|
||||
|
||||
result = der_cb(cf, data, cb_user_data, i, &der, &der_len);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
certdata = CFDataCreate(NULL, der, (CFIndex)der_len);
|
||||
if(!certdata) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cert = SecCertificateCreateWithData(NULL, certdata);
|
||||
CFRelease(certdata);
|
||||
if(!cert) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
CFArrayAppendValue(cert_array, cert);
|
||||
CFRelease(cert);
|
||||
}
|
||||
|
||||
status = SecTrustCreateWithCertificates(cert_array, policies, &trust);
|
||||
if(status != noErr || !trust) {
|
||||
failf(data, "Apple SecTrust: failed to create validation trust");
|
||||
result = CURLE_PEER_FAILED_VERIFICATION;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if defined(HAVE_BUILTIN_AVAILABLE) && defined(SUPPORTS_SecOCSP)
|
||||
if(ocsp_len > 0) {
|
||||
if(__builtin_available(macOS 10.9, iOS 7, tvOS 9, watchOS 2, *)) {
|
||||
CFDataRef ocspdata =
|
||||
CFDataCreate(NULL, ocsp_buf, (CFIndex)ocsp_len);
|
||||
|
||||
status = SecTrustSetOCSPResponse(trust, ocspdata);
|
||||
CFRelease(ocspdata);
|
||||
if(status != noErr) {
|
||||
failf(data, "Apple SecTrust: failed to set OCSP response: %i",
|
||||
(int)status);
|
||||
result = CURLE_PEER_FAILED_VERIFICATION;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)ocsp_buf;
|
||||
(void)ocsp_len;
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORTS_SecTrustEvaluateWithError
|
||||
#if defined(HAVE_BUILTIN_AVAILABLE)
|
||||
if(__builtin_available(macOS 10.14, iOS 12, tvOS 12, watchOS 5, *)) {
|
||||
#else
|
||||
if(1) {
|
||||
#endif
|
||||
result = SecTrustEvaluateWithError(trust, &error) ?
|
||||
CURLE_OK : CURLE_PEER_FAILED_VERIFICATION;
|
||||
if(error) {
|
||||
CFIndex code = CFErrorGetCode(error);
|
||||
error_ref = CFErrorCopyDescription(error);
|
||||
|
||||
if(error_ref) {
|
||||
CFIndex size = CFStringGetMaximumSizeForEncoding(
|
||||
CFStringGetLength(error_ref), kCFStringEncodingUTF8);
|
||||
err_desc = malloc(size + 1);
|
||||
if(err_desc) {
|
||||
if(!CFStringGetCString(error_ref, err_desc, size,
|
||||
kCFStringEncodingUTF8)) {
|
||||
free(err_desc);
|
||||
err_desc = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
infof(data, "Apple SecTrust failure %ld%s%s", code,
|
||||
err_desc ? ": " : "", err_desc ? err_desc : "");
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* SUPPORTS_SecTrustEvaluateWithError */
|
||||
{
|
||||
#ifndef REQUIRES_SecTrustEvaluateWithError
|
||||
SecTrustResultType sec_result;
|
||||
status = SecTrustEvaluate(trust, &sec_result);
|
||||
|
||||
if(status != noErr) {
|
||||
failf(data, "Apple SecTrust verification failed: error %i", (int)status);
|
||||
}
|
||||
else if((status == kSecTrustResultUnspecified) ||
|
||||
(status == kSecTrustResultProceed)) {
|
||||
/* "unspecified" means system-trusted with no explicit user setting */
|
||||
result = CURLE_OK;
|
||||
}
|
||||
#endif /* REQUIRES_SecTrustEvaluateWithError */
|
||||
}
|
||||
|
||||
out:
|
||||
free(err_desc);
|
||||
if(error_ref)
|
||||
CFRelease(error_ref);
|
||||
if(error)
|
||||
CFRelease(error);
|
||||
if(host_str)
|
||||
CFRelease(host_str);
|
||||
if(policies)
|
||||
CFRelease(policies);
|
||||
if(policy)
|
||||
CFRelease(policy);
|
||||
if(cert_array)
|
||||
CFRelease(cert_array);
|
||||
if(trust)
|
||||
CFRelease(trust);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* USE_SSL && USE_APPLE_SECTRUST */
|
||||
55
lib/vtls/apple.h
Normal file
55
lib/vtls/apple.h
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef HEADER_CURL_VTLS_APPLE_H
|
||||
#define HEADER_CURL_VTLS_APPLE_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Jan Venekamp, <jan@venekamp.net>
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "../curl_setup.h"
|
||||
|
||||
#if defined(USE_SSL) && defined(USE_APPLE_SECTRUST)
|
||||
struct Curl_cfilter;
|
||||
struct Curl_easy;
|
||||
struct ssl_peer;
|
||||
|
||||
/* Get the DER encoded i-th certificate in the server handshake */
|
||||
typedef CURLcode Curl_vtls_get_cert_der(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
void *user_data,
|
||||
size_t i,
|
||||
unsigned char **pder,
|
||||
size_t *pder_len);
|
||||
|
||||
/* Ask Apple's Security framework to verify the certificate chain
|
||||
* send by the peer. On CURLE_OK it has been verified.
|
||||
*/
|
||||
CURLcode Curl_vtls_apple_verify(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct ssl_peer *peer,
|
||||
size_t num_certs,
|
||||
Curl_vtls_get_cert_der *der_cb,
|
||||
void *cb_user_data,
|
||||
const unsigned char *ocsp_buf,
|
||||
size_t ocsp_len);
|
||||
#endif /* USE_SSL && USE_APPLE_SECTRUST */
|
||||
|
||||
#endif /* HEADER_CURL_VTLS_APPLE_H */
|
||||
386
lib/vtls/gtls.c
386
lib/vtls/gtls.c
@ -48,6 +48,7 @@
|
||||
#include "vtls.h"
|
||||
#include "vtls_int.h"
|
||||
#include "vtls_scache.h"
|
||||
#include "apple.h"
|
||||
#include "../vauth/vauth.h"
|
||||
#include "../parsedate.h"
|
||||
#include "../connect.h" /* for the connect timeout */
|
||||
@ -454,62 +455,75 @@ static CURLcode gtls_populate_creds(struct Curl_cfilter *cf,
|
||||
{
|
||||
struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
|
||||
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
|
||||
bool creds_are_empty = TRUE;
|
||||
int rc;
|
||||
|
||||
if(config->verifypeer) {
|
||||
bool imported_native_ca = FALSE;
|
||||
|
||||
if(ssl_config->native_ca_store) {
|
||||
rc = gnutls_certificate_set_x509_system_trust(creds);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if(config->CAfile) {
|
||||
/* set the trusted CA cert bundle file */
|
||||
gnutls_certificate_set_verify_flags(creds,
|
||||
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
|
||||
|
||||
rc = gnutls_certificate_set_x509_trust_file(creds,
|
||||
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) {
|
||||
ssl_config->certverifyresult = rc;
|
||||
return CURLE_SSL_CACERT_BADFILE;
|
||||
}
|
||||
}
|
||||
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(creds, 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) {
|
||||
ssl_config->certverifyresult = rc;
|
||||
return CURLE_SSL_CACERT_BADFILE;
|
||||
}
|
||||
}
|
||||
else
|
||||
infof(data, "found %d certificates in %s", rc, config->CApath);
|
||||
}
|
||||
if(!config->verifypeer) {
|
||||
infof(data, "SSL Trust: peer verification disabled");
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
infof(data, "SSL Trust Anchors:");
|
||||
if(ssl_config->native_ca_store) {
|
||||
#ifdef USE_APPLE_SECTRUST
|
||||
infof(data, " Native: Apple SecTrust");
|
||||
creds_are_empty = FALSE;
|
||||
#else
|
||||
rc = gnutls_certificate_set_x509_system_trust(creds);
|
||||
if(rc < 0)
|
||||
infof(data, "error reading native ca store (%s), continuing anyway",
|
||||
gnutls_strerror(rc));
|
||||
else {
|
||||
infof(data, " Native: %d certificates from system trust", rc);
|
||||
if(rc > 0)
|
||||
creds_are_empty = FALSE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if(config->CAfile) {
|
||||
/* set the trusted CA cert bundle file */
|
||||
gnutls_certificate_set_verify_flags(creds,
|
||||
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
|
||||
|
||||
rc = gnutls_certificate_set_x509_trust_file(creds,
|
||||
config->CAfile,
|
||||
GNUTLS_X509_FMT_PEM);
|
||||
creds_are_empty = creds_are_empty && (rc <= 0);
|
||||
if(rc < 0) {
|
||||
infof(data, "error reading ca cert file %s (%s)%s",
|
||||
config->CAfile, gnutls_strerror(rc),
|
||||
(creds_are_empty ? "" : ", continuing anyway"));
|
||||
if(creds_are_empty) {
|
||||
ssl_config->certverifyresult = rc;
|
||||
return CURLE_SSL_CACERT_BADFILE;
|
||||
}
|
||||
}
|
||||
else
|
||||
infof(data, " CAfile: %d certificates in %s", rc, config->CAfile);
|
||||
}
|
||||
|
||||
if(config->CApath) {
|
||||
/* set the trusted CA cert directory */
|
||||
rc = gnutls_certificate_set_x509_trust_dir(creds, config->CApath,
|
||||
GNUTLS_X509_FMT_PEM);
|
||||
creds_are_empty = creds_are_empty && (rc <= 0);
|
||||
if(rc < 0) {
|
||||
infof(data, "error reading ca cert file %s (%s)%s",
|
||||
config->CApath, gnutls_strerror(rc),
|
||||
(creds_are_empty ? "" : ", continuing anyway"));
|
||||
if(creds_are_empty) {
|
||||
ssl_config->certverifyresult = rc;
|
||||
return CURLE_SSL_CACERT_BADFILE;
|
||||
}
|
||||
}
|
||||
else
|
||||
infof(data, " CApath: %d certificates in %s", rc, config->CApath);
|
||||
}
|
||||
|
||||
if(creds_are_empty)
|
||||
infof(data, " no trust anchors configured");
|
||||
|
||||
if(config->CRLfile) {
|
||||
/* set the CRL list file */
|
||||
rc = gnutls_certificate_set_x509_crl_file(creds, config->CRLfile,
|
||||
@ -520,7 +534,7 @@ static CURLcode gtls_populate_creds(struct Curl_cfilter *cf,
|
||||
return CURLE_SSL_CRL_BADFILE;
|
||||
}
|
||||
else
|
||||
infof(data, "found %d CRL in %s", rc, config->CRLfile);
|
||||
infof(data, " CRLfile: %d CRL in %s", rc, config->CRLfile);
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
@ -1520,31 +1534,76 @@ out:
|
||||
return result;
|
||||
}
|
||||
|
||||
struct gtls_cert_chain {
|
||||
const gnutls_datum_t *certs;
|
||||
unsigned int num_certs;
|
||||
};
|
||||
|
||||
#ifdef USE_APPLE_SECTRUST
|
||||
static CURLcode gtls_chain_get_der(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
void *user_data,
|
||||
size_t i,
|
||||
unsigned char **pder,
|
||||
size_t *pder_len)
|
||||
{
|
||||
struct gtls_cert_chain *chain = user_data;
|
||||
|
||||
(void)cf;
|
||||
(void)data;
|
||||
*pder_len = 0;
|
||||
*pder = NULL;
|
||||
|
||||
if(i >= chain->num_certs)
|
||||
return CURLE_TOO_LARGE;
|
||||
*pder = chain->certs[i].data;
|
||||
*pder_len = (size_t)chain->certs[i].size;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode glts_apple_verify(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct ssl_peer *peer,
|
||||
struct gtls_cert_chain *chain,
|
||||
bool *pverified)
|
||||
{
|
||||
CURLcode result;
|
||||
|
||||
result = Curl_vtls_apple_verify(cf, data, peer, chain->num_certs,
|
||||
gtls_chain_get_der, chain,
|
||||
NULL, 0);
|
||||
*pverified = !result;
|
||||
if(*pverified)
|
||||
infof(data, " SSL certificate verified by Apple SecTrust.");
|
||||
return result;
|
||||
}
|
||||
#endif /* USE_APPLE_SECTRUST */
|
||||
|
||||
CURLcode
|
||||
Curl_gtls_verifyserver(struct Curl_easy *data,
|
||||
Curl_gtls_verifyserver(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
gnutls_session_t session,
|
||||
struct ssl_primary_config *config,
|
||||
struct ssl_config_data *ssl_config,
|
||||
struct ssl_peer *peer,
|
||||
const char *pinned_key)
|
||||
{
|
||||
unsigned int cert_list_size;
|
||||
const gnutls_datum_t *chainp;
|
||||
unsigned int verify_status = 0;
|
||||
struct gtls_cert_chain chain;
|
||||
gnutls_x509_crt_t x509_cert = NULL, x509_issuer = NULL;
|
||||
time_t certclock;
|
||||
int rc;
|
||||
CURLcode result = CURLE_OK;
|
||||
long * const certverifyresult = &ssl_config->certverifyresult;
|
||||
|
||||
(void)cf;
|
||||
/* This function will return the peer's raw certificate (chain) as sent by
|
||||
the peer. These certificates are in raw format (DER encoded for
|
||||
X.509). In case of a X.509 then a certificate list may be present. The
|
||||
first certificate in the list is the peer's certificate, following the
|
||||
issuer's certificate, then the issuer's issuer etc. */
|
||||
|
||||
chainp = gnutls_certificate_get_peers(session, &cert_list_size);
|
||||
if(!chainp) {
|
||||
chain.certs = gnutls_certificate_get_peers(session, &chain.num_certs);
|
||||
if(!chain.certs) {
|
||||
if(config->verifypeer ||
|
||||
config->verifyhost ||
|
||||
config->issuercert) {
|
||||
@ -1567,16 +1626,16 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
|
||||
infof(data, " common name: WARNING could not obtain");
|
||||
}
|
||||
|
||||
if(data->set.ssl.certinfo && chainp) {
|
||||
if(data->set.ssl.certinfo && chain.certs) {
|
||||
unsigned int i;
|
||||
|
||||
result = Curl_ssl_init_certinfo(data, (int)cert_list_size);
|
||||
result = Curl_ssl_init_certinfo(data, (int)chain.num_certs);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
for(i = 0; i < cert_list_size; i++) {
|
||||
const char *beg = (const char *) chainp[i].data;
|
||||
const char *end = beg + chainp[i].size;
|
||||
for(i = 0; i < chain.num_certs; i++) {
|
||||
const char *beg = (const char *) chain.certs[i].data;
|
||||
const char *end = beg + chain.certs[i].size;
|
||||
|
||||
result = Curl_extract_certinfo(data, (int)i, beg, end);
|
||||
if(result)
|
||||
@ -1585,13 +1644,15 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
if(config->verifypeer) {
|
||||
/* This function will try to verify the peer's certificate and return its
|
||||
status (trusted, invalid etc.). The value of status should be one or
|
||||
more of the gnutls_certificate_status_t enumerated elements bitwise
|
||||
or'd. To avoid denial of service attacks some default upper limits
|
||||
regarding the certificate key size and chain size are set. To override
|
||||
them use gnutls_certificate_set_verify_limits(). */
|
||||
|
||||
bool verified = FALSE;
|
||||
unsigned int verify_status = 0;
|
||||
/* This function will try to verify the peer's certificate and return
|
||||
its status (trusted, invalid etc.). The value of status should be
|
||||
one or more of the gnutls_certificate_status_t enumerated elements
|
||||
bitwise or'd. To avoid denial of service attacks some default
|
||||
upper limits regarding the certificate key size and chain size
|
||||
are set. To override them use
|
||||
gnutls_certificate_set_verify_limits(). */
|
||||
rc = gnutls_certificate_verify_peers2(session, &verify_status);
|
||||
if(rc < 0) {
|
||||
failf(data, "server cert verify failed: %d", rc);
|
||||
@ -1599,37 +1660,109 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*certverifyresult = verify_status;
|
||||
verified = !(verify_status & GNUTLS_CERT_INVALID);
|
||||
if(verified)
|
||||
infof(data, " SSL certificate verified by GnuTLS");
|
||||
|
||||
/* verify_status is a bitmask of gnutls_certificate_status bits */
|
||||
if(verify_status & GNUTLS_CERT_INVALID) {
|
||||
#ifdef USE_APPLE_SECTRUST
|
||||
if(!verified && ssl_config->native_ca_store &&
|
||||
(verify_status & GNUTLS_CERT_SIGNER_NOT_FOUND)) {
|
||||
result = glts_apple_verify(cf, data, peer, &chain, &verified);
|
||||
if(result && (result != CURLE_PEER_FAILED_VERIFICATION))
|
||||
goto out; /* unexpected error */
|
||||
if(verified) {
|
||||
infof(data, "SSL certificate verified via Apple SecTrust.");
|
||||
*certverifyresult = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!verified) {
|
||||
/* verify_status is a bitmask of gnutls_certificate_status bits */
|
||||
const char *cause = "certificate error, no details available";
|
||||
if(verify_status & GNUTLS_CERT_EXPIRED)
|
||||
cause = "certificate has expired";
|
||||
else if(verify_status & GNUTLS_CERT_SIGNER_NOT_FOUND)
|
||||
cause = "certificate signer not trusted";
|
||||
else if(verify_status & GNUTLS_CERT_INSECURE_ALGORITHM)
|
||||
cause = "certificate uses insecure algorithm";
|
||||
else if(verify_status & GNUTLS_CERT_INVALID_OCSP_STATUS)
|
||||
cause = "attached OCSP status response is invalid";
|
||||
failf(data, "SSL certificate verification failed: %s. (CAfile: %s "
|
||||
"CRLfile: %s)", cause,
|
||||
config->CAfile ? config->CAfile : "none",
|
||||
ssl_config->primary.CRLfile ?
|
||||
ssl_config->primary.CRLfile : "none");
|
||||
result = CURLE_PEER_FAILED_VERIFICATION;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else
|
||||
infof(data, " SSL certificate verification SKIPPED");
|
||||
|
||||
/* initialize an X.509 certificate structure. */
|
||||
gnutls_x509_crt_init(&x509_cert);
|
||||
|
||||
if(chain.certs)
|
||||
/* convert the given DER or PEM encoded Certificate to the native
|
||||
gnutls_x509_crt_t format */
|
||||
gnutls_x509_crt_import(x509_cert, chain.certs, GNUTLS_X509_FMT_DER);
|
||||
|
||||
/* Check for time-based validity */
|
||||
certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
|
||||
|
||||
if(certclock == (time_t)-1) {
|
||||
if(config->verifypeer) {
|
||||
failf(data, "server cert expiration date verify failed");
|
||||
*certverifyresult = GNUTLS_CERT_EXPIRED;
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
infof(data, " SSL certificate expiration date verify FAILED");
|
||||
}
|
||||
else {
|
||||
if(certclock < time(NULL)) {
|
||||
if(config->verifypeer) {
|
||||
const char *cause = "certificate error, no details available";
|
||||
if(verify_status & GNUTLS_CERT_EXPIRED)
|
||||
cause = "certificate has expired";
|
||||
else if(verify_status & GNUTLS_CERT_SIGNER_NOT_FOUND)
|
||||
cause = "certificate signer not trusted";
|
||||
else if(verify_status & GNUTLS_CERT_INSECURE_ALGORITHM)
|
||||
cause = "certificate uses insecure algorithm";
|
||||
else if(verify_status & GNUTLS_CERT_INVALID_OCSP_STATUS)
|
||||
cause = "attached OCSP status response is invalid";
|
||||
failf(data, "server verification failed: %s. (CAfile: %s "
|
||||
"CRLfile: %s)", cause,
|
||||
config->CAfile ? config->CAfile : "none",
|
||||
ssl_config->primary.CRLfile ?
|
||||
ssl_config->primary.CRLfile : "none");
|
||||
failf(data, "server certificate expiration date has passed.");
|
||||
*certverifyresult = GNUTLS_CERT_EXPIRED;
|
||||
result = CURLE_PEER_FAILED_VERIFICATION;
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
infof(data, " server certificate verification FAILED");
|
||||
infof(data, " SSL certificate expiration date FAILED");
|
||||
}
|
||||
else
|
||||
infof(data, " server certificate verification OK");
|
||||
infof(data, " SSL certificate expiration date OK");
|
||||
}
|
||||
|
||||
certclock = gnutls_x509_crt_get_activation_time(x509_cert);
|
||||
|
||||
if(certclock == (time_t)-1) {
|
||||
if(config->verifypeer) {
|
||||
failf(data, "server cert activation date verify failed");
|
||||
*certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
infof(data, " SSL certificate activation date verify FAILED");
|
||||
}
|
||||
else {
|
||||
if(certclock > time(NULL)) {
|
||||
if(config->verifypeer) {
|
||||
failf(data, "server certificate not activated yet.");
|
||||
*certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
|
||||
result = CURLE_PEER_FAILED_VERIFICATION;
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
infof(data, " SSL certificate activation date FAILED");
|
||||
}
|
||||
else
|
||||
infof(data, " SSL certificate activation date OK");
|
||||
}
|
||||
else
|
||||
infof(data, " server certificate verification SKIPPED");
|
||||
|
||||
if(config->verifystatus) {
|
||||
result = gtls_verify_ocsp_status(data, session);
|
||||
@ -1637,15 +1770,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
infof(data, " server certificate status verification SKIPPED");
|
||||
|
||||
/* initialize an X.509 certificate structure. */
|
||||
gnutls_x509_crt_init(&x509_cert);
|
||||
|
||||
if(chainp)
|
||||
/* convert the given DER or PEM encoded Certificate to the native
|
||||
gnutls_x509_crt_t format */
|
||||
gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
|
||||
infof(data, " SSL certificate status verification SKIPPED");
|
||||
|
||||
if(config->issuercert) {
|
||||
gnutls_datum_t issuerp;
|
||||
@ -1660,7 +1785,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
|
||||
result = CURLE_SSL_ISSUER_ERROR;
|
||||
goto out;
|
||||
}
|
||||
infof(data, " server certificate issuer check OK (Issuer Cert: %s)",
|
||||
infof(data, " SSL certificate issuer check OK (Issuer Cert: %s)",
|
||||
config->issuercert ? config->issuercert : "none");
|
||||
}
|
||||
|
||||
@ -1725,61 +1850,6 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
/* Check for time-based validity */
|
||||
certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
|
||||
|
||||
if(certclock == (time_t)-1) {
|
||||
if(config->verifypeer) {
|
||||
failf(data, "server cert expiration date verify failed");
|
||||
*certverifyresult = GNUTLS_CERT_EXPIRED;
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
infof(data, " server certificate expiration date verify FAILED");
|
||||
}
|
||||
else {
|
||||
if(certclock < time(NULL)) {
|
||||
if(config->verifypeer) {
|
||||
failf(data, "server certificate expiration date has passed.");
|
||||
*certverifyresult = GNUTLS_CERT_EXPIRED;
|
||||
result = CURLE_PEER_FAILED_VERIFICATION;
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
infof(data, " server certificate expiration date FAILED");
|
||||
}
|
||||
else
|
||||
infof(data, " server certificate expiration date OK");
|
||||
}
|
||||
|
||||
certclock = gnutls_x509_crt_get_activation_time(x509_cert);
|
||||
|
||||
if(certclock == (time_t)-1) {
|
||||
if(config->verifypeer) {
|
||||
failf(data, "server cert activation date verify failed");
|
||||
*certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
infof(data, " server certificate activation date verify FAILED");
|
||||
}
|
||||
else {
|
||||
if(certclock > time(NULL)) {
|
||||
if(config->verifypeer) {
|
||||
failf(data, "server certificate not activated yet.");
|
||||
*certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
|
||||
result = CURLE_PEER_FAILED_VERIFICATION;
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
infof(data, " server certificate activation date FAILED");
|
||||
}
|
||||
else
|
||||
infof(data, " server certificate activation date OK");
|
||||
}
|
||||
|
||||
if(pinned_key) {
|
||||
result = pkp_pin_peer_pubkey(data, x509_cert, pinned_key);
|
||||
if(result != CURLE_OK) {
|
||||
@ -1814,7 +1884,7 @@ static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
|
||||
#endif
|
||||
CURLcode result;
|
||||
|
||||
result = Curl_gtls_verifyserver(data, session, conn_config, ssl_config,
|
||||
result = Curl_gtls_verifyserver(cf, data, session, conn_config, ssl_config,
|
||||
&connssl->peer, pinned_key);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
@ -100,7 +100,8 @@ CURLcode Curl_gtls_client_trust_setup(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct gtls_ctx *gtls);
|
||||
|
||||
CURLcode Curl_gtls_verifyserver(struct Curl_easy *data,
|
||||
CURLcode Curl_gtls_verifyserver(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
gnutls_session_t session,
|
||||
struct ssl_primary_config *config,
|
||||
struct ssl_config_data *ssl_config,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -71,7 +71,6 @@ struct ossl_ctx {
|
||||
/* these ones requires specific SSL-types */
|
||||
SSL_CTX* ssl_ctx;
|
||||
SSL* ssl;
|
||||
X509* server_cert;
|
||||
BIO_METHOD *bio_method;
|
||||
CURLcode io_result; /* result of last BIO cfilter operation */
|
||||
/* blocked writes need to retry with same length, remember it */
|
||||
@ -82,6 +81,7 @@ struct ossl_ctx {
|
||||
bool keylog_done;
|
||||
#endif
|
||||
BIT(x509_store_setup); /* x509 store has been set up */
|
||||
BIT(store_is_empty); /* no certs/paths/blobs in x509 store */
|
||||
BIT(reused_session); /* session-ID was reused for this */
|
||||
};
|
||||
|
||||
@ -122,7 +122,7 @@ extern const struct Curl_ssl Curl_ssl_openssl;
|
||||
*/
|
||||
CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
SSL_CTX *ssl_ctx);
|
||||
struct ossl_ctx *octx);
|
||||
|
||||
CURLcode Curl_ossl_ctx_configure(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
|
||||
147
lib/vtls/vtls.c
147
lib/vtls/vtls.c
@ -75,9 +75,14 @@
|
||||
#include "../curlx/inet_pton.h"
|
||||
#include "../connect.h"
|
||||
#include "../select.h"
|
||||
#include "../setopt.h"
|
||||
#include "../strdup.h"
|
||||
#include "../rand.h"
|
||||
|
||||
#ifdef USE_APPLE_SECTRUST
|
||||
#include <Security/Security.h>
|
||||
#endif /* USE_APPLE_SECTRUST */
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "../curl_memory.h"
|
||||
#include "../memdebug.h"
|
||||
@ -290,62 +295,100 @@ static void free_primary_ssl_config(struct ssl_primary_config *sslc)
|
||||
|
||||
CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data)
|
||||
{
|
||||
data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH];
|
||||
data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
|
||||
data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE];
|
||||
data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
|
||||
data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
|
||||
data->set.ssl.primary.cipher_list =
|
||||
data->set.str[STRING_SSL_CIPHER_LIST];
|
||||
data->set.ssl.primary.cipher_list13 =
|
||||
data->set.str[STRING_SSL_CIPHER13_LIST];
|
||||
data->set.ssl.primary.signature_algorithms =
|
||||
data->set.str[STRING_SSL_SIGNATURE_ALGORITHMS];
|
||||
data->set.ssl.primary.pinned_key =
|
||||
data->set.str[STRING_SSL_PINNEDPUBLICKEY];
|
||||
data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT];
|
||||
data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
|
||||
data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES];
|
||||
#ifdef USE_TLS_SRP
|
||||
data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME];
|
||||
data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD];
|
||||
struct ssl_config_data *sslc = &data->set.ssl;
|
||||
#if defined(CURL_CA_PATH) || defined(CURL_CA_BUNDLE)
|
||||
struct UserDefined *set = &data->set;
|
||||
CURLcode result;
|
||||
#endif
|
||||
data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
|
||||
data->set.ssl.key = data->set.str[STRING_KEY];
|
||||
data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
|
||||
data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD];
|
||||
data->set.ssl.primary.clientcert = data->set.str[STRING_CERT];
|
||||
data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
|
||||
|
||||
if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
|
||||
#ifdef USE_APPLE_SECTRUST
|
||||
if(!sslc->custom_capath && !sslc->custom_cafile && !sslc->custom_cablob)
|
||||
sslc->native_ca_store = TRUE;
|
||||
#endif
|
||||
#ifdef CURL_CA_PATH
|
||||
if(!sslc->custom_capath && !set->str[STRING_SSL_CAPATH]) {
|
||||
result = Curl_setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
sslc->primary.CApath = data->set.str[STRING_SSL_CAPATH];
|
||||
#endif
|
||||
#ifdef CURL_CA_BUNDLE
|
||||
if(!sslc->custom_cafile && !set->str[STRING_SSL_CAFILE]) {
|
||||
result = Curl_setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
sslc->primary.CAfile = data->set.str[STRING_SSL_CAFILE];
|
||||
sslc->primary.CRLfile = data->set.str[STRING_SSL_CRLFILE];
|
||||
sslc->primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
|
||||
sslc->primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
|
||||
sslc->primary.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
|
||||
sslc->primary.cipher_list13 = data->set.str[STRING_SSL_CIPHER13_LIST];
|
||||
sslc->primary.signature_algorithms =
|
||||
data->set.str[STRING_SSL_SIGNATURE_ALGORITHMS];
|
||||
sslc->primary.pinned_key =
|
||||
data->set.str[STRING_SSL_PINNEDPUBLICKEY];
|
||||
sslc->primary.cert_blob = data->set.blobs[BLOB_CERT];
|
||||
sslc->primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
|
||||
sslc->primary.curves = data->set.str[STRING_SSL_EC_CURVES];
|
||||
#ifdef USE_TLS_SRP
|
||||
sslc->primary.username = data->set.str[STRING_TLSAUTH_USERNAME];
|
||||
sslc->primary.password = data->set.str[STRING_TLSAUTH_PASSWORD];
|
||||
#endif
|
||||
sslc->cert_type = data->set.str[STRING_CERT_TYPE];
|
||||
sslc->key = data->set.str[STRING_KEY];
|
||||
sslc->key_type = data->set.str[STRING_KEY_TYPE];
|
||||
sslc->key_passwd = data->set.str[STRING_KEY_PASSWD];
|
||||
sslc->primary.clientcert = data->set.str[STRING_CERT];
|
||||
sslc->key_blob = data->set.blobs[BLOB_KEY];
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
|
||||
data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
|
||||
data->set.proxy_ssl.primary.cipher_list =
|
||||
data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
|
||||
data->set.proxy_ssl.primary.cipher_list13 =
|
||||
data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
|
||||
data->set.proxy_ssl.primary.pinned_key =
|
||||
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
|
||||
data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
|
||||
data->set.proxy_ssl.primary.ca_info_blob =
|
||||
data->set.blobs[BLOB_CAINFO_PROXY];
|
||||
data->set.proxy_ssl.primary.issuercert =
|
||||
data->set.str[STRING_SSL_ISSUERCERT_PROXY];
|
||||
data->set.proxy_ssl.primary.issuercert_blob =
|
||||
data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
|
||||
data->set.proxy_ssl.primary.CRLfile =
|
||||
data->set.str[STRING_SSL_CRLFILE_PROXY];
|
||||
data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
|
||||
data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
|
||||
data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
|
||||
data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
|
||||
data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
|
||||
data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
|
||||
sslc = &data->set.proxy_ssl;
|
||||
if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
|
||||
#ifdef USE_APPLE_SECTRUST
|
||||
if(!sslc->custom_capath && !sslc->custom_cafile && !sslc->custom_cablob)
|
||||
sslc->native_ca_store = TRUE;
|
||||
#endif
|
||||
#ifdef CURL_CA_PATH
|
||||
if(!sslc->custom_capath && !set->str[STRING_SSL_CAPATH_PROXY]) {
|
||||
result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY],
|
||||
CURL_CA_PATH);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
sslc->primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
|
||||
#endif
|
||||
#ifdef CURL_CA_BUNDLE
|
||||
if(!sslc->custom_cafile && !set->str[STRING_SSL_CAFILE_PROXY]) {
|
||||
result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY],
|
||||
CURL_CA_BUNDLE);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
sslc->primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
|
||||
sslc->primary.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
|
||||
sslc->primary.cipher_list13 = data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
|
||||
sslc->primary.pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
|
||||
sslc->primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
|
||||
sslc->primary.ca_info_blob = data->set.blobs[BLOB_CAINFO_PROXY];
|
||||
sslc->primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
|
||||
sslc->primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
|
||||
sslc->primary.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
|
||||
sslc->cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
|
||||
sslc->key = data->set.str[STRING_KEY_PROXY];
|
||||
sslc->key_type = data->set.str[STRING_KEY_TYPE_PROXY];
|
||||
sslc->key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
|
||||
sslc->primary.clientcert = data->set.str[STRING_CERT_PROXY];
|
||||
sslc->key_blob = data->set.blobs[BLOB_KEY_PROXY];
|
||||
#ifdef USE_TLS_SRP
|
||||
data->set.proxy_ssl.primary.username =
|
||||
data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
|
||||
data->set.proxy_ssl.primary.password =
|
||||
data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
|
||||
sslc->primary.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
|
||||
sslc->primary.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
|
||||
#endif
|
||||
#endif /* CURL_DISABLE_PROXY */
|
||||
|
||||
|
||||
@ -371,7 +371,7 @@ void Curl_ssl_scache_unlock(struct Curl_easy *data)
|
||||
|
||||
static CURLcode cf_ssl_peer_key_add_path(struct dynbuf *buf,
|
||||
const char *name,
|
||||
char *path,
|
||||
const char *path,
|
||||
bool *is_local)
|
||||
{
|
||||
if(path && path[0]) {
|
||||
|
||||
58
m4/curl-apple-sectrust.m4
Normal file
58
m4/curl-apple-sectrust.m4
Normal file
@ -0,0 +1,58 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at https://curl.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
#***************************************************************************
|
||||
|
||||
AC_DEFUN([CURL_WITH_APPLE_SECTRUST], [
|
||||
AC_MSG_CHECKING([whether to enable Apple OS native certificate validation])
|
||||
if test "x$OPT_APPLE_SECTRUST" = xyes; then
|
||||
AC_COMPILE_IFELSE([
|
||||
AC_LANG_PROGRAM([[
|
||||
#include <sys/types.h>
|
||||
#include <TargetConditionals.h>
|
||||
]],[[
|
||||
#if TARGET_OS_MAC
|
||||
return 0;
|
||||
#else
|
||||
#error Not macOS
|
||||
#endif
|
||||
]])
|
||||
],[
|
||||
build_for_apple="yes"
|
||||
],[
|
||||
build_for_apple="no"
|
||||
])
|
||||
if test "x$build_for_apple" != "xno"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(USE_APPLE_SECTRUST, 1, [enable Apple OS certificate validation])
|
||||
APPLE_SECTRUST_ENABLED=1
|
||||
APPLE_SECTRUST_LDFLAGS='-framework CoreFoundation -framework CoreServices -framework Security'
|
||||
LDFLAGS="$LDFLAGS $APPLE_SECTRUST_LDFLAGS"
|
||||
LDFLAGSPC="$LDFLAGSPC $APPLE_SECTRUST_LDFLAGS"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
])
|
||||
@ -19,7 +19,7 @@ https
|
||||
insecure HTTPS without permission
|
||||
</name>
|
||||
<command>
|
||||
https://%HOSTIP:%HTTPSPORT/want/%TESTNUMBER --cacert moooo
|
||||
https://%HOSTIP:%HTTPSPORT/want/%TESTNUMBER --cacert moooo --no-ca-native
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
||||
@ -610,6 +610,8 @@ class TestDownload:
|
||||
pytest.skip("h3 not supported")
|
||||
if proto != 'h3' and sys.platform.startswith('darwin') and env.ci_run:
|
||||
pytest.skip('failing on macOS CI runners')
|
||||
if proto == 'h3' and sys.platform.startswith('darwin') and env.curl_uses_lib('gnutls'):
|
||||
pytest.skip('h3 gnutls early data failing on macOS')
|
||||
count = 2
|
||||
docname = 'data-10k'
|
||||
# we want this test to always connect to nghttpx, since it is
|
||||
|
||||
@ -693,6 +693,8 @@ class TestUpload:
|
||||
pytest.skip("h3 not supported")
|
||||
if proto != 'h3' and sys.platform.startswith('darwin') and env.ci_run:
|
||||
pytest.skip('failing on macOS CI runners')
|
||||
if proto == 'h3' and sys.platform.startswith('darwin') and env.curl_uses_lib('gnutls'):
|
||||
pytest.skip('h3 gnutls early data failing on macOS')
|
||||
count = 2
|
||||
# we want this test to always connect to nghttpx, since it is
|
||||
# the only server we have that supports TLS earlydata
|
||||
|
||||
@ -433,9 +433,9 @@ class TestSSLUse:
|
||||
exp_trace = None
|
||||
match_trace = None
|
||||
if env.curl_uses_lib('openssl') or env.curl_uses_lib('quictls'):
|
||||
exp_trace = r'.*SSL certificate problem: certificate has expired$'
|
||||
exp_trace = r'.*SSL certificate OpenSSL verify result: certificate has expired.*$'
|
||||
elif env.curl_uses_lib('gnutls'):
|
||||
exp_trace = r'.*server verification failed: certificate has expired\..*'
|
||||
exp_trace = r'.*SSL certificate verification failed: certificate has expired\..*'
|
||||
elif env.curl_uses_lib('wolfssl'):
|
||||
exp_trace = r'.*server verification failed: certificate has expired\.$'
|
||||
if exp_trace is not None:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user