From: Daniel McCarney Date: Fri, 21 Mar 2025 18:43:07 +0000 (-0400) Subject: rustls: tidy up X-Git-Tag: curl-8_13_0~69 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=088f0e6a5b8d934073a0e089ebecd14ca75120c4;p=thirdparty%2Fcurl.git rustls: tidy up Closes #16796 --- diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c index 963d23d1fc..6117ada0d2 100644 --- a/lib/vtls/rustls.c +++ b/lib/vtls/rustls.c @@ -8,6 +8,7 @@ * Copyright (C) Jacob Hoffman-Andrews, * * Copyright (C) kpcyrd, + * Copyright (C) Daniel McCarney, * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -37,12 +38,8 @@ #include "vtls.h" #include "vtls_int.h" #include "rustls.h" -#include "select.h" #include "strerror.h" -#include "multiif.h" -#include "connect.h" /* for the connect timeout */ #include "cipher_suite.h" -#include "rand.h" #include "x509asn1.h" struct rustls_ssl_backend_data @@ -55,7 +52,7 @@ struct rustls_ssl_backend_data }; /* For a given rustls_result error code, return the best-matching CURLcode. */ -static CURLcode map_error(rustls_result r) +static CURLcode map_error(const rustls_result r) { if(rustls_result_is_cert_error(r)) { return CURLE_PEER_FAILED_VERIFICATION; @@ -70,10 +67,19 @@ static CURLcode map_error(rustls_result r) } } +static void +rustls_failf(struct Curl_easy *data, const rustls_result rr, const char *msg) +{ + char errorbuf[STRERROR_LEN]; + size_t errorlen; + rustls_error(rr, errorbuf, sizeof(errorbuf), &errorlen); + failf(data, "%s: %.*s", msg, (int)errorlen, errorbuf); +} + static bool cr_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data) { - struct ssl_connect_data *ctx = cf->ctx; + const struct ssl_connect_data *ctx = cf->ctx; struct rustls_ssl_backend_data *backend; (void)data; @@ -90,7 +96,7 @@ struct io_ctx { static int read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n) { - struct io_ctx *io_ctx = userdata; + const struct io_ctx *io_ctx = userdata; struct ssl_connect_data *const connssl = io_ctx->cf->ctx; CURLcode result; int ret = 0; @@ -115,7 +121,7 @@ read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n) static int write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n) { - struct io_ctx *io_ctx = userdata; + const struct io_ctx *io_ctx = userdata; CURLcode result; int ret = 0; ssize_t nwritten = Curl_conn_cf_send(io_ctx->cf->next, io_ctx->data, @@ -137,7 +143,7 @@ write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n) static ssize_t tls_recv_more(struct Curl_cfilter *cf, struct Curl_easy *data, CURLcode *err) { - struct ssl_connect_data *const connssl = cf->ctx; + const struct ssl_connect_data *const connssl = cf->ctx; struct rustls_ssl_backend_data *const backend = (struct rustls_ssl_backend_data *)connssl->backend; struct io_ctx io_ctx; @@ -163,11 +169,7 @@ static ssize_t tls_recv_more(struct Curl_cfilter *cf, rresult = rustls_connection_process_new_packets(backend->conn); if(rresult != RUSTLS_RESULT_OK) { - char errorbuf[255]; - size_t errorlen; - rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen); - failf(data, "rustls_connection_process_new_packets: %.*s", - (int)errorlen, errorbuf); + rustls_failf(data, rresult, "rustls_connection_process_new_packets"); *err = map_error(rresult); return -1; } @@ -193,7 +195,7 @@ static ssize_t cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data, char *plainbuf, size_t plainlen, CURLcode *err) { - struct ssl_connect_data *const connssl = cf->ctx; + const struct ssl_connect_data *const connssl = cf->ctx; struct rustls_ssl_backend_data *const backend = (struct rustls_ssl_backend_data *)connssl->backend; struct rustls_connection *rconn = NULL; @@ -233,10 +235,7 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data, } else if(rresult != RUSTLS_RESULT_OK) { /* n always equals 0 in this case, do not need to check it */ - char errorbuf[255]; - size_t errorlen; - rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen); - failf(data, "rustls_connection_read: %.*s", (int)errorlen, errorbuf); + rustls_failf(data, rresult, "rustls_connection_read"); *err = CURLE_RECV_ERROR; nread = -1; goto out; @@ -279,7 +278,6 @@ static CURLcode cr_flush_out(struct Curl_cfilter *cf, struct Curl_easy *data, rustls_io_result io_error; size_t tlswritten = 0; size_t tlswritten_total = 0; - CURLcode result = CURLE_OK; io_ctx.cf = cf; io_ctx.data = data; @@ -305,7 +303,7 @@ static CURLcode cr_flush_out(struct Curl_cfilter *cf, struct Curl_easy *data, CURL_TRC_CF(data, cf, "cf_send: wrote %zu TLS bytes", tlswritten); tlswritten_total += tlswritten; } - return result; + return CURLE_OK; } /* @@ -322,14 +320,11 @@ static ssize_t cr_send(struct Curl_cfilter *cf, struct Curl_easy *data, const void *plainbuf, size_t plainlen, CURLcode *err) { - struct ssl_connect_data *const connssl = cf->ctx; + const struct ssl_connect_data *const connssl = cf->ctx; struct rustls_ssl_backend_data *const backend = (struct rustls_ssl_backend_data *)connssl->backend; struct rustls_connection *rconn = NULL; size_t plainwritten = 0; - rustls_result rresult; - char errorbuf[256]; - size_t errorlen; const unsigned char *buf = plainbuf; size_t blen = plainlen; ssize_t nwritten = 0; @@ -361,11 +356,11 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data, } if(blen > 0) { + rustls_result rresult; CURL_TRC_CF(data, cf, "cf_send: adding %zu plain bytes to Rustls", blen); rresult = rustls_connection_write(rconn, buf, blen, &plainwritten); if(rresult != RUSTLS_RESULT_OK) { - rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen); - failf(data, "rustls_connection_write: %.*s", (int)errorlen, errorbuf); + rustls_failf(data, rresult, "rustls_connection_write"); *err = CURLE_WRITE_ERROR; return -1; } @@ -419,7 +414,7 @@ read_file_into(const char *filename, while(!feof(f)) { uint8_t buf[256]; - size_t rr = fread(buf, 1, sizeof(buf), f); + const size_t rr = fread(buf, 1, sizeof(buf), f); if(rr == 0 || CURLE_OK != Curl_dyn_addn(out, buf, rr)) { fclose(f); @@ -437,8 +432,8 @@ cr_get_selected_ciphers(struct Curl_easy *data, const struct rustls_supported_ciphersuite **selected, size_t *selected_size) { - size_t supported_len = *selected_size; - size_t default_len = rustls_default_crypto_provider_ciphersuites_len(); + const size_t supported_len = *selected_size; + const size_t default_len = rustls_default_crypto_provider_ciphersuites_len(); const struct rustls_supported_ciphersuite *entry; const char *ciphers = ciphers12; size_t count = 0, default13_count = 0, i, j; @@ -524,246 +519,329 @@ add_ciphers: } static CURLcode -cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, - struct rustls_ssl_backend_data *const backend) +init_config_builder(struct Curl_easy *data, + const struct ssl_primary_config *conn_config, + struct rustls_client_config_builder **config_builder) { - struct ssl_connect_data *connssl = cf->ctx; - struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); + const struct rustls_supported_ciphersuite **cipher_suites = NULL; struct rustls_crypto_provider_builder *custom_provider_builder = NULL; const struct rustls_crypto_provider *custom_provider = NULL; - struct rustls_connection *rconn = NULL; - struct rustls_client_config_builder *config_builder = NULL; - const struct rustls_root_cert_store *roots = NULL; - struct rustls_root_cert_store_builder *roots_builder = NULL; - struct rustls_web_pki_server_cert_verifier_builder *verifier_builder = NULL; - struct rustls_server_cert_verifier *server_cert_verifier = NULL; - const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; - const char * const ssl_cafile = - /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ - (ca_info_blob ? NULL : conn_config->CAfile); - const bool verifypeer = conn_config->verifypeer; - char errorbuf[256]; - size_t errorlen; - rustls_result result; - DEBUGASSERT(backend); - rconn = backend->conn; + uint16_t tls_versions[2] = { + RUSTLS_TLS_VERSION_TLSV1_2, + RUSTLS_TLS_VERSION_TLSV1_3, + }; + size_t tls_versions_len = 2; + size_t cipher_suites_len = + rustls_default_crypto_provider_ciphersuites_len(); - { - uint16_t tls_versions[2] = { - RUSTLS_TLS_VERSION_TLSV1_2, - RUSTLS_TLS_VERSION_TLSV1_3, - }; - size_t tls_versions_len = 2; - const struct rustls_supported_ciphersuite **cipher_suites; - size_t cipher_suites_len = - rustls_default_crypto_provider_ciphersuites_len(); - - switch(conn_config->version) { - case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1: - case CURL_SSLVERSION_TLSv1_0: - case CURL_SSLVERSION_TLSv1_1: - case CURL_SSLVERSION_TLSv1_2: - break; - case CURL_SSLVERSION_TLSv1_3: - tls_versions[0] = RUSTLS_TLS_VERSION_TLSV1_3; + CURLcode result = CURLE_OK; + rustls_result rr; + + switch(conn_config->version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + break; + case CURL_SSLVERSION_TLSv1_3: + tls_versions[0] = RUSTLS_TLS_VERSION_TLSV1_3; + tls_versions_len = 1; + break; + default: + failf(data, "rustls: unsupported minimum TLS version value"); + result = CURLE_BAD_FUNCTION_ARGUMENT; + goto cleanup; + } + + switch(conn_config->version_max) { + case CURL_SSLVERSION_MAX_DEFAULT: + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_TLSv1_3: + break; + case CURL_SSLVERSION_MAX_TLSv1_2: + if(tls_versions[0] == RUSTLS_TLS_VERSION_TLSV1_2) { tls_versions_len = 1; break; - default: - failf(data, "rustls: unsupported minimum TLS version value"); - return CURLE_BAD_FUNCTION_ARGUMENT; } + FALLTHROUGH(); + case CURL_SSLVERSION_MAX_TLSv1_1: + case CURL_SSLVERSION_MAX_TLSv1_0: + default: + failf(data, "rustls: unsupported maximum TLS version value"); + result = CURLE_BAD_FUNCTION_ARGUMENT; + goto cleanup; + } - switch(conn_config->version_max) { - case CURL_SSLVERSION_MAX_DEFAULT: - case CURL_SSLVERSION_MAX_NONE: - case CURL_SSLVERSION_MAX_TLSv1_3: - break; - case CURL_SSLVERSION_MAX_TLSv1_2: - if(tls_versions[0] == RUSTLS_TLS_VERSION_TLSV1_2) { - tls_versions_len = 1; - break; - } - FALLTHROUGH(); - case CURL_SSLVERSION_MAX_TLSv1_1: - case CURL_SSLVERSION_MAX_TLSv1_0: - default: - failf(data, "rustls: unsupported maximum TLS version value"); - return CURLE_BAD_FUNCTION_ARGUMENT; - } + cipher_suites = malloc(sizeof(cipher_suites) * (cipher_suites_len)); + if(!cipher_suites) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } - cipher_suites = malloc(sizeof(cipher_suites) * (cipher_suites_len)); - if(!cipher_suites) - return CURLE_OUT_OF_MEMORY; - - cr_get_selected_ciphers(data, - conn_config->cipher_list, - conn_config->cipher_list13, - cipher_suites, &cipher_suites_len); - if(cipher_suites_len == 0) { - failf(data, "rustls: no supported cipher in list"); - free(cipher_suites); - return CURLE_SSL_CIPHER; - } + cr_get_selected_ciphers(data, + conn_config->cipher_list, + conn_config->cipher_list13, + cipher_suites, &cipher_suites_len); + if(cipher_suites_len == 0) { + failf(data, "rustls: no supported cipher in list"); + result = CURLE_SSL_CIPHER; + goto cleanup; + } - result = rustls_crypto_provider_builder_new_from_default( - &custom_provider_builder); - if(result != RUSTLS_RESULT_OK) { - failf(data, - "rustls: failed to create crypto provider builder from default"); - return CURLE_SSL_CIPHER; - } + rr = rustls_crypto_provider_builder_new_from_default( + &custom_provider_builder); + if(rr != RUSTLS_RESULT_OK) { + rustls_failf(data, rr, + "failed to create crypto provider builder from default"); + result = CURLE_SSL_CIPHER; + goto cleanup; + } - result = - rustls_crypto_provider_builder_set_cipher_suites( - custom_provider_builder, - cipher_suites, - cipher_suites_len); - if(result != RUSTLS_RESULT_OK) { - failf(data, - "rustls: failed to set ciphersuites for crypto provider builder"); - rustls_crypto_provider_builder_free(custom_provider_builder); - return CURLE_SSL_CIPHER; - } + rr = + rustls_crypto_provider_builder_set_cipher_suites( + custom_provider_builder, + cipher_suites, + cipher_suites_len); + if(rr != RUSTLS_RESULT_OK) { + rustls_failf(data, rr, + "failed to set ciphersuites for crypto provider builder"); + result = CURLE_SSL_CIPHER; + goto cleanup; + } - result = rustls_crypto_provider_builder_build( - custom_provider_builder, &custom_provider); - if(result != RUSTLS_RESULT_OK) { - failf(data, "rustls: failed to build custom crypto provider"); - rustls_crypto_provider_builder_free(custom_provider_builder); - return CURLE_SSL_CIPHER; - } + rr = rustls_crypto_provider_builder_build( + custom_provider_builder, &custom_provider); + if(rr != RUSTLS_RESULT_OK) { + rustls_failf(data, rr, "failed to build custom crypto provider"); + result = CURLE_SSL_CIPHER; + goto cleanup; + } - result = rustls_client_config_builder_new_custom(custom_provider, + rr = rustls_client_config_builder_new_custom(custom_provider, tls_versions, tls_versions_len, - &config_builder); + config_builder); + if(rr != RUSTLS_RESULT_OK) { + rustls_failf(data, rr, "failed to create client config builder"); + result = CURLE_SSL_CIPHER; + goto cleanup; + } + +cleanup: + if(cipher_suites) { free(cipher_suites); - if(result != RUSTLS_RESULT_OK) { - failf(data, "rustls: failed to create client config"); - return CURLE_SSL_CIPHER; - } } + if(custom_provider_builder) { + rustls_crypto_provider_builder_free(custom_provider_builder); + } + if(custom_provider) { + rustls_crypto_provider_free(custom_provider); + } + return result; +} - rustls_crypto_provider_builder_free(custom_provider_builder); - rustls_crypto_provider_free(custom_provider); +static void +init_config_builder_alpn(struct Curl_easy *data, + const struct ssl_connect_data *connssl, + struct rustls_client_config_builder *config_builder) { + struct alpn_proto_buf proto; + rustls_slice_bytes alpn[ALPN_ENTRIES_MAX]; + size_t i; - if(connssl->alpn) { - struct alpn_proto_buf proto; - rustls_slice_bytes alpn[ALPN_ENTRIES_MAX]; - size_t i; + for(i = 0; i < connssl->alpn->count; ++i) { + alpn[i].data = (const uint8_t *)connssl->alpn->entries[i]; + alpn[i].len = strlen(connssl->alpn->entries[i]); + } + rustls_client_config_builder_set_alpn_protocols(config_builder, alpn, + connssl->alpn->count); + Curl_alpn_to_proto_str(&proto, connssl->alpn); + infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data); +} - for(i = 0; i < connssl->alpn->count; ++i) { - alpn[i].data = (const uint8_t *)connssl->alpn->entries[i]; - alpn[i].len = strlen(connssl->alpn->entries[i]); - } - rustls_client_config_builder_set_alpn_protocols(config_builder, alpn, - connssl->alpn->count); - Curl_alpn_to_proto_str(&proto, connssl->alpn); - infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data); +static CURLcode +init_config_builder_verifier_crl( + struct Curl_easy *data, + const struct ssl_primary_config *conn_config, + struct rustls_web_pki_server_cert_verifier_builder *builder) +{ + CURLcode result = CURLE_OK; + struct dynbuf crl_contents; + rustls_result rr; + + Curl_dyn_init(&crl_contents, DYN_CRLFILE_SIZE); + if(!read_file_into(conn_config->CRLfile, &crl_contents)) { + failf(data, "rustls: failed to read revocation list file"); + result = CURLE_SSL_CRL_BADFILE; + goto cleanup; } - if(!verifypeer) { - rustls_client_config_builder_dangerous_set_certificate_verifier( - config_builder, cr_verify_none); + + rr = rustls_web_pki_server_cert_verifier_builder_add_crl( + builder, + Curl_dyn_uptr(&crl_contents), + Curl_dyn_len(&crl_contents)); + if(rr != RUSTLS_RESULT_OK) { + rustls_failf(data, rr, "failed to parse revocation list"); + result = CURLE_SSL_CRL_BADFILE; + goto cleanup; } - else if(ca_info_blob || ssl_cafile) { - roots_builder = rustls_root_cert_store_builder_new(); - - if(ca_info_blob) { - /* Enable strict parsing only if verification is not disabled. */ - result = rustls_root_cert_store_builder_add_pem(roots_builder, - ca_info_blob->data, - ca_info_blob->len, - verifypeer); - if(result != RUSTLS_RESULT_OK) { - failf(data, "rustls: failed to parse trusted certificates from blob"); - rustls_root_cert_store_builder_free(roots_builder); - rustls_client_config_builder_free(config_builder); - return CURLE_SSL_CACERT_BADFILE; - } + +cleanup: + Curl_dyn_free(&crl_contents); + return result; +} + +static CURLcode +init_config_builder_verifier(struct Curl_easy *data, + struct rustls_client_config_builder *builder, + const struct ssl_primary_config *conn_config, + const struct curl_blob *ca_info_blob, + const char * const ssl_cafile) { + const struct rustls_root_cert_store *roots = NULL; + struct rustls_root_cert_store_builder *roots_builder = NULL; + struct rustls_web_pki_server_cert_verifier_builder *verifier_builder = NULL; + struct rustls_server_cert_verifier *server_cert_verifier = NULL; + rustls_result rr = RUSTLS_RESULT_OK; + CURLcode result = CURLE_OK; + + roots_builder = rustls_root_cert_store_builder_new(); + if(ca_info_blob) { + rr = rustls_root_cert_store_builder_add_pem(roots_builder, + ca_info_blob->data, + ca_info_blob->len, + 1); + if(rr != RUSTLS_RESULT_OK) { + rustls_failf(data, rr, "failed to parse trusted certificates from blob"); + + result = CURLE_SSL_CACERT_BADFILE; + goto cleanup; } - else if(ssl_cafile) { - /* Enable strict parsing only if verification is not disabled. */ - result = rustls_root_cert_store_builder_load_roots_from_file( - roots_builder, ssl_cafile, verifypeer); - if(result != RUSTLS_RESULT_OK) { - failf(data, "rustls: failed to load trusted certificates"); - rustls_root_cert_store_builder_free(roots_builder); - rustls_client_config_builder_free(config_builder); - return CURLE_SSL_CACERT_BADFILE; - } + } + else if(ssl_cafile) { + rr = rustls_root_cert_store_builder_load_roots_from_file(roots_builder, + ssl_cafile, + 1); + if(rr != RUSTLS_RESULT_OK) { + rustls_failf(data, rr, "failed to load trusted certificates"); + + result = CURLE_SSL_CACERT_BADFILE; + goto cleanup; } + } - result = rustls_root_cert_store_builder_build(roots_builder, &roots); - rustls_root_cert_store_builder_free(roots_builder); - if(result != RUSTLS_RESULT_OK) { - failf(data, "rustls: failed to build trusted root certificate store"); - rustls_client_config_builder_free(config_builder); - return CURLE_SSL_CACERT_BADFILE; + rr = rustls_root_cert_store_builder_build(roots_builder, &roots); + if(rr != RUSTLS_RESULT_OK) { + rustls_failf(data, rr, "failed to build trusted root certificate store"); + result = CURLE_SSL_CACERT_BADFILE; + } + + verifier_builder = rustls_web_pki_server_cert_verifier_builder_new(roots); + + if(conn_config->CRLfile) { + result = init_config_builder_verifier_crl(data, + conn_config, + verifier_builder); + if(result != CURLE_OK) { + goto cleanup; } + } + + rr = rustls_web_pki_server_cert_verifier_builder_build( + verifier_builder, &server_cert_verifier); + if(rr != RUSTLS_RESULT_OK) { + rustls_failf(data, rr, "failed to build certificate verifier"); + result = CURLE_SSL_CACERT_BADFILE; + goto cleanup; + } - verifier_builder = rustls_web_pki_server_cert_verifier_builder_new(roots); + rustls_client_config_builder_set_server_verifier(builder, + server_cert_verifier); +cleanup: + if(roots_builder) { + rustls_root_cert_store_builder_free(roots_builder); + } + if(roots) { rustls_root_cert_store_free(roots); + } + if(verifier_builder) { + rustls_web_pki_server_cert_verifier_builder_free(verifier_builder); + } + if(server_cert_verifier) { + rustls_server_cert_verifier_free(server_cert_verifier); + } - if(conn_config->CRLfile) { - struct dynbuf crl_contents; - Curl_dyn_init(&crl_contents, DYN_CRLFILE_SIZE); - if(!read_file_into(conn_config->CRLfile, &crl_contents)) { - failf(data, "rustls: failed to read revocation list file"); - Curl_dyn_free(&crl_contents); - rustls_web_pki_server_cert_verifier_builder_free(verifier_builder); - return CURLE_SSL_CRL_BADFILE; - } + return result; +} - result = rustls_web_pki_server_cert_verifier_builder_add_crl( - verifier_builder, - Curl_dyn_uptr(&crl_contents), - Curl_dyn_len(&crl_contents)); - Curl_dyn_free(&crl_contents); - if(result != RUSTLS_RESULT_OK) { - failf(data, "rustls: failed to parse revocation list"); - rustls_web_pki_server_cert_verifier_builder_free(verifier_builder); - return CURLE_SSL_CRL_BADFILE; - } - } +static CURLcode +cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, + struct rustls_ssl_backend_data *const backend) +{ + const struct ssl_connect_data *connssl = cf->ctx; + const struct ssl_primary_config *conn_config = + Curl_ssl_cf_get_primary_config(cf); + struct rustls_connection *rconn = NULL; + struct rustls_client_config_builder *config_builder = NULL; - result = rustls_web_pki_server_cert_verifier_builder_build( - verifier_builder, &server_cert_verifier); - rustls_web_pki_server_cert_verifier_builder_free(verifier_builder); - if(result != RUSTLS_RESULT_OK) { - failf(data, "rustls: failed to build certificate verifier"); - rustls_server_cert_verifier_free(server_cert_verifier); + const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; + const char * const ssl_cafile = + /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ + (ca_info_blob ? NULL : conn_config->CAfile); + CURLcode result = CURLE_OK; + rustls_result rr; + + DEBUGASSERT(backend); + rconn = backend->conn; + + result = init_config_builder(data, conn_config, &config_builder); + if(result != CURLE_OK) { + return result; + } + + if(connssl->alpn) { + init_config_builder_alpn(data, connssl, config_builder); + } + + if(!conn_config->verifypeer) { + rustls_client_config_builder_dangerous_set_certificate_verifier( + config_builder, cr_verify_none); + } + else if(ca_info_blob || ssl_cafile) { + result = init_config_builder_verifier(data, + config_builder, + conn_config, + ca_info_blob, + ssl_cafile); + if(result != CURLE_OK) { rustls_client_config_builder_free(config_builder); - return CURLE_SSL_CACERT_BADFILE; + return result; } - - rustls_client_config_builder_set_server_verifier(config_builder, - server_cert_verifier); - rustls_server_cert_verifier_free(server_cert_verifier); } - result = rustls_client_config_builder_build( + rr = rustls_client_config_builder_build( config_builder, &backend->config); - if(result != RUSTLS_RESULT_OK) { - failf(data, "rustls: failed to build client config"); + if(rr != RUSTLS_RESULT_OK) { + rustls_failf(data, rr, "failed to build client config"); + rustls_client_config_builder_free(config_builder); rustls_client_config_free(backend->config); return CURLE_SSL_CONNECT_ERROR; } DEBUGASSERT(rconn == NULL); - result = rustls_client_connection_new(backend->config, - connssl->peer.hostname, &rconn); - if(result != RUSTLS_RESULT_OK) { - rustls_error(result, errorbuf, sizeof(errorbuf), &errorlen); - failf(data, "rustls_client_connection_new: %.*s", (int)errorlen, errorbuf); + rr = rustls_client_connection_new(backend->config, + connssl->peer.hostname, + &rconn); + if(rr != RUSTLS_RESULT_OK) { + rustls_failf(data, result, "rustls_client_connection_new"); return CURLE_COULDNT_CONNECT; } DEBUGASSERT(rconn); rustls_connection_set_userdata(rconn, backend); backend->conn = rconn; - return CURLE_OK; + + return result; } static void @@ -788,9 +866,9 @@ cr_connect(struct Curl_cfilter *cf, struct Curl_easy *data, bool *done) { struct ssl_connect_data *const connssl = cf->ctx; - struct rustls_ssl_backend_data *const backend = + const struct rustls_ssl_backend_data *const backend = (struct rustls_ssl_backend_data *)connssl->backend; - struct rustls_connection *rconn = NULL; + const struct rustls_connection *rconn = NULL; CURLcode tmperr = CURLE_OK; int result; bool wants_read; @@ -835,8 +913,10 @@ cr_connect(struct Curl_cfilter *cf, } /* REALLY Done with the handshake. */ { - uint16_t proto = rustls_connection_get_protocol_version(rconn); - uint16_t cipher = rustls_connection_get_negotiated_ciphersuite(rconn); + const uint16_t proto = + rustls_connection_get_protocol_version(rconn); + const uint16_t cipher = + rustls_connection_get_negotiated_ciphersuite(rconn); char buf[64] = ""; const char *ver = "TLS version unknown"; if(proto == RUSTLS_TLS_VERSION_TLSV1_3) @@ -944,14 +1024,13 @@ cr_get_internals(struct ssl_connect_data *connssl, static CURLcode cr_shutdown(struct Curl_cfilter *cf, struct Curl_easy *data, - bool send_shutdown, bool *done) + const bool send_shutdown, bool *done) { struct ssl_connect_data *connssl = cf->ctx; struct rustls_ssl_backend_data *backend = (struct rustls_ssl_backend_data *)connssl->backend; CURLcode result = CURLE_OK; ssize_t nwritten, nread; - char buf[1024]; size_t i; DEBUGASSERT(backend); @@ -984,6 +1063,7 @@ cr_shutdown(struct Curl_cfilter *cf, } for(i = 0; i < 10; ++i) { + char buf[1024]; nread = cr_recv(cf, data, buf, (int)sizeof(buf), &result); if(nread <= 0) break; @@ -1013,7 +1093,7 @@ out: static void cr_close(struct Curl_cfilter *cf, struct Curl_easy *data) { - struct ssl_connect_data *connssl = cf->ctx; + const struct ssl_connect_data *connssl = cf->ctx; struct rustls_ssl_backend_data *backend = (struct rustls_ssl_backend_data *)connssl->backend; @@ -1031,7 +1111,7 @@ cr_close(struct Curl_cfilter *cf, struct Curl_easy *data) static size_t cr_version(char *buffer, size_t size) { - struct rustls_str ver = rustls_version(); + const struct rustls_str ver = rustls_version(); return msnprintf(buffer, size, "%.*s", (int)ver.len, ver.data); }