vtls: handle possible malicious certs_num from peer
No binary (build failed)
—
(log yok)
| @@ -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; |
| + | } |
| } | |
| } | |
| @@ -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; | |
| @@ -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; | |
| @@ -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) | |
| @@ -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) { | |
| @@ -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); | |
| @@ -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; | |
| } | |