diff --git a/Cargo.lock b/Cargo.lock index 7497ae280..f209e2ac9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1848,7 +1848,11 @@ dependencies = [ "regex", "reqwest", "rstest", + "rustls", + "rustls-pemfile", + "rustls-pki-types", "rustls-platform-verifier", + "rustls-webpki", "schemars", "semver 1.0.17", "serde", @@ -2502,6 +2506,7 @@ version = "0.23.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" dependencies = [ + "log", "once_cell", "ring", "rustls-pki-types", @@ -2540,9 +2545,8 @@ checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" [[package]] name = "rustls-platform-verifier" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afbb878bdfdf63a336a5e63561b1835e7a8c91524f51621db870169eac84b490" +version = "0.4.0" +source = "git+https://github.com/rustls/rustls-platform-verifier.git?rev=ca87571fe47730665917b8c29f14a3989f3cbe57#ca87571fe47730665917b8c29f14a3989f3cbe57" dependencies = [ "core-foundation", "core-foundation-sys", @@ -2555,15 +2559,14 @@ dependencies = [ "rustls-webpki", "security-framework", "security-framework-sys", - "webpki-roots", - "winapi", + "webpki-root-certs", + "windows-sys 0.52.0", ] [[package]] name = "rustls-platform-verifier-android" version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" +source = "git+https://github.com/rustls/rustls-platform-verifier.git?rev=ca87571fe47730665917b8c29f14a3989f3cbe57#ca87571fe47730665917b8c29f14a3989f3cbe57" [[package]] name = "rustls-webpki" @@ -3476,6 +3479,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-root-certs" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c6dfa3ac045bc517de14c7b1384298de1dbd229d38e08e169d9ae8c170937c" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webpki-roots" version = "0.26.6" diff --git a/Cargo.toml b/Cargo.toml index 5d35ecb97..44a8640c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,7 +73,11 @@ regex = "=1.8.4" reqwest = { version = "=0.12.8", default-features = false, features = ["blocking", "deflate", "gzip", "brotli", "socks", "rustls-tls"] } rstest = "=0.17.0" rstest_reuse = "=0.5.0" -rustls-platform-verifier = "=0.3.4" +rustls = { version = "=0.23.14", default-features = false, features = ["ring", "logging", "std", "tls12"] } +rustls-platform-verifier = { git = "https://github.com/rustls/rustls-platform-verifier.git", rev = "ca87571fe47730665917b8c29f14a3989f3cbe57" } +rustls-pemfile = "=2.2.0" +rustls-pki-types = "=1.9.0" +rustls-webpki = { version = "=0.102.8", features = ["ring"] } schemars = { version = "=0.8.12", features = ["chrono", "either", "enumset", "indexmap"] } semver = { version = "=1.0.17", features = ["serde"] } serde = { version = "=1.0.164", features = ["derive"] } diff --git a/packages/nextclade-cli/Cargo.toml b/packages/nextclade-cli/Cargo.toml index a2770c26d..d76923374 100644 --- a/packages/nextclade-cli/Cargo.toml +++ b/packages/nextclade-cli/Cargo.toml @@ -41,7 +41,11 @@ pretty_assertions = { workspace = true } rayon = { workspace = true } regex = { workspace = true } reqwest = { workspace = true } +rustls = { workspace = true } rustls-platform-verifier = { workspace = true } +rustls-pemfile = { workspace = true } +rustls-pki-types = { workspace = true } +rustls-webpki = { workspace = true } schemars = { workspace = true } semver = { workspace = true } serde = { workspace = true } diff --git a/packages/nextclade-cli/src/io/http_client.rs b/packages/nextclade-cli/src/io/http_client.rs index b8cd5c0c4..a280fe195 100644 --- a/packages/nextclade-cli/src/io/http_client.rs +++ b/packages/nextclade-cli/src/io/http_client.rs @@ -1,12 +1,19 @@ use clap::{Parser, ValueHint}; -use eyre::Report; +use eyre::{Report, WrapErr}; use log::info; use nextclade::make_internal_error; use nextclade::utils::info::{this_package_name, this_package_version_str}; use reqwest::blocking::Client; use reqwest::{Method, Proxy}; -use rustls_platform_verifier; +use rustls::ClientConfig; +use rustls_pemfile; +use rustls_pki_types::CertificateDer; +use rustls_platform_verifier::Verifier; +use std::env; +use std::io::BufReader; +use std::fs::File; use std::str::FromStr; +use std::sync::Arc; use std::time::Duration; use url::Url; @@ -62,8 +69,13 @@ impl HttpClient { let user_agent = format!("{} {}", this_package_name(), this_package_version_str()); + let tls_config = ClientConfig::builder() + .dangerous() // …but the rustls_platform_verifier::Verifier is safe + .with_custom_certificate_verifier(Arc::new(Verifier::new_with_extra_roots(extra_ca_certs()?)?)) + .with_no_client_auth(); + let client = client_builder - .use_preconfigured_tls(rustls_platform_verifier::tls_config()) + .use_preconfigured_tls(tls_config) .connection_verbose(verbose) .connect_timeout(Some(Duration::from_secs(60))) .user_agent(user_agent) @@ -112,3 +124,21 @@ impl HttpClient { Ok(content) } } + +fn extra_ca_certs() -> Result>, Report> { + match env::var_os("NEXTCLADE_EXTRA_CA_CERTS") { + Some(filename) => { + let file = File::open(filename.clone()) + .wrap_err_with(|| format!("When opening NEXTCLADE_EXTRA_CA_CERTS file {filename:?}"))?; + + let mut reader = BufReader::new(file); + + let certs = rustls_pemfile::certs(&mut reader) + .map(|c| c.wrap_err_with(|| "When parsing an extra CA certificate".to_owned())) + .collect::, Report>>()?; + + Ok(certs) + } + None => Ok(vec![]) + } +}