Skip to content

Commit

Permalink
rebased branch bundled_cacert from moparisthebest
Browse files Browse the repository at this point in the history
Validation : 397e11b [397e11b]
Parents : 4506607
Auteur : moparisthebest <admin@moparisthebest.com>
Date : vendredi 3 avril 2020 00:32:42
Auteur : moparisthebest
Date de validation : samedi 4 avril 2020 00:31:23
Add CURLOPT_CAINFO_PEM
  • Loading branch information
gvollant committed Feb 10, 2021
1 parent 89193ed commit 8e99b65
Show file tree
Hide file tree
Showing 13 changed files with 249 additions and 2 deletions.
4 changes: 4 additions & 0 deletions docs/libcurl/curl_easy_setopt.3
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
66 changes: 66 additions & 0 deletions docs/libcurl/opts/CURLOPT_CAINFO_PEM.3
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
.\" **************************************************************************
.\" * _ _ ____ _
.\" * Project ___| | | | _ \| |
.\" * / __| | | | |_) | |
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2021, 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.
.\" *
.\" **************************************************************************
.\"
.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 <curl/curl.h>

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), "
71 changes: 71 additions & 0 deletions docs/libcurl/opts/CURLOPT_PROXY_CAINFO_PEM.3
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
.\" **************************************************************************
.\" * _ _ ____ _
.\" * Project ___| | | | _ \| |
.\" * / __| | | | |_) | |
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2021, 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.
.\" *
.\" **************************************************************************
.\"
.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 <curl/curl.h>

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), "
2 changes: 2 additions & 0 deletions docs/libcurl/opts/Makefile.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down Expand Up @@ -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 \
Expand Down
2 changes: 2 additions & 0 deletions docs/libcurl/symbols-in-versions
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions include/curl/curl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
4 changes: 3 additions & 1 deletion include/curl/typecheck-gcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2021, 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
Expand Down Expand Up @@ -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 || \
Expand Down Expand Up @@ -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 || \
Expand Down
4 changes: 3 additions & 1 deletion lib/easyoptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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},
Expand Down Expand Up @@ -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
15 changes: 15 additions & 0 deletions lib/setopt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions lib/url.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand All @@ -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];
Expand Down
3 changes: 3 additions & 0 deletions lib/urldata.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down
65 changes: 65 additions & 0 deletions lib/vtls/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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 */
Expand Down

0 comments on commit 8e99b65

Please sign in to comment.