CVE-2024-2466: TLS certificate check bypass with mbedTLS
What the report claims
Curl library bypasses TLS certificate name check when connecting via IP address, allowing spoofing attacks.
Compare with curl's recorded outcome
Known vulnerability
A real vulnerability: CVE-2024-2466 TLS certificate check bypass with mbedTLS
Shown for comparison after analysis. The pipeline did not see this label.
ProveIt's finding
The available evidence does not settle the report. A maintainer should investigate.
See the withdrawn model reasoning
The following reasoning failed the citation check and does not support the final finding.
- Curl_ssl_peer_init only sets peer->sni for DNS hostnames (lines 1589-1603 in lib/vtls/vtls.c), leaving it NULL for IP addresses
- mbed_connect_step1 (per report and grounded symbols) only calls mbedtls_ssl_set_hostname when peer->sni is set
- mbedTLS documentation explicitly states mbedtls_ssl_set_hostname is required for CN/SAN verification even without SNI
- This bypasses server certificate host verification, enabling spoofing with valid certificates for other domains (CWE-297)
- The bug was previously fixed for CVE-2016-3739 but reintroduced by later refactoring per the commit history analysis
How this analysis ran 5 claims · 10 citations verified
Evidence check: judge quoted an external source that does not say that (https://mbed-tls.readthedocs.io/en/latest/kb/attacks/ssl_set_hostname)
Checked against curl master on 2024-03-14 (09f367977af2). Dev evaluation split. Citation verification checks that a referenced line was in the evidence; it does not prove the model interpreted it correctly.
Inspect the withdrawn draft reply
This draft belongs to the withdrawn judgment. It may contain unsupported claims.
Thank you for the detailed report and reproduction steps. The issue is confirmed: when connecting via IP address, peer->sni is not set (lib/vtls/vtls.c:1589-1603), so mbedtls_ssl_set_hostname is not called in mbed_connect_step1, bypassing CN/SAN verification. mbedTLS documentation confirms this function must be called for host verification regardless of SNI usage. This reintroduces CVE-2016-3739. We will fix by calling mbedtls_ssl_set_hostname with peer->hostname even when sni is NULL.
Inspect all claims and source code 5 claims · 9 code excerpts
This model judgment was withdrawn. The claim assessments below are preserved for inspection and may be wrong.
Report claims
mbedtls_ssl_set_hostname is not called when SNI is not set, causing server certificate name verification to be bypassed
Read the reasoning
Curl_ssl_peer_init only sets peer->sni for DNS hostnames (not IP addresses). The report states mbed_connect_step1 only calls mbedtls_ssl_set_hostname when peer->sni is set. External mbedTLS documentation confirms mbedtls_ssl_set_hostname is required for CN/SAN verification regardless of SNI usage. The deterministic checks confirm the symbols exist and the core quoted lines appear in the codebase.
lib/vtls/mbedtls.c in function mbed_connect_step1
Read the reasoning
The function mbed_connect_step1 exists in lib/vtls/mbedtls.c at the expected location per deterministic checks.
connecting to a host by its IP address instead of its DNS name
Read the reasoning
The peer type enum values for IP addresses exist and are used in get_peer_type to classify IP hostnames, which then prevents sni from being set.
SSL handshake completes without verifying the server's certificate against the host name, enabling spoofing
Read the reasoning
External sources confirm that skipping mbedtls_ssl_set_hostname bypasses CN/SAN verification, enabling spoofing/impersonation attacks with valid certificates for different domains.
Use curl with an IP address (e.g., curl https://93.184.216.34) and observe that no certificate verification error is raised
Read the reasoning
The reproduction steps are concrete: connecting via IP address triggers the code path where sni is NULL, so mbedtls_ssl_set_hostname is not called, and the handshake succeeds without host verification.
Deterministic checks that failed
- quote 4 of 10 quoted lines appear nowhere in curl, e.g. 'char *hostname; /* hostname for verification */'
- quote 2 of 5 quoted lines appear nowhere in curl, e.g. 'if(mbedtls_ssl_set_hostname(&backend->ssl, hostname)) {'
What the report says about other projects
confirmed mbedtls_ssl_set_hostname must be called for server name verification even when SNI is not used, as it also sets the name for CN/SAN checks
“mbedtls_ssl_set_hostname() must be called for server name verification even when SNI is not used, as it also sets the name for CN/SAN checks.” source
confirmed If no server host name was specified, every host name was accepted. This is an example of an insecure default weakness (CWE-1188).
“Historically, Mbed TLS did not require mbedtls_ssl_set_hostname() to be called. If no server host name was specified, every host name was accepted. This is an example of an insecure default weakness (CWE-1188).” source
confirmed The end certificate must be issued for the server that the client is trying to reach. Mbed TLS checks that the certificate content matches the name passed to mbedtls_ssl_set_hostname().
“The end certificate must be issued for the server that the client is trying to reach. Mbed TLS checks that the certificate content matches the name passed to mbedtls_ssl_set_hostname().” source
Read the original report (excerpt)
Source code
| 358 | static CURLcode |
| C2: mbed_connect_step1 function definition starts here | |
| 359 | mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) |
| 360 | { |
| 361 | struct ssl_connect_data *connssl = cf->ctx; |
| 362 | struct mbed_ssl_backend_data *backend = |
| 363 | (struct mbed_ssl_backend_data *)connssl->backend; |
| 364 | struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); |
| 365 | const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; |
| 366 | struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); |
| 367 | const char * const ssl_cafile = |
| 368 | /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ |
| 369 | (ca_info_blob ? NULL : conn_config->CAfile); |
| 370 | const bool verifypeer = conn_config->verifypeer; |
| 371 | const char * const ssl_capath = conn_config->CApath; |
| 372 | char * const ssl_cert = ssl_config->primary.clientcert; |
| 373 | const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob; |
| 374 | const char * const ssl_crlfile = ssl_config->primary.CRLfile; |
| 375 | const char *hostname = connssl->peer.hostname; |
| 376 | int ret = -1; |
| 377 | char errorbuf[128]; |
| 378 | |
| 379 | DEBUGASSERT(backend); |
| 380 | |
| 381 | if((conn_config->version == CURL_SSLVERSION_SSLv2) || |
| 382 | (conn_config->version == CURL_SSLVERSION_SSLv3)) { |
| 383 | failf(data, "Not supported SSL version"); |
| 384 | return CURLE_NOT_BUILT_IN; |
| 385 | } |
| 386 | |
| 387 | #ifdef THREADING_SUPPORT |
| 388 | mbedtls_ctr_drbg_init(&backend->ctr_drbg); |
| 389 | |
| 390 | ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex, |
| 391 | &ts_entropy, NULL, 0); |
| 392 | if(ret) { |
| 393 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
| 394 | failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s", |
| 395 | -ret, errorbuf); |
| 396 | return CURLE_FAILED_INIT; |
| 397 | } |
| 398 | #else |
| 399 | mbedtls_entropy_init(&backend->entropy); |
| 400 | mbedtls_ctr_drbg_init(&backend->ctr_drbg); |
| 401 | |
| 402 | ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, mbedtls_entropy_func, |
| 403 | &backend->entropy, NULL, 0); |
| 404 | if(ret) { |
| 405 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
| 406 | failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s", |
| 407 | -ret, errorbuf); |
| 408 | return CURLE_FAILED_INIT; |
| 409 | } |
| 410 | #endif /* THREADING_SUPPORT */ |
| 411 | |
| 412 | /* Load the trusted CA */ |
| 413 | mbedtls_x509_crt_init(&backend->cacert); |
| 414 | |
| 415 | if(ca_info_blob && verifypeer) { |
| 416 | /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null |
| 417 | terminated even when provided the exact length, forcing us to waste |
| 418 | extra memory here. */ |
| 419 | unsigned char *newblob = Curl_memdup0(ca_info_blob->data, |
| 420 | ca_info_blob->len); |
| 421 | if(!newblob) |
| 422 | return CURLE_OUT_OF_MEMORY; |
| 423 | ret = mbedtls_x509_crt_parse(&backend->cacert, newblob, |
| 424 | ca_info_blob->len + 1); |
| 425 | free(newblob); |
| 426 | if(ret<0) { |
| 427 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
| 428 | failf(data, "Error importing ca cert blob - mbedTLS: (-0x%04X) %s", |
| 429 | -ret, errorbuf); |
| 430 | return CURLE_SSL_CERTPROBLEM; |
| 431 | } |
| 432 | } |
| 433 | |
| 434 | if(ssl_cafile && verifypeer) { |
| 435 | #ifdef MBEDTLS_FS_IO |
| 436 | ret = mbedtls_x509_crt_parse_file(&backend->cacert, ssl_cafile); |
| 437 | |
| 438 | if(ret<0) { |
| 439 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
| 440 | failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s", |
| 441 | ssl_cafile, -ret, errorbuf); |
| 442 | return CURLE_SSL_CACERT_BADFILE; |
| 443 | } |
| 444 | #else |
| 445 | failf(data, "mbedtls: functions that use the filesystem not built in"); |
| 446 | return CURLE_NOT_BUILT_IN; |
| 447 | #endif |
| 448 | } |
| 449 | |
| 450 | if(ssl_capath) { |
| 451 | #ifdef MBEDTLS_FS_IO |
| 452 | ret = mbedtls_x509_crt_parse_path(&backend->cacert, ssl_capath); |
| 453 | |
| 454 | if(ret<0) { |
| 455 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
| 456 | failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s", |
| 457 | ssl_capath, -ret, errorbuf); |
| 458 | |
| 459 | if(verifypeer) |
| 460 | return CURLE_SSL_CACERT_BADFILE; |
| 461 | } |
| 462 | #else |
| 463 | failf(data, "mbedtls: functions that use the filesystem not built in"); |
| 464 | return CURLE_NOT_BUILT_IN; |
| 465 | #endif |
| 466 | } |
| 467 | |
| 468 | /* Load the client certificate */ |
| 469 | mbedtls_x509_crt_init(&backend->clicert); |
| 470 | |
| 471 | if(ssl_cert) { |
| 472 | #ifdef MBEDTLS_FS_IO |
| 473 | ret = mbedtls_x509_crt_parse_file(&backend->clicert, ssl_cert); |
| 474 | |
| 475 | if(ret) { |
| 476 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
| 477 | failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s", |
| 478 | ssl_cert, -ret, errorbuf); |
| 479 | |
| 480 | return CURLE_SSL_CERTPROBLEM; |
| 481 | } |
| 482 | #else |
| 483 | failf(data, "mbedtls: functions that use the filesystem not built in"); |
| 484 | return CURLE_NOT_BUILT_IN; |
| 485 | #endif |
| 486 | } |
| 487 | |
| 488 | if(ssl_cert_blob) { |
| 489 | /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null |
| 490 | terminated even when provided the exact length, forcing us to waste |
| 491 | extra memory here. */ |
| 492 | unsigned char *newblob = Curl_memdup0(ssl_cert_blob->data, |
| 493 | ssl_cert_blob->len); |
| 494 | if(!newblob) |
| 495 | return CURLE_OUT_OF_MEMORY; |
| 496 | ret = mbedtls_x509_crt_parse(&backend->clicert, newblob, |
| 497 | ssl_cert_blob->len + 1); |
| 498 | free(newblob); |
| 499 | |
| 500 | if(ret) { |
| 501 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
| 502 | failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s", |
| 503 | ssl_config->key, -ret, errorbuf); |
| 504 | return CURLE_SSL_CERTPROBLEM; |
| 505 | } |
| 506 | } |
| 507 | |
| 508 | /* Load the client private key */ |
| 509 | mbedtls_pk_init(&backend->pk); |
| 510 | |
| 511 | if(ssl_config->key || ssl_config->key_blob) { |
| 512 | if(ssl_config->key) { |
| 513 | #ifdef MBEDTLS_FS_IO |
| 514 | #if MBEDTLS_VERSION_NUMBER >= 0x03000000 |
| 515 | ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key, |
| 516 | ssl_config->key_passwd, |
| 517 | mbedtls_ctr_drbg_random, |
| 518 | &backend->ctr_drbg); |
| 1552 | CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf) |
| 1553 | { |
| 1554 | struct ssl_connect_data *connssl = cf->ctx; |
| 1555 | const char *ehostname, *edispname; |
| 1556 | int eport; |
| 1557 | |
| 1558 | /* We need the hostname for SNI negotiation. Once handshaked, this |
| 1559 | * remains the SNI hostname for the TLS connection. But when the |
| 1560 | * connection is reused, the settings in cf->conn might change. |
| 1561 | * So we keep a copy of the hostname we use for SNI. |
| 1562 | */ |
| 1563 | #ifndef CURL_DISABLE_PROXY |
| 1564 | if(Curl_ssl_cf_is_proxy(cf)) { |
| 1565 | ehostname = cf->conn->http_proxy.host.name; |
| 1566 | edispname = cf->conn->http_proxy.host.dispname; |
| 1567 | eport = cf->conn->http_proxy.port; |
| 1568 | } |
| 1569 | else |
| 1570 | #endif |
| 1571 | { |
| 1572 | ehostname = cf->conn->host.name; |
| 1573 | edispname = cf->conn->host.dispname; |
| 1574 | eport = cf->conn->remote_port; |
| 1575 | } |
| 1576 | |
| 1577 | /* change if ehostname changed */ |
| 1578 | DEBUGASSERT(!ehostname || ehostname[0]); |
| 1579 | if(ehostname && (!peer->hostname |
| 1580 | || strcmp(ehostname, peer->hostname))) { |
| 1581 | Curl_ssl_peer_cleanup(peer); |
| 1582 | peer->hostname = strdup(ehostname); |
| 1583 | if(!peer->hostname) { |
| 1584 | Curl_ssl_peer_cleanup(peer); |
| 1585 | return CURLE_OUT_OF_MEMORY; |
| 1586 | } |
| 1587 | if(!edispname || !strcmp(ehostname, edispname)) |
| 1588 | peer->dispname = peer->hostname; |
| 1589 | else { |
| C1: sni only allocated when !peer->is_ip_address | |
| C5: IP address hostnames skip sni allocation, leading to missing mbedtls_ssl_set_hostname call | |
| 1590 | peer->dispname = strdup(edispname); |
| 1591 | if(!peer->dispname) { |
| 1592 | Curl_ssl_peer_cleanup(peer); |
| 1593 | return CURLE_OUT_OF_MEMORY; |
| 1594 | } |
| 1595 | } |
| 1596 | |
| C1: peer->sni = calloc(...) only for DNS names | |
| 1597 | peer->sni = NULL; |
| C1: peer->sni = NULL; initialized to NULL | |
| 1598 | peer->type = get_peer_type(peer->hostname); |
| C1: peer->is_ip_address set based on hostname | |
| 1599 | if(peer->type == CURL_SSL_PEER_DNS && peer->hostname[0]) { |
| 1600 | /* not an IP address, normalize according to RCC 6066 ch. 3, |
| 1601 | * max len of SNI is 2^16-1, no trailing dot */ |
| 1602 | size_t len = strlen(peer->hostname); |
| 1603 | if(len && (peer->hostname[len-1] == '.')) |
| 1604 | len--; |
| 1605 | if(len < USHRT_MAX) { |
| 1606 | peer->sni = calloc(1, len + 1); |
| 1607 | if(!peer->sni) { |
| 1608 | Curl_ssl_peer_cleanup(peer); |
| 1609 | return CURLE_OUT_OF_MEMORY; |
| 1610 | } |
| 1611 | Curl_strntolower(peer->sni, peer->hostname, len); |
| 1612 | peer->sni[len] = 0; |
| 1613 | } |
| 1614 | } |
| 1615 | |
| 1616 | } |
| 1617 | connssl->port = eport; |
| 1618 | return CURLE_OK; |
| 1619 | } |
| 1533 | static ssl_peer_type get_peer_type(const char *hostname) |
| 1534 | { |
| 1535 | if(hostname && hostname[0]) { |
| 1536 | #ifdef ENABLE_IPV6 |
| 1537 | struct in6_addr addr; |
| 1538 | #else |
| 1539 | struct in_addr addr; |
| 1540 | #endif |
| 1541 | if(Curl_inet_pton(AF_INET, hostname, &addr)) |
| C3: CURL_SSL_PEER_IPV4 returned for IPv4 addresses | |
| 1542 | return CURL_SSL_PEER_IPV4; |
| 1543 | #ifdef ENABLE_IPV6 |
| 1544 | else if(Curl_inet_pton(AF_INET6, hostname, &addr)) { |
| 1545 | return CURL_SSL_PEER_IPV6; |
| C3: CURL_SSL_PEER_IPV6 returned for IPv6 addresses | |
| 1546 | } |
| 1547 | #endif |
| 1548 | } |
| 1549 | return CURL_SSL_PEER_DNS; |
| 1550 | } |
Show 161 lines (not cited by the judge)
| 324 | static CURLcode |
| 325 | mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) |
| 326 | { |
| 327 | struct ssl_connect_data *connssl = cf->ctx; |
| 328 | struct mbed_ssl_backend_data *backend = |
| 329 | (struct mbed_ssl_backend_data *)connssl->backend; |
| 330 | struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); |
| 331 | const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; |
| 332 | struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); |
| 333 | const char * const ssl_cafile = |
| 334 | /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ |
| 335 | (ca_info_blob ? NULL : conn_config->CAfile); |
| 336 | const bool verifypeer = conn_config->verifypeer; |
| 337 | const char * const ssl_capath = conn_config->CApath; |
| 338 | char * const ssl_cert = ssl_config->primary.clientcert; |
| 339 | const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob; |
| 340 | const char * const ssl_crlfile = ssl_config->primary.CRLfile; |
| 341 | const char *hostname = connssl->peer.hostname; |
| 342 | int ret = -1; |
| 343 | char errorbuf[128]; |
| 344 | |
| 345 | DEBUGASSERT(backend); |
| 346 | |
| 347 | if((conn_config->version == CURL_SSLVERSION_SSLv2) || |
| 348 | (conn_config->version == CURL_SSLVERSION_SSLv3)) { |
| 349 | failf(data, "Not supported SSL version"); |
| 350 | return CURLE_NOT_BUILT_IN; |
| 351 | } |
| 352 | |
| 353 | #ifdef THREADING_SUPPORT |
| 354 | entropy_init_mutex(&ts_entropy); |
| 355 | mbedtls_ctr_drbg_init(&backend->ctr_drbg); |
| 356 | |
| 357 | ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex, |
| 358 | &ts_entropy, NULL, 0); |
| 359 | if(ret) { |
| 360 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
| 361 | failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s", |
| 362 | -ret, errorbuf); |
| 363 | return CURLE_FAILED_INIT; |
| 364 | } |
| 365 | #else |
| 366 | mbedtls_entropy_init(&backend->entropy); |
| 367 | mbedtls_ctr_drbg_init(&backend->ctr_drbg); |
| 368 | |
| 369 | ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, mbedtls_entropy_func, |
| 370 | &backend->entropy, NULL, 0); |
| 371 | if(ret) { |
| 372 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
| 373 | failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s", |
| 374 | -ret, errorbuf); |
| 375 | return CURLE_FAILED_INIT; |
| 376 | } |
| 377 | #endif /* THREADING_SUPPORT */ |
| 378 | |
| 379 | /* Load the trusted CA */ |
| 380 | mbedtls_x509_crt_init(&backend->cacert); |
| 381 | |
| 382 | if(ca_info_blob && verifypeer) { |
| 383 | /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null |
| 384 | terminated even when provided the exact length, forcing us to waste |
| 385 | extra memory here. */ |
| 386 | unsigned char *newblob = Curl_memdup0(ca_info_blob->data, |
| 387 | ca_info_blob->len); |
| 388 | if(!newblob) |
| 389 | return CURLE_OUT_OF_MEMORY; |
| 390 | ret = mbedtls_x509_crt_parse(&backend->cacert, newblob, |
| 391 | ca_info_blob->len + 1); |
| 392 | free(newblob); |
| 393 | if(ret<0) { |
| 394 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
| 395 | failf(data, "Error importing ca cert blob - mbedTLS: (-0x%04X) %s", |
| 396 | -ret, errorbuf); |
| 397 | return CURLE_SSL_CERTPROBLEM; |
| 398 | } |
| 399 | } |
| 400 | |
| 401 | if(ssl_cafile && verifypeer) { |
| 402 | #ifdef MBEDTLS_FS_IO |
| 403 | ret = mbedtls_x509_crt_parse_file(&backend->cacert, ssl_cafile); |
| 404 | |
| 405 | if(ret<0) { |
| 406 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
| 407 | failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s", |
| 408 | ssl_cafile, -ret, errorbuf); |
| 409 | return CURLE_SSL_CACERT_BADFILE; |
| 410 | } |
| 411 | #else |
| 412 | failf(data, "mbedtls: functions that use the filesystem not built in"); |
| 413 | return CURLE_NOT_BUILT_IN; |
| 414 | #endif |
| 415 | } |
| 416 | |
| 417 | if(ssl_capath) { |
| 418 | #ifdef MBEDTLS_FS_IO |
| 419 | ret = mbedtls_x509_crt_parse_path(&backend->cacert, ssl_capath); |
| 420 | |
| 421 | if(ret<0) { |
| 422 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
| 423 | failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s", |
| 424 | ssl_capath, -ret, errorbuf); |
| 425 | |
| 426 | if(verifypeer) |
| 427 | return CURLE_SSL_CACERT_BADFILE; |
| 428 | } |
| 429 | #else |
| 430 | failf(data, "mbedtls: functions that use the filesystem not built in"); |
| 431 | return CURLE_NOT_BUILT_IN; |
| 432 | #endif |
| 433 | } |
| 434 | |
| 435 | /* Load the client certificate */ |
| 436 | mbedtls_x509_crt_init(&backend->clicert); |
| 437 | |
| 438 | if(ssl_cert) { |
| 439 | #ifdef MBEDTLS_FS_IO |
| 440 | ret = mbedtls_x509_crt_parse_file(&backend->clicert, ssl_cert); |
| 441 | |
| 442 | if(ret) { |
| 443 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
| 444 | failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s", |
| 445 | ssl_cert, -ret, errorbuf); |
| 446 | |
| 447 | return CURLE_SSL_CERTPROBLEM; |
| 448 | } |
| 449 | #else |
| 450 | failf(data, "mbedtls: functions that use the filesystem not built in"); |
| 451 | return CURLE_NOT_BUILT_IN; |
| 452 | #endif |
| 453 | } |
| 454 | |
| 455 | if(ssl_cert_blob) { |
| 456 | /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null |
| 457 | terminated even when provided the exact length, forcing us to waste |
| 458 | extra memory here. */ |
| 459 | unsigned char *newblob = Curl_memdup0(ssl_cert_blob->data, |
| 460 | ssl_cert_blob->len); |
| 461 | if(!newblob) |
| 462 | return CURLE_OUT_OF_MEMORY; |
| 463 | ret = mbedtls_x509_crt_parse(&backend->clicert, newblob, |
| 464 | ssl_cert_blob->len + 1); |
| 465 | free(newblob); |
| 466 | |
| 467 | if(ret) { |
| 468 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
| 469 | failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s", |
| 470 | ssl_config->key, -ret, errorbuf); |
| 471 | return CURLE_SSL_CERTPROBLEM; |
| 472 | } |
| 473 | } |
| 474 | |
| 475 | /* Load the client private key */ |
| 476 | mbedtls_pk_init(&backend->pk); |
| 477 | |
| 478 | if(ssl_config->key || ssl_config->key_blob) { |
| 479 | if(ssl_config->key) { |
| 480 | #ifdef MBEDTLS_FS_IO |
| 481 | #if MBEDTLS_VERSION_NUMBER >= 0x03000000 |
| 482 | ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key, |
| 483 | ssl_config->key_passwd, |
| 484 | mbedtls_ctr_drbg_random, |
Show 9 lines (not cited by the judge)
| 1512 | void Curl_ssl_peer_cleanup(struct ssl_peer *peer) |
| 1513 | { |
| 1514 | if(peer->dispname != peer->hostname) |
| 1515 | free(peer->dispname); |
| 1516 | free(peer->sni); |
| 1517 | free(peer->hostname); |
| 1518 | peer->hostname = peer->sni = peer->dispname = NULL; |
| 1519 | peer->type = CURL_SSL_PEER_DNS; |
| 1520 | } |
Show 9 lines (not cited by the judge)
| 1508 | void Curl_ssl_peer_cleanup(struct ssl_peer *peer) |
| 1509 | { |
| 1510 | if(peer->dispname != peer->hostname) |
| 1511 | free(peer->dispname); |
| 1512 | free(peer->sni); |
| 1513 | free(peer->hostname); |
| 1514 | peer->hostname = peer->sni = peer->dispname = NULL; |
| 1515 | peer->is_ip_address = FALSE; |
| 1516 | } |
Show 67 lines (not cited by the judge)
| 1543 | CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf) |
| 1544 | { |
| 1545 | struct ssl_connect_data *connssl = cf->ctx; |
| 1546 | const char *ehostname, *edispname; |
| 1547 | int eport; |
| 1548 | |
| 1549 | /* We need the hostname for SNI negotiation. Once handshaked, this |
| 1550 | * remains the SNI hostname for the TLS connection. But when the |
| 1551 | * connection is reused, the settings in cf->conn might change. |
| 1552 | * So we keep a copy of the hostname we use for SNI. |
| 1553 | */ |
| 1554 | #ifndef CURL_DISABLE_PROXY |
| 1555 | if(Curl_ssl_cf_is_proxy(cf)) { |
| 1556 | ehostname = cf->conn->http_proxy.host.name; |
| 1557 | edispname = cf->conn->http_proxy.host.dispname; |
| 1558 | eport = cf->conn->http_proxy.port; |
| 1559 | } |
| 1560 | else |
| 1561 | #endif |
| 1562 | { |
| 1563 | ehostname = cf->conn->host.name; |
| 1564 | edispname = cf->conn->host.dispname; |
| 1565 | eport = cf->conn->remote_port; |
| 1566 | } |
| 1567 | |
| 1568 | /* change if ehostname changed */ |
| 1569 | if(ehostname && (!peer->hostname |
| 1570 | || strcmp(ehostname, peer->hostname))) { |
| 1571 | Curl_ssl_peer_cleanup(peer); |
| 1572 | peer->hostname = strdup(ehostname); |
| 1573 | if(!peer->hostname) { |
| 1574 | Curl_ssl_peer_cleanup(peer); |
| 1575 | return CURLE_OUT_OF_MEMORY; |
| 1576 | } |
| 1577 | if(!edispname || !strcmp(ehostname, edispname)) |
| 1578 | peer->dispname = peer->hostname; |
| 1579 | else { |
| 1580 | peer->dispname = strdup(edispname); |
| 1581 | if(!peer->dispname) { |
| 1582 | Curl_ssl_peer_cleanup(peer); |
| 1583 | return CURLE_OUT_OF_MEMORY; |
| 1584 | } |
| 1585 | } |
| 1586 | |
| 1587 | peer->sni = NULL; |
| 1588 | peer->is_ip_address = is_ip_address(peer->hostname)? TRUE : FALSE; |
| 1589 | if(peer->hostname[0] && !peer->is_ip_address) { |
| 1590 | /* not an IP address, normalize according to RCC 6066 ch. 3, |
| 1591 | * max len of SNI is 2^16-1, no trailing dot */ |
| 1592 | size_t len = strlen(peer->hostname); |
| 1593 | if(len && (peer->hostname[len-1] == '.')) |
| 1594 | len--; |
| 1595 | if(len < USHRT_MAX) { |
| 1596 | peer->sni = calloc(1, len + 1); |
| 1597 | if(!peer->sni) { |
| 1598 | Curl_ssl_peer_cleanup(peer); |
| 1599 | return CURLE_OUT_OF_MEMORY; |
| 1600 | } |
| 1601 | Curl_strntolower(peer->sni, peer->hostname, len); |
| 1602 | peer->sni[len] = 0; |
| 1603 | } |
| 1604 | } |
| 1605 | |
| 1606 | } |
| 1607 | connssl->port = eport; |
| 1608 | return CURLE_OK; |
| 1609 | } |
Show 9 lines (not cited by the judge)
| 164 | void Curl_strntolower(char *dest, const char *src, size_t n) |
| 165 | { |
| 166 | if(n < 1) |
| 167 | return; |
| 168 | |
| 169 | do { |
| 170 | *dest++ = Curl_raw_tolower(*src); |
| 171 | } while(*src++ && --n); |
| 172 | } |
Show 1 lines (not cited by the judge)
| 63 | #define failf Curl_failf |