From 8e99b65a1560ddbefb3522e4d2d395f118eae2ed Mon Sep 17 00:00:00 2001 From: Gilles Vollant Date: Mon, 13 Jul 2020 03:17:56 +0200 Subject: [PATCH] rebased branch bundled_cacert from moparisthebest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Validation : 397e11bfa6175c525d9365e63162888a77008213 [397e11b] Parents : 4506607b44 Auteur : moparisthebest Date : vendredi 3 avril 2020 00:32:42 Auteur : moparisthebest Date de validation : samedi 4 avril 2020 00:31:23 Add CURLOPT_CAINFO_PEM --- docs/libcurl/curl_easy_setopt.3 | 4 ++ docs/libcurl/opts/CURLOPT_CAINFO_PEM.3 | 66 ++++++++++++++++++ docs/libcurl/opts/CURLOPT_PROXY_CAINFO_PEM.3 | 71 ++++++++++++++++++++ docs/libcurl/opts/Makefile.inc | 2 + docs/libcurl/symbols-in-versions | 2 + include/curl/curl.h | 8 +++ include/curl/typecheck-gcc.h | 4 +- lib/easyoptions.c | 4 +- lib/setopt.c | 15 +++++ lib/url.c | 4 ++ lib/urldata.h | 3 + lib/vtls/openssl.c | 65 ++++++++++++++++++ lib/vtls/vtls.c | 3 + 13 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 docs/libcurl/opts/CURLOPT_CAINFO_PEM.3 create mode 100644 docs/libcurl/opts/CURLOPT_PROXY_CAINFO_PEM.3 diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 index ee5bd32da6e25f..1aaa4ef646539c 100644 --- a/docs/libcurl/curl_easy_setopt.3 +++ b/docs/libcurl/curl_easy_setopt.3 @@ -575,8 +575,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..150d48ba4c75e7 --- /dev/null +++ b/docs/libcurl/opts/CURLOPT_CAINFO_PEM.3 @@ -0,0 +1,66 @@ +.\" ************************************************************************** +.\" * _ _ ____ _ +.\" * Project ___| | | | _ \| | +.\" * / __| | | | |_) | | +.\" * | (__| |_| | _ <| |___ +.\" * \___|\___/|_| \_\_____| +.\" * +.\" * Copyright (C) 1998 - 2021, 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 "31 March 2021" "libcurl 7.76.0" "curl_easy_setopt options" +.SH NAME +CURLOPT_CAINFO_PEM \- 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 server 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 +NULL +.SH PROTOCOLS +All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc. +.SH EXAMPLE +.nf +const char *strpem; +/* strpem must point to a PEM string */ +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.76.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..1ce48f15d6c5b0 --- /dev/null +++ b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_PEM.3 @@ -0,0 +1,71 @@ +.\" ************************************************************************** +.\" * _ _ ____ _ +.\" * Project ___| | | | _ \| | +.\" * / __| | | | |_) | | +.\" * | (__| |_| | _ <| |___ +.\" * \___|\___/|_| \_\_____| +.\" * +.\" * Copyright (C) 1998 - 2021, 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 "31 March 2021" "libcurl 7.76.0" "curl_easy_setopt options" +.SH NAME +CURLOPT_PROXY_CAINFO_PEM \- 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. + +The application does not have to keep the string around after setting this +option. +.SH DEFAULT +NULL +.SH PROTOCOLS +Used with HTTPS proxy +.SH EXAMPLE +.nf +const char *strpem; +/* strpem must point to a PEM string */ +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.76.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 3b5d27edd5248f..6a9b2c195d280c 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 66c36c4ce7a40f..b77610c3ec8f53 100644 --- a/docs/libcurl/symbols-in-versions +++ b/docs/libcurl/symbols-in-versions @@ -372,6 +372,7 @@ CURLOPT_APPEND 7.17.0 CURLOPT_AUTOREFERER 7.1 CURLOPT_BUFFERSIZE 7.10 CURLOPT_CAINFO 7.4.2 +CURLOPT_CAINFO_PEM 7.76.0 CURLOPT_CAPATH 7.9.8 CURLOPT_CERTINFO 7.19.1 CURLOPT_CHUNK_BGN_FUNCTION 7.21.0 @@ -538,6 +539,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.76.0 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 46503178d015c2..93904b846fea2c 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -2079,6 +2079,14 @@ typedef enum { /* Parameters for V4 signature */ CURLOPT(CURLOPT_AWS_SIGV4, CURLOPTTYPE_STRINGPOINT, 305), + /* 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, 306), + + /* 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, 307), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h index 230f4c1067e6fb..3596cd83b41f0e 100644 --- a/include/curl/typecheck-gcc.h +++ b/include/curl/typecheck-gcc.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, 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 @@ -256,6 +256,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t, (option) == CURLOPT_ACCEPT_ENCODING || \ (option) == CURLOPT_ALTSVC || \ (option) == CURLOPT_CAINFO || \ + (option) == CURLOPT_CAINFO_PEM || \ (option) == CURLOPT_CAPATH || \ (option) == CURLOPT_COOKIE || \ (option) == CURLOPT_COOKIEFILE || \ @@ -291,6 +292,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t, (option) == CURLOPT_PROXYUSERNAME || \ (option) == CURLOPT_PROXYUSERPWD || \ (option) == CURLOPT_PROXY_CAINFO || \ + (option) == CURLOPT_PROXY_CAINFO_PEM || \ (option) == CURLOPT_PROXY_CAPATH || \ (option) == CURLOPT_PROXY_CRLFILE || \ (option) == CURLOPT_PROXY_ISSUERCERT || \ diff --git a/lib/easyoptions.c b/lib/easyoptions.c index b54829ba385faa..f9a34f4cf4ce44 100644 --- a/lib/easyoptions.c +++ b/lib/easyoptions.c @@ -38,6 +38,7 @@ struct curl_easyoption Curl_easyopts[] = { {"AWS_SIGV4", CURLOPT_AWS_SIGV4, CURLOT_STRING, 0}, {"BUFFERSIZE", CURLOPT_BUFFERSIZE, CURLOT_LONG, 0}, {"CAINFO", CURLOPT_CAINFO, CURLOT_STRING, 0}, + {"CAINFO_PEM", CURLOPT_CAINFO_PEM, CURLOT_STRING, 0}, {"CAPATH", CURLOPT_CAPATH, CURLOT_STRING, 0}, {"CERTINFO", CURLOPT_CERTINFO, CURLOT_LONG, 0}, {"CHUNK_BGN_FUNCTION", CURLOPT_CHUNK_BGN_FUNCTION, CURLOT_FUNCTION, 0}, @@ -202,6 +203,7 @@ struct curl_easyoption Curl_easyopts[] = { {"PROXYUSERNAME", CURLOPT_PROXYUSERNAME, CURLOT_STRING, 0}, {"PROXYUSERPWD", CURLOPT_PROXYUSERPWD, CURLOT_STRING, 0}, {"PROXY_CAINFO", CURLOPT_PROXY_CAINFO, CURLOT_STRING, 0}, + {"PROXY_CAINFO_PEM", CURLOPT_PROXY_CAINFO_PEM, CURLOT_STRING, 0}, {"PROXY_CAPATH", CURLOPT_PROXY_CAPATH, CURLOT_STRING, 0}, {"PROXY_CRLFILE", CURLOPT_PROXY_CRLFILE, CURLOT_STRING, 0}, {"PROXY_ISSUERCERT", CURLOPT_PROXY_ISSUERCERT, CURLOT_STRING, 0}, @@ -349,6 +351,6 @@ struct curl_easyoption Curl_easyopts[] = { */ int Curl_easyopts_check(void) { - return ((CURLOPT_LASTENTRY%10000) != (305 + 1)); + return ((CURLOPT_LASTENTRY%10000) != (307 + 1)); } #endif diff --git a/lib/setopt.c b/lib/setopt.c index 715b2f284c12b3..814e6eb8f4cfe8 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -2032,6 +2032,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 f160b1596b367f..e44be0585f78f8 100644 --- a/lib/url.c +++ b/lib/url.c @@ -3695,6 +3695,8 @@ 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.ssl.primary.ca_file_pem = + data->set.str[STRING_SSL_CAFILE_PEM_ORIG]; 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 = @@ -3709,6 +3711,8 @@ static CURLcode create_conn(struct Curl_easy *data, #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.ca_file_pem = + data->set.str[STRING_SSL_CAFILE_PEM_PROXY]; data->set.proxy_ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE]; data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; diff --git a/lib/urldata.h b/lib/urldata.h index 6a9c52c44fc465..a099e43b5d0dbc 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -254,6 +254,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 */ @@ -1543,6 +1544,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 c4621d8d3387b9..ee90e979cc56e7 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -2499,6 +2499,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 < (int)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 Curl_easy *data, struct connectdata *conn, int sockindex) { @@ -2529,6 +2584,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, 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]; @@ -3019,6 +3075,15 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, 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 6a0069237fdb24..b6d41d5bd735dd 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -137,6 +137,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) && @@ -163,6 +164,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); @@ -178,6 +180,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);