From 238cf40f7b25f29b48756153b836e50740eeb127 Mon Sep 17 00:00:00 2001 From: Paolo Barbolini Date: Sun, 3 Dec 2023 10:56:40 +0100 Subject: [PATCH] Update rustls to v0.22 and related dependencies --- async-nats/Cargo.toml | 11 ++--- async-nats/src/connector.rs | 16 ++---- async-nats/src/options.rs | 9 +--- async-nats/src/tls.rs | 92 ++++++++++++----------------------- async-nats/tests/tls_tests.rs | 10 +--- 5 files changed, 41 insertions(+), 97 deletions(-) diff --git a/async-nats/Cargo.toml b/async-nats/Cargo.toml index 6fd12748b..9c2af44b4 100644 --- a/async-nats/Cargo.toml +++ b/async-nats/Cargo.toml @@ -25,22 +25,19 @@ serde_json = "1.0.104" serde_repr = "0.1.16" tokio = { version = "1.29.0", features = ["macros", "rt", "fs", "net", "sync", "time", "io-util"] } url = { version = "2"} -tokio-rustls = "0.24" -rustls-pemfile = "1.0.2" +tokio-rustls = "0.25" +rustls-pemfile = "2" nuid = "0.5" serde_nanos = "0.1.3" time = { version = "0.3.24", features = ["parsing", "formatting", "serde", "serde-well-known"] } -rustls-native-certs = "0.6" +rustls-native-certs = "0.7" tracing = "0.1" thiserror = "1.0" base64 = "0.21" tokio-retry = "0.3" ring = "0.17" rand = "0.8" -webpki = { package = "rustls-webpki", version = "0.101.2", features = ["alloc", "std"] } - -# for -Z minimal-versions -rustls = "0.21.6" # used by tokio-rustls 0.24.0 +webpki = { package = "rustls-webpki", version = "0.102" } [dev-dependencies] criterion = { version = "0.5", features = ["async_tokio"]} diff --git a/async-nats/src/connector.rs b/async-nats/src/connector.rs index 6070f5a7e..c7b6e8728 100644 --- a/async-nats/src/connector.rs +++ b/async-nats/src/connector.rs @@ -40,7 +40,6 @@ use std::io; use std::path::PathBuf; use std::sync::Arc; use std::time::Duration; -use tokio::io::ErrorKind; use tokio::net::TcpStream; use tokio::time::sleep; use tokio_rustls::rustls; @@ -306,19 +305,14 @@ impl Connector { .await .map_err(|err| ConnectError::with_source(crate::ConnectErrorKind::Tls, err))?, ); - let tls_connector = tokio_rustls::TlsConnector::try_from(tls_config) - .map_err(|err| { - io::Error::new( - ErrorKind::Other, - format!("failed to create TLS connector from TLS config: {err}"), - ) - }) - .map_err(|err| ConnectError::with_source(crate::ConnectErrorKind::Tls, err))?; + let tls_connector = tokio_rustls::TlsConnector::from(tls_config); - let domain = rustls::ServerName::try_from(tls_host) + let domain = webpki::types::ServerName::try_from(tls_host) .map_err(|err| ConnectError::with_source(crate::ConnectErrorKind::Tls, err))?; - let tls_stream = tls_connector.connect(domain, connection.stream).await?; + let tls_stream = tls_connector + .connect(domain.to_owned(), connection.stream) + .await?; Ok::(Connection::new(Box::new(tls_stream), 0)) }; diff --git a/async-nats/src/options.rs b/async-nats/src/options.rs index 912c6e200..2c264e52d 100644 --- a/async-nats/src/options.rs +++ b/async-nats/src/options.rs @@ -845,16 +845,9 @@ impl ConnectOptions { /// # async fn main() -> Result<(), async_nats::Error> { /// let mut root_store = async_nats::rustls::RootCertStore::empty(); /// - /// root_store.add_parsable_certificates( - /// rustls_native_certs::load_native_certs()? - /// .into_iter() - /// .map(|cert| cert.0) - /// .collect::>>() - /// .as_ref(), - /// ); + /// root_store.add_parsable_certificates(rustls_native_certs::load_native_certs()?); /// /// let tls_client = async_nats::rustls::ClientConfig::builder() - /// .with_safe_defaults() /// .with_root_certificates(root_store) /// .with_no_client_auth(); /// diff --git a/async-nats/src/tls.rs b/async-nats/src/tls.rs index c00f37c63..b0fab53c3 100644 --- a/async-nats/src/tls.rs +++ b/async-nats/src/tls.rs @@ -13,72 +13,48 @@ use crate::connector::ConnectorOptions; use crate::tls; -use std::fs::File; use std::io::{self, BufReader, ErrorKind}; use std::path::PathBuf; -use tokio_rustls::rustls::{self, Certificate, OwnedTrustAnchor, PrivateKey}; -use webpki::TrustAnchor; +use tokio_rustls::rustls::{ClientConfig, RootCertStore}; +use webpki::types::{CertificateDer, PrivateKeyDer}; /// Loads client certificates from a `.pem` file. /// If the pem file is found, but does not contain any certificates, it will return /// empty set of Certificates, not error. /// Can be used to parse only client certificates from .pem file containing both client key and certs. -pub(crate) async fn load_certs(path: PathBuf) -> io::Result> { +pub(crate) async fn load_certs(path: PathBuf) -> io::Result>> { tokio::task::spawn_blocking(move || { let file = std::fs::File::open(path)?; let mut reader = BufReader::new(file); - let certs = rustls_pemfile::certs(&mut reader)? - .into_iter() - .map(Certificate) - .collect(); - Ok(certs) + rustls_pemfile::certs(&mut reader).collect::>>() }) .await? } /// Loads client key from a `.pem` file. /// Can be used to parse only client key from .pem file containing both client key and certs. -pub(crate) async fn load_key(path: PathBuf) -> io::Result { +pub(crate) async fn load_key(path: PathBuf) -> io::Result> { tokio::task::spawn_blocking(move || { let file = std::fs::File::open(path)?; let mut reader = BufReader::new(file); - - loop { - match rustls_pemfile::read_one(&mut reader)? { - Some(rustls_pemfile::Item::RSAKey(key)) - | Some(rustls_pemfile::Item::PKCS8Key(key)) - | Some(rustls_pemfile::Item::ECKey(key)) => return Ok(PrivateKey(key)), - // if public key is found, don't error, just skip it and hope to find client key next. - Some(rustls_pemfile::Item::X509Certificate(_)) | Some(_) => {} - None => break, - } - } - - Err(io::Error::new( - ErrorKind::NotFound, - "could not find client key in the path", - )) + rustls_pemfile::private_key(&mut reader)?.ok_or_else(|| { + io::Error::new(ErrorKind::NotFound, "could not find client key in the path") + }) }) .await? } -pub(crate) async fn config_tls(options: &ConnectorOptions) -> io::Result { - let mut root_store = tokio_rustls::rustls::RootCertStore::empty(); +pub(crate) async fn config_tls(options: &ConnectorOptions) -> io::Result { + let mut root_store = RootCertStore::empty(); // load native system certs only if user did not specify them. if options.tls_client_config.is_some() || options.certificates.is_empty() { - root_store.add_parsable_certificates( - rustls_native_certs::load_native_certs() - .map_err(|err| { - io::Error::new( - ErrorKind::Other, - format!("could not load platform certs: {err}"), - ) - })? - .into_iter() - .map(|cert| cert.0) - .collect::>>() - .as_slice(), - ); + let certs_iter = rustls_native_certs::load_native_certs().map_err(|err| { + io::Error::new( + ErrorKind::Other, + format!("could not load platform certs: {err}"), + ) + })?; + root_store.add_parsable_certificates(certs_iter); } // use provided ClientConfig or built it from options. @@ -88,28 +64,20 @@ pub(crate) async fn config_tls(options: &ConnectorOptions) -> io::Result, webpki::Error>>() + .map_err(|err| { + io::Error::new( + ErrorKind::InvalidInput, + format!("could not load certs: {err}"), + ) + })?; + root_store.extend(trust_anchors); } - let builder = rustls::ClientConfig::builder() - .with_safe_defaults() - .with_root_certificates(root_store); + let builder = ClientConfig::builder().with_root_certificates(root_store); if let Some(cert) = options.client_cert.clone() { if let Some(key) = options.client_key.clone() { let key = tls::load_key(key).await?; diff --git a/async-nats/tests/tls_tests.rs b/async-nats/tests/tls_tests.rs index ab0fd2b8c..4ffb747d8 100644 --- a/async-nats/tests/tls_tests.rs +++ b/async-nats/tests/tls_tests.rs @@ -95,17 +95,9 @@ mod client { async fn custom_tls_client() { let mut root_store = async_nats::rustls::RootCertStore::empty(); - root_store.add_parsable_certificates( - rustls_native_certs::load_native_certs() - .unwrap() - .into_iter() - .map(|cert| cert.0) - .collect::>>() - .as_ref(), - ); + root_store.add_parsable_certificates(rustls_native_certs::load_native_certs().unwrap()); let tls_client = async_nats::rustls::ClientConfig::builder() - .with_safe_defaults() .with_root_certificates(root_store) .with_no_client_auth();