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 Jul 13, 2020
1 parent 2bd8fe8 commit e7f0319
Show file tree
Hide file tree
Showing 10 changed files with 174 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,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.")
Expand Down
18 changes: 18 additions & 0 deletions acinclude.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -5173,6 +5173,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}
Expand Down
8 changes: 8 additions & 0 deletions include/curl/curl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1971,6 +1971,14 @@ typedef enum {
CURLOPT(CURLOPT_PROXY_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 296),
CURLOPT(CURLOPT_PROXY_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 297),

/* 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, 291),

/* 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, 292),

CURLOPT_LASTENTRY /* the last unused */
} CURLoption;

Expand Down
38 changes: 38 additions & 0 deletions lib/cacert.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2020, 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.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;
*/
15 changes: 15 additions & 0 deletions lib/setopt.c
Original file line number Diff line number Diff line change
Expand Up @@ -2010,6 +2010,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
21 changes: 21 additions & 0 deletions lib/url.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,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);
static unsigned int get_protocol_family(unsigned int protocol);

Expand Down Expand Up @@ -534,6 +538,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
Expand Down Expand Up @@ -3601,6 +3617,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 =
Expand Down
3 changes: 3 additions & 0 deletions lib/urldata.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ struct ssl_primary_config {
char *cipher_list13; /* list of TLS 1.3 cipher suites to use */
char *pinned_key;
struct curl_blob *cert_blob;
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 @@ -1507,6 +1508,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 @@ -2444,6 +2444,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;
Expand Down Expand Up @@ -2485,6 +2540,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];
Expand Down Expand Up @@ -2961,6 +3017,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 */
Expand Down
3 changes: 3 additions & 0 deletions lib/vtls/vtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) &&
Expand All @@ -158,6 +159,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);
Expand All @@ -172,6 +174,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);
Expand Down

0 comments on commit e7f0319

Please sign in to comment.