From b25574367cf094e912d8ae6ccaf1d255d454869f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 26 Jun 2020 23:26:01 +0200 Subject: vtls: compare blobs when finding a connection to reuse Reported-by: Gergely Nagy Fixes #5617 Closes #5619 --- lib/url.c | 4 +++- lib/urldata.h | 1 + lib/vtls/vtls.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/lib/url.c b/lib/url.c index 4e5587d34..a1a6b6910 100644 --- a/lib/url.c +++ b/lib/url.c @@ -3609,6 +3609,7 @@ static CURLcode create_conn(struct Curl_easy *data, data->set.str[STRING_SSL_CIPHER13_LIST_ORIG]; data->set.ssl.primary.pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_ORIG]; #ifndef CURL_DISABLE_PROXY data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY]; @@ -3622,6 +3623,7 @@ static CURLcode create_conn(struct Curl_easy *data, 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.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY]; data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY]; data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY]; @@ -3655,7 +3657,7 @@ static CURLcode create_conn(struct Curl_easy *data, data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT_ORIG]; if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary, - &conn->ssl_config)) { + &conn->ssl_config)) { result = CURLE_OUT_OF_MEMORY; goto out; } diff --git a/lib/urldata.h b/lib/urldata.h index 1fc25196a..f80a02def 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -229,6 +229,7 @@ struct ssl_primary_config { char *cipher_list; /* list of ciphers to use */ char *cipher_list13; /* list of TLS 1.3 cipher suites to use */ char *pinned_key; + struct curl_blob *cert_blob; 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 */ diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index 1cce961a6..c3a55fb1c 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -63,6 +63,7 @@ #include "warnless.h" #include "curl_base64.h" #include "curl_printf.h" +#include "strdup.h" /* The last #include files should be: */ #include "curl_memory.h" @@ -82,6 +83,44 @@ else \ dest->var = NULL; +#define CLONE_BLOB(var) \ + if(blobdup(&dest->var, source->var)) \ + return FALSE; + +static CURLcode blobdup(struct curl_blob **dest, + struct curl_blob *src) +{ + DEBUGASSERT(dest); + DEBUGASSERT(!*dest); + if(src) { + /* only if there's data to dupe! */ + struct curl_blob *d; + d = malloc(sizeof(struct curl_blob) + src->len); + if(!d) + return CURLE_OUT_OF_MEMORY; + d->len = src->len; + /* Always duplicate because the connection may survive longer than the + handle that passed in the blob. */ + d->flags = CURL_BLOB_COPY; + d->data = (void *)((char *)d + sizeof(struct curl_blob)); + memcpy(d->data, src->data, src->len); + *dest = d; + } + return CURLE_OK; +} + +/* returns TRUE if the blobs are identical */ +static bool blobcmp(struct curl_blob *first, struct curl_blob *second) +{ + if(!first && !second) /* both are NULL */ + return TRUE; + if(!first || !second) /* one is NULL */ + return FALSE; + if(first->len != second->len) /* different sizes */ + return FALSE; + return !memcmp(first->data, second->data, first->len); /* same data */ +} + bool Curl_ssl_config_matches(struct ssl_primary_config *data, struct ssl_primary_config *needle) @@ -91,6 +130,7 @@ Curl_ssl_config_matches(struct ssl_primary_config *data, (data->verifypeer == needle->verifypeer) && (data->verifyhost == needle->verifyhost) && (data->verifystatus == needle->verifystatus) && + 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->clientcert, needle->clientcert) && @@ -115,6 +155,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source, dest->verifystatus = source->verifystatus; dest->sessionid = source->sessionid; + CLONE_BLOB(cert_blob); CLONE_STRING(CApath); CLONE_STRING(CAfile); CLONE_STRING(clientcert); @@ -137,6 +178,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc) Curl_safefree(sslc->cipher_list); Curl_safefree(sslc->cipher_list13); Curl_safefree(sslc->pinned_key); + Curl_safefree(sslc->cert_blob); } #ifdef USE_SSL -- cgit v1.2.1