diff --git a/CMakeLists.txt b/CMakeLists.txt index 29c588bcd70c17..46748c9c01a57f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -802,6 +802,8 @@ set(CURL_CA_FALLBACK OFF CACHE BOOL "Set ON to use built-in CA store of TLS backend. Defaults to OFF") set(CURL_CA_PATH "auto" CACHE STRING "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.") +set(CURL_CA_BUNDLE_PEM OFF CACHE BOOL + "Set ON to use built-in CACERT_PEM from generated cacert.h. Defaults to OFF") if("${CURL_CA_BUNDLE}" STREQUAL "") message(FATAL_ERROR "Invalid value of CURL_CA_BUNDLE. Use 'none', 'auto' or file path.") diff --git a/acinclude.m4 b/acinclude.m4 index 380a8fffc99a87..75e2a66b93c758 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -2306,6 +2306,24 @@ AC_HELP_STRING([--without-ca-fallback], [Don't use the built in CA store of the fi AC_DEFINE_UNQUOTED(CURL_CA_FALLBACK, 1, [define "1" to use built in CA store of SSL library ]) fi + + AC_MSG_CHECKING([whether to use built in CACERT_PEM from generated cacert.h]) + AC_ARG_WITH(ca-built-in, +AC_HELP_STRING([--with-ca-built-in], [Use the built in CACERT_PEM from generated cacert.h]) +AC_HELP_STRING([--without-ca-built-in], [Don't use the built in CACERT_PEM from generated cacert.h]), + [ + if test "x$with_ca_built_in" != "xyes" -a "x$with_ca_built_in" != "xno"; then + AC_MSG_ERROR([--with-ca-built-in only allows yes or no as parameter]) + fi + ], + [ with_ca_fallback="no"]) + AC_MSG_RESULT([$with_ca_built_in]) + if test "x$with_ca_built_in" = "xyes"; then + if test "x$OPENSSL_ENABLED" != "x1"; then + AC_MSG_ERROR([--with-ca-built-in only works with OpenSSL]) + fi + AC_DEFINE_UNQUOTED(CURL_CA_BUNDLE_PEM, 1, [define "1" to use built in CACERT_PEM from generated cacert.h ]) + fi ]) dnl CURL_CHECK_WIN32_LARGEFILE diff --git a/configure.ac b/configure.ac index 1075511c9da42c..91faaf8931c9dc 100755 --- a/configure.ac +++ b/configure.ac @@ -5255,6 +5255,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl: ca cert bundle: ${ca}${ca_warning} ca cert path: ${capath}${capath_warning} ca fallback: ${with_ca_fallback} + ca built in: ${with_ca_built_in} LDAP: ${curl_ldap_msg} LDAPS: ${curl_ldaps_msg} RTSP: ${curl_rtsp_msg} diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 index e4dafa7995d3ff..16178e71dc3411 100644 --- a/docs/libcurl/curl_easy_setopt.3 +++ b/docs/libcurl/curl_easy_setopt.3 @@ -573,8 +573,12 @@ Verify the proxy SSL certificate. See \fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP Verify the SSL certificate's status. See \fICURLOPT_SSL_VERIFYSTATUS(3)\fP .IP CURLOPT_CAINFO CA cert bundle. See \fICURLOPT_CAINFO(3)\fP +.IP CURLOPT_CAINFO_PEM +CA cert bundle as PEM string. See \fICURLOPT_CAINFO_PEM(3)\fP .IP CURLOPT_PROXY_CAINFO Proxy CA cert bundle. See \fICURLOPT_PROXY_CAINFO(3)\fP +.IP CURLOPT_PROXY_CAINFO_PEM +Proxy CA cert bundle as PEM string. See \fICURLOPT_PROXY_CAINFO_PEM(3)\fP .IP CURLOPT_ISSUERCERT Issuer certificate. See \fICURLOPT_ISSUERCERT(3)\fP .IP CURLOPT_ISSUERCERT_BLOB diff --git a/docs/libcurl/opts/CURLOPT_CAINFO_PEM.3 b/docs/libcurl/opts/CURLOPT_CAINFO_PEM.3 new file mode 100644 index 00000000000000..294f430a21d9ed --- /dev/null +++ b/docs/libcurl/opts/CURLOPT_CAINFO_PEM.3 @@ -0,0 +1,67 @@ +.\" ************************************************************************** +.\" * _ _ ____ _ +.\" * Project ___| | | | _ \| | +.\" * / __| | | | |_) | | +.\" * | (__| |_| | _ <| |___ +.\" * \___|\___/|_| \_\_____| +.\" * +.\" * Copyright (C) 1998 - 2019, Daniel Stenberg, , 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. +.\" * +.\" ************************************************************************** +.\" +.TH CURLOPT_CAINFO_PEM 3 "14 Nov 2020" "libcurl 7.74.0" "curl_easy_setopt options" +.SH NAME +CURLOPT_CAINFO \- with proxy Certificate Authority (CA) bundle in PEM format +.SH SYNOPSIS +#include + +CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CAINFO_PEM, char *pem_string); +.SH DESCRIPTION +Pass a char * to a null-terminated string with PEM encoded content holding one +or more certificates to verify the HTTPS proxy with. + +If \fICURLOPT_SSL_VERIFYPEER(3)\fP is zero and you avoid verifying the +server's certificate, \fICURLOPT_CAINFO(3)\fP need not even indicate an +accessible file. + + +The application does not have to keep the string around after setting this +option. +.SH DEFAULT +Built-in system specific. When curl is built with Secure Transport or +Schannel, this option is not set by default. +.SH PROTOCOLS +All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc. +.SH EXAMPLE +.nf +const char* strpem; +/* user must fill strpem with content of a PEM file */ +CURL *curl = curl_easy_init(); +if(curl) { + curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); + curl_easy_setopt(curl, CURLOPT_CAINFO_PEM, strpem); + ret = curl_easy_perform(curl); + curl_easy_cleanup(curl); +} +.fi +.SH AVAILABILITY +Added in 7.74.0 + +This option is supported by the OpenSSL backends. +.SH RETURN VALUE +Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or +CURLE_OUT_OF_MEMORY if there was insufficient heap space. +.SH "SEE ALSO" +.BR CURLOPT_CAPATH "(3), " +.BR CURLOPT_SSL_VERIFYPEER "(3), " CURLOPT_SSL_VERIFYHOST "(3), " diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_PEM.3 b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_PEM.3 new file mode 100644 index 00000000000000..a2beb7300337e6 --- /dev/null +++ b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_PEM.3 @@ -0,0 +1,84 @@ +.\" ************************************************************************** +.\" * _ _ ____ _ +.\" * Project ___| | | | _ \| | +.\" * / __| | | | |_) | | +.\" * | (__| |_| | _ <| |___ +.\" * \___|\___/|_| \_\_____| +.\" * +.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, , 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. +.\" * +.\" ************************************************************************** +.\" +.TH CURLOPT_PROXY_CAINFO_PEM 3 "14 Nov 2020" "libcurl 7.74.0" "curl_easy_setopt options" +.SH NAME +CURLOPT_PROXY_CAINFO \- string with proxy Certificate Authority (CA) bundle in PEM format +.SH SYNOPSIS +#include + +CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAINFO_PEM, char *pem_string); +.SH DESCRIPTION +This option is for connecting to an HTTPS proxy, not an HTTPS server. + +Pass a char * to a null-terminated string with PEM encoded content holding one +or more certificates to verify the HTTPS proxy with. + +If \fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP is zero and you avoid verifying the +server's certificate, \fICURLOPT_PROXY_CAINFO(3)\fP need not even indicate an +accessible file. + +This option is by default set to the system path where libcurl's cacert bundle +is assumed to be stored, as established at build time. + +If curl is built against the NSS SSL library, the NSS PEM PKCS#11 module +(libnsspem.so) needs to be available for this option to work properly. + +(iOS and macOS only) If curl is built against Secure Transport, then this +option is supported for backward compatibility with other SSL engines, but it +should not be set. If the option is not set, then curl will use the +certificates in the system and user Keychain to verify the peer, which is the +preferred method of verifying the peer's certificate chain. + +This option is supported by the OpenSSL backends. + +The application does not have to keep the string around after setting this +option. +.SH DEFAULT +Built-in system specific +.SH PROTOCOLS +Used with HTTPS proxy +.SH EXAMPLE +.nf +const char* strpem; +/* user must fill strpem with content of a PEM file */ +CURL *curl = curl_easy_init(); +if(curl) { + curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); + /* using an HTTPS proxy */ + curl_easy_setopt(curl, CURLOPT_PROXY, "https://localhost:443"); + curl_easy_setopt(curl, CURLOPT_PROXY_CAINFO_PEM, strpem); + ret = curl_easy_perform(curl); + curl_easy_cleanup(curl); +} +.fi +.SH AVAILABILITY +Added in 7.74.0 + +This option is supported by the OpenSSL backends..SH RETURN VALUE +Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or +CURLE_OUT_OF_MEMORY if there was insufficient heap space. +.SH "SEE ALSO" +.BR CURLOPT_PROXY_CAPATH "(3), " +.BR CURLOPT_PROXY_SSL_VERIFYPEER "(3), " CURLOPT_PROXY_SSL_VERIFYHOST "(3), " +.BR CURLOPT_CAPATH "(3), " +.BR CURLOPT_SSL_VERIFYPEER "(3), " CURLOPT_SSL_VERIFYHOST "(3), " diff --git a/docs/libcurl/opts/Makefile.inc b/docs/libcurl/opts/Makefile.inc index dc6b99aca3c385..e161f36636b50c 100644 --- a/docs/libcurl/opts/Makefile.inc +++ b/docs/libcurl/opts/Makefile.inc @@ -114,6 +114,7 @@ man_MANS = \ CURLOPT_AUTOREFERER.3 \ CURLOPT_BUFFERSIZE.3 \ CURLOPT_CAINFO.3 \ + CURLOPT_CAINFO_PEM.3 \ CURLOPT_CAPATH.3 \ CURLOPT_CERTINFO.3 \ CURLOPT_CHUNK_BGN_FUNCTION.3 \ @@ -263,6 +264,7 @@ man_MANS = \ CURLOPT_PROXYUSERNAME.3 \ CURLOPT_PROXYUSERPWD.3 \ CURLOPT_PROXY_CAINFO.3 \ + CURLOPT_PROXY_CAINFO_PEM.3 \ CURLOPT_PROXY_CAPATH.3 \ CURLOPT_PROXY_CRLFILE.3 \ CURLOPT_PROXY_KEYPASSWD.3 \ diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions index 861aaf88f48ab6..b9eccf552dd834 100644 --- a/docs/libcurl/symbols-in-versions +++ b/docs/libcurl/symbols-in-versions @@ -371,6 +371,7 @@ CURLOPT_APPEND 7.17.0 CURLOPT_AUTOREFERER 7.1 CURLOPT_BUFFERSIZE 7.10 CURLOPT_CAINFO 7.4.2 +CURLOPT_CAINFO_PEM 7.74 CURLOPT_CAPATH 7.9.8 CURLOPT_CERTINFO 7.19.1 CURLOPT_CHUNK_BGN_FUNCTION 7.21.0 @@ -537,6 +538,7 @@ CURLOPT_PROXYTYPE 7.10 CURLOPT_PROXYUSERNAME 7.19.1 CURLOPT_PROXYUSERPWD 7.1 CURLOPT_PROXY_CAINFO 7.52.0 +CURLOPT_PROXY_CAINFO_PEM 7.74 CURLOPT_PROXY_CAPATH 7.52.0 CURLOPT_PROXY_CRLFILE 7.52.0 CURLOPT_PROXY_ISSUERCERT 7.71.0 diff --git a/include/curl/curl.h b/include/curl/curl.h index 492a71cfe30f28..3eed8d8a076881 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -2073,6 +2073,14 @@ typedef enum { CURLOPT(CURLOPT_HSTSWRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 303), CURLOPT(CURLOPT_HSTSWRITEDATA, CURLOPTTYPE_CBPOINT, 304), + /* The CAfile in memory as PEM used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAINFO_PEM, CURLOPTTYPE_STRINGPOINT, 299), + + /* The CAfile in memory as PEM used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAINFO_PEM, CURLOPTTYPE_STRINGPOINT, 300), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/lib/cacert.h b/lib/cacert.h new file mode 100644 index 00000000000000..f637fc52cab787 --- /dev/null +++ b/lib/cacert.h @@ -0,0 +1,38 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , 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.haxx.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. + * + ***************************************************************************/ + +/* + +regenerate this file like so: + +curl -Oz cacert.pem https://curl.haxx.se/ca/cacert.pem \ +&& xxd -i -C cacert.pem | sed -r 's/(0x..)$/\1, 0x00/' > lib/cacert.h + +unless CACERT_PEM is defined in here, there will be a compile error if +CURL_CA_BUNDLE_PEM is defined, CACERT_PEM must be a proper null-terminated +C string + +unsigned char CACERT_PEM[] = { + 0x62, 0x6f, 0x62, 0x0a, 0x00 +}; +unsigned int CACERT_PEM_LEN = 4; +*/ diff --git a/lib/setopt.c b/lib/setopt.c index 12a268e94b8f9d..9da24a169fd434 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -2013,6 +2013,21 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) result = CURLE_NOT_BUILT_IN; break; #endif + case CURLOPT_CAINFO_PEM: + /* + * Set CA info for SSL connection. Specify entire PEM of the CA certificate + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PEM_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_CAINFO_PEM: + /* + * Set CA info for SSL connection proxy. + * Specify entire PEM of the CA certificate + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PEM_PROXY], + va_arg(param, char *)); + break; case CURLOPT_CRLFILE: /* * Set CRL file info for SSL connection. Specify file name of the CRL diff --git a/lib/url.c b/lib/url.c index 381f98dc65bfc5..5dc7a1f2ea78da 100644 --- a/lib/url.c +++ b/lib/url.c @@ -130,6 +130,10 @@ bool curl_win32_idn_to_ascii(const char *in, char **out); #include "curl_memory.h" #include "memdebug.h" +#if defined(CURL_CA_BUNDLE_PEM) +#include "cacert.h" +#endif + static void conn_free(struct connectdata *conn); /* Some parts of the code (e.g. chunked encoding) assume this buffer has at @@ -551,6 +555,18 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) set->socks5_gssapi_nec = FALSE; #endif +#if defined(CURL_CA_BUNDLE_PEM) + result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PEM_ORIG], + (const char *) CACERT_PEM); + if(result) + return result; + + result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PEM_PROXY], + (const char *) CACERT_PEM); + if(result) + return result; +#endif + /* Set the default CA cert bundle/path detected/specified at build time. * * If Schannel is the selected SSL backend then these locations are @@ -3655,6 +3671,11 @@ static CURLcode create_conn(struct Curl_easy *data, */ data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG]; data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG]; + data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY]; + data->set.ssl.primary.ca_file_pem = + data->set.str[STRING_SSL_CAFILE_PEM_ORIG]; + data->set.proxy_ssl.primary.ca_file_pem = + data->set.str[STRING_SSL_CAFILE_PEM_PROXY]; data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE]; data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; data->set.ssl.primary.cipher_list = diff --git a/lib/urldata.h b/lib/urldata.h index a3c2b3cf3e4d19..84f7c9cb2f65df 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -229,6 +229,7 @@ struct ssl_primary_config { char *pinned_key; struct curl_blob *cert_blob; char *curves; /* list of curves to use */ + char *ca_file_pem; BIT(verifypeer); /* set TRUE if this is desired */ BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */ BIT(verifystatus); /* set TRUE if certificate status must be checked */ @@ -1511,6 +1512,8 @@ enum dupstring { STRING_SSL_CAPATH_PROXY, /* CA directory name (doesn't work on windows) */ STRING_SSL_CAFILE_ORIG, /* certificate file to verify peer against */ STRING_SSL_CAFILE_PROXY, /* certificate file to verify peer against */ + STRING_SSL_CAFILE_PEM_ORIG, /* PEM certificate to verify peer against */ + STRING_SSL_CAFILE_PEM_PROXY, /* PEM certificate to verify peer against */ STRING_SSL_PINNEDPUBLICKEY_ORIG, /* public key file to verify peer against */ STRING_SSL_PINNEDPUBLICKEY_PROXY, /* public key file to verify proxy */ STRING_SSL_CIPHER_LIST_ORIG, /* list of ciphers to use */ diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index 1803ed34c124ac..bcf47cb21bdabb 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -2457,6 +2457,61 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) return res; } +static CURLcode load_cacert_from_memory(SSL_CTX *ctx, + const char * const ca_file_pem) +{ + /* these need freed at the end */ + BIO *cbio = NULL; + STACK_OF(X509_INFO) *inf = NULL; + + /* everything else is just a reference */ + int i, count = 0; + X509_STORE *cts = NULL; + X509_INFO *itmp = NULL; + + CURLcode result = CURLE_SSL_CACERT_BADFILE; + + do { + /* casting strlen to int feels wrong, but what to do with this API? */ + cbio = BIO_new_mem_buf(ca_file_pem, (int) strlen(ca_file_pem)); + if(!cbio) + break; + + cts = SSL_CTX_get_cert_store(ctx); + if(!cts) + break; + + inf = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL); + if(!inf) + break; + + /* add each entry from PEM file to x509_store */ + for(i = 0; i < sk_X509_INFO_num(inf); ++i) { + itmp = sk_X509_INFO_value(inf, i); + if(itmp->x509) { + X509_STORE_add_cert(cts, itmp->x509); + ++count; + } + if(itmp->crl) { + X509_STORE_add_crl(cts, itmp->crl); + ++count; + } + } + + /* if we didn't end up importing anything, treat that as an error */ + if(count > 0) + result = CURLE_OK; + } while(0); + + if(inf) + sk_X509_INFO_pop_free(inf, X509_INFO_free); + + if(cbio) + BIO_free(cbio); + + return result; +} + static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) { CURLcode result = CURLE_OK; @@ -2487,6 +2542,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) const char * const ssl_cert_type = SSL_SET_OPTION(cert_type); const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); const char * const ssl_capath = SSL_CONN_CONFIG(CApath); + const char * const ca_file_pem = SSL_CONN_CONFIG(ca_file_pem); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); char error_buffer[256]; @@ -2976,6 +3032,15 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) infof(data, "error importing windows ca store, continuing anyway\n"); } #endif + if(ca_file_pem && load_cacert_from_memory(backend->ctx, ca_file_pem)) { + if(verifypeer) { + /* Fail if we insist on successfully verifying the server. */ + failf(data, "error setting certificate from memory"); + return CURLE_SSL_CACERT_BADFILE; + } + /* Continue with a warning if no certificate verification is required. */ + infof(data, "error setting certificate file, continuing anyway\n"); + } #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */ diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index 3bd51fdaf296c4..8ca5ef98a2e8ca 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -133,6 +133,7 @@ Curl_ssl_config_matches(struct ssl_primary_config *data, blobcmp(data->cert_blob, needle->cert_blob) && Curl_safe_strcasecompare(data->CApath, needle->CApath) && Curl_safe_strcasecompare(data->CAfile, needle->CAfile) && + Curl_safe_strcasecompare(data->ca_file_pem, needle->ca_file_pem) && Curl_safe_strcasecompare(data->clientcert, needle->clientcert) && Curl_safe_strcasecompare(data->random_file, needle->random_file) && Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) && @@ -159,6 +160,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source, CLONE_BLOB(cert_blob); CLONE_STRING(CApath); CLONE_STRING(CAfile); + CLONE_STRING(ca_file_pem); CLONE_STRING(clientcert); CLONE_STRING(random_file); CLONE_STRING(egdsocket); @@ -174,6 +176,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc) { Curl_safefree(sslc->CApath); Curl_safefree(sslc->CAfile); + Curl_safefree(sslc->ca_file_pem); Curl_safefree(sslc->clientcert); Curl_safefree(sslc->random_file); Curl_safefree(sslc->egdsocket);