From e3a4273c419b744316f0a7c97736408d5aa08a27 Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Sun, 25 Feb 2024 21:50:18 +0100 Subject: [PATCH] rustls: make curl compile with 0.12.0 Closes #12989 --- .github/workflows/linux.yml | 2 +- docs/RUSTLS.md | 4 +-- docs/TODO | 9 ------ lib/vtls/rustls.c | 64 ++++++++++++++++++++++++++----------- 4 files changed, 48 insertions(+), 31 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index b655c96379..3d447a871b 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -48,7 +48,7 @@ env: msh3-version: v0.6.0 openssl3-version: openssl-3.1.3 quictls-version: 3.1.4+quic - rustls-version: v0.10.0 + rustls-version: v0.12.0 jobs: autotools: diff --git a/docs/RUSTLS.md b/docs/RUSTLS.md index 7a0d806b62..3515e16662 100644 --- a/docs/RUSTLS.md +++ b/docs/RUSTLS.md @@ -3,7 +3,7 @@ [Rustls is a TLS backend written in Rust](https://docs.rs/rustls/). Curl can be built to use it as an alternative to OpenSSL or other TLS backends. We use the [rustls-ffi C bindings](https://github.com/rustls/rustls-ffi/). This -version of curl depends on version v0.10.0 of rustls-ffi. +version of curl depends on version v0.12.0 of rustls-ffi. # Building with rustls @@ -12,7 +12,7 @@ First, [install Rust](https://rustup.rs/). Next, check out, build, and install the appropriate version of rustls-ffi: % cargo install cbindgen - % git clone https://github.com/rustls/rustls-ffi -b v0.10.0 + % git clone https://github.com/rustls/rustls-ffi -b v0.12.0 % cd rustls-ffi % make % make DESTDIR=${HOME}/rustls-ffi-built/ install diff --git a/docs/TODO b/docs/TODO index ee537b913f..f1b3ccd664 100644 --- a/docs/TODO +++ b/docs/TODO @@ -126,7 +126,6 @@ 13.12 Reduce CA certificate bundle reparsing 13.13 Make sure we forbid TLS 1.3 post-handshake authentication 13.14 Support the clienthello extension - 13.15 Support latest rustls 14. GnuTLS 14.2 check connection @@ -923,14 +922,6 @@ https://datatracker.ietf.org/doc/html/rfc7685 https://github.com/curl/curl/issues/2299 -13.15 Support latest rustls - - The rustls backend does not build with the latest rustls-ffi version due to - API changes. Taking this bump should be a first step towards fixing the - remaining issues that still keeps the rustls backend experimental in curl. - - See https://github.com/curl/curl/issues/12737 - 14. GnuTLS 14.2 check connection diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c index d58970910c..485b1d3890 100644 --- a/lib/vtls/rustls.c +++ b/lib/vtls/rustls.c @@ -7,6 +7,7 @@ * * Copyright (C) Jacob Hoffman-Andrews, * + * Copyright (C) kpcyrd, * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -373,7 +374,10 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, 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; - struct rustls_root_cert_store *roots = 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 */ @@ -414,38 +418,60 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, hostname = "example.invalid"; } } - else if(ca_info_blob) { - roots = rustls_root_cert_store_new(); - - /* Enable strict parsing only if verification isn't disabled. */ - result = rustls_root_cert_store_add_pem(roots, 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_free(roots); - rustls_client_config_free( - rustls_client_config_builder_build(config_builder)); - return CURLE_SSL_CACERT_BADFILE; + 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 isn't 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_free( + rustls_client_config_builder_build(config_builder)); + return CURLE_SSL_CACERT_BADFILE; + } + } + else if(ssl_cafile) { + /* Enable strict parsing only if verification isn't 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_free( + rustls_client_config_builder_build(config_builder)); + return CURLE_SSL_CACERT_BADFILE; + } } - result = rustls_client_config_builder_use_roots(config_builder, roots); - rustls_root_cert_store_free(roots); + 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 load trusted certificates"); rustls_client_config_free( rustls_client_config_builder_build(config_builder)); return CURLE_SSL_CACERT_BADFILE; } - } - else if(ssl_cafile) { - result = rustls_client_config_builder_load_roots_from_file( - config_builder, ssl_cafile); + + verifier_builder = rustls_web_pki_server_cert_verifier_builder_new(roots); + + 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 load trusted certificates"); + rustls_server_cert_verifier_free(server_cert_verifier); rustls_client_config_free( rustls_client_config_builder_build(config_builder)); return CURLE_SSL_CACERT_BADFILE; } + + rustls_client_config_builder_set_server_verifier(config_builder, + server_cert_verifier); } backend->config = rustls_client_config_builder_build(config_builder); -- 2.47.3