From: x2018 Date: Fri, 7 Nov 2025 12:51:22 +0000 (+0800) Subject: vtls: handle possible malicious certs_num from peer X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9c0ccd27390c985bd4b7875b5f161ac1e68c9da4;p=thirdparty%2Fcurl.git vtls: handle possible malicious certs_num from peer For GnuTLS, mbedTLS, Rustls, Schannel and wolfSSL This check was previously added for OpenSSL in 3df71e6dc23e80466c2d448 Closes #19397 --- diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index ebd2c8de1e..34d9b84d79 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.c @@ -1618,19 +1618,27 @@ Curl_gtls_verifyserver(struct Curl_cfilter *cf, } if(data->set.ssl.certinfo && chain.certs) { - unsigned int i; - - result = Curl_ssl_init_certinfo(data, (int)chain.num_certs); - if(result) + if(chain.num_certs > MAX_ALLOWED_CERT_AMOUNT) { + failf(data, "%u certificates is more than allowed (%u)", + chain.num_certs, MAX_ALLOWED_CERT_AMOUNT); + result = CURLE_SSL_CONNECT_ERROR; goto out; + } + else { + unsigned int i; - for(i = 0; i < chain.num_certs; i++) { - const char *beg = (const char *) chain.certs[i].data; - const char *end = beg + chain.certs[i].size; - - result = Curl_extract_certinfo(data, (int)i, beg, end); + result = Curl_ssl_init_certinfo(data, (int)chain.num_certs); if(result) goto out; + + for(i = 0; i < chain.num_certs; i++) { + const char *beg = (const char *) chain.certs[i].data; + const char *end = beg + chain.certs[i].size; + + result = Curl_extract_certinfo(data, (int)i, beg, end); + if(result) + goto out; + } } } diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index 36200de6fa..f5302499bd 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -475,10 +475,19 @@ mbed_extract_certinfo(struct Curl_easy *data, const mbedtls_x509_crt *crt) { CURLcode result; const mbedtls_x509_crt *cur; + int cert_count = 0; int i; - for(i = 0, cur = crt; cur; ++i, cur = cur->next); - result = Curl_ssl_init_certinfo(data, i); + for(cur = crt; cur && cert_count <= MAX_ALLOWED_CERT_AMOUNT; cur = cur->next) + cert_count++; + + if(cert_count > MAX_ALLOWED_CERT_AMOUNT) { + infof(data, "Certificates is more than allowed (%u), skipping certinfo", + MAX_ALLOWED_CERT_AMOUNT); + return; + } + + result = Curl_ssl_init_certinfo(data, cert_count); for(i = 0, cur = crt; result == CURLE_OK && cur; ++i, cur = cur->next) { const char *beg = (const char *) cur->raw.p; diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index 87b00cc252..59fd0cbd6d 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -349,8 +349,6 @@ static CURLcode X509V3_ext(struct Curl_easy *data, return result; } -#define MAX_ALLOWED_CERT_AMOUNT 100 - static CURLcode ossl_certchain(struct Curl_easy *data, SSL *ssl) { CURLcode result; diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c index ecf4d03152..262f016f9f 100644 --- a/lib/vtls/rustls.c +++ b/lib/vtls/rustls.c @@ -1211,8 +1211,13 @@ cr_connect(struct Curl_cfilter *cf, if(data->set.ssl.certinfo) { size_t num_certs = 0; size_t i; - while(rustls_connection_get_peer_certificate(rconn, (int)num_certs)) { + while(rustls_connection_get_peer_certificate(rconn, num_certs)) { num_certs++; + if(num_certs > MAX_ALLOWED_CERT_AMOUNT) { + failf(data, "%zu certificates is more than allowed (%u)", + num_certs, MAX_ALLOWED_CERT_AMOUNT); + return CURLE_SSL_CONNECT_ERROR; + } } result = Curl_ssl_init_certinfo(data, (int)num_certs); if(result) diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c index f9d697bbb8..c96e0df77b 100644 --- a/lib/vtls/schannel.c +++ b/lib/vtls/schannel.c @@ -1478,6 +1478,8 @@ cert_counter_callback(const CERT_CONTEXT *ccert_context, bool reverse_order, (void)reverse_order; if(valid_cert_encoding(ccert_context)) (*(int *)certs_count)++; + if(*(int *)certs_count > MAX_ALLOWED_CERT_AMOUNT) + return FALSE; return TRUE; } @@ -1623,6 +1625,12 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data) } traverse_cert_store(ccert_context, cert_counter_callback, &certs_count); + if(certs_count > MAX_ALLOWED_CERT_AMOUNT) { + failf(data, "%d certificates is more than allowed (%u)", + certs_count, MAX_ALLOWED_CERT_AMOUNT); + CertFreeCertificateContext(ccert_context); + return CURLE_SSL_CONNECT_ERROR; + } result = Curl_ssl_init_certinfo(data, certs_count); if(!result) { diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h index 180333e63c..dbe13c5903 100644 --- a/lib/vtls/vtls.h +++ b/lib/vtls/vtls.h @@ -165,6 +165,7 @@ void Curl_ssl_version(char *buffer, size_t size); /* Certificate information list handling. */ #define CURL_X509_STR_MAX 100000 +#define MAX_ALLOWED_CERT_AMOUNT 100 void Curl_ssl_free_certinfo(struct Curl_easy *data); CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num); diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c index 19e8c5558a..585a406002 100644 --- a/lib/vtls/wolfssl.c +++ b/lib/vtls/wolfssl.c @@ -1512,9 +1512,13 @@ wssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) wolfSSL_set_bio(wssl->ssl, bio, bio); } #else /* USE_BIO_CHAIN */ + curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data); + if(sockfd > INT_MAX) { + failf(data, "SSL: socket value too large"); + return CURLE_SSL_CONNECT_ERROR; + } /* pass the raw socket into the SSL layer */ - if(!wolfSSL_set_fd(wssl->ssl, - (int)Curl_conn_cf_get_socket(cf, data))) { + if(!wolfSSL_set_fd(wssl->ssl, (int)sockfd)) { failf(data, "SSL: wolfSSL_set_fd failed"); return CURLE_SSL_CONNECT_ERROR; }