vtls: handle possible malicious certs_num from peer

For GnuTLS, mbedTLS, Rustls, Schannel and wolfSSL

This check was previously added for OpenSSL in 3df71e6dc2

Closes #19397
This commit is contained in:
x2018 2025-11-07 20:51:22 +08:00 committed by Daniel Stenberg
parent a6fcaf2958
commit 9c0ccd2739
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
7 changed files with 49 additions and 16 deletions

View file

@ -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;
}
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -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) {

View file

@ -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);

View file

@ -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;
}