diff --git a/awc/Cargo.toml b/awc/Cargo.toml index da9e78ae8..721790fae 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -27,6 +27,7 @@ features = [ "rustls-0_20", "rustls-0_21", "rustls-0_22-webpki-roots", + "rustls-0_23-webpki-roots", "compress-brotli", "compress-gzip", "compress-zstd", @@ -48,6 +49,10 @@ rustls-0_21 = ["tls-rustls-0_21", "actix-tls/rustls-0_21"] rustls-0_22-webpki-roots = ["tls-rustls-0_22", "actix-tls/rustls-0_22-webpki-roots"] # TLS via Rustls v0.22 (Native roots) rustls-0_22-native-roots = ["tls-rustls-0_22", "actix-tls/rustls-0_22-native-roots"] +# TLS via Rustls v0.22 (WebPKI roots) +rustls-0_23-webpki-roots = ["tls-rustls-0_23", "actix-tls/rustls-0_23-webpki-roots"] +# TLS via Rustls v0.22 (Native roots) +rustls-0_23-native-roots = ["tls-rustls-0_23", "actix-tls/rustls-0_23-native-roots"] # Brotli algorithm content-encoding support compress-brotli = ["actix-http/compress-brotli", "__compress"] @@ -104,6 +109,7 @@ tls-openssl = { package = "openssl", version = "0.10.55", optional = true } tls-rustls-0_20 = { package = "rustls", version = "0.20", optional = true, features = ["dangerous_configuration"] } tls-rustls-0_21 = { package = "rustls", version = "0.21", optional = true, features = ["dangerous_configuration"] } tls-rustls-0_22 = { package = "rustls", version = "0.22", optional = true } +tls-rustls-0_23 = { package = "rustls", version = "0.23", optional = true, default-features = false } trust-dns-resolver = { version = "0.23", optional = true } diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index 94629b955..ea4594b80 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -57,6 +57,13 @@ enum OurTlsConnector { ))] #[allow(dead_code)] // false positive; used in build_tls Rustls022(std::sync::Arc), + + #[cfg(any( + feature = "rustls-0_23-webpki-roots", + feature = "rustls-0_23-native-roots", + ))] + #[allow(dead_code)] // false positive; used in build_tls + Rustls023(std::sync::Arc), } /// Manages HTTP client network connectivity. @@ -96,10 +103,32 @@ impl Connector<()> { } cfg_if::cfg_if! { - if #[cfg(any(feature = "rustls-0_22-webpki-roots", feature = "rustls-0_22-webpki-roots"))] { - /// Build TLS connector with Rustls v0.22, based on supplied ALPN protocols. + if #[cfg(any(feature = "rustls-0_23-webpki-roots", feature = "rustls-0_23-native-roots"))] { + /// Build TLS connector with Rustls v0.23, based on supplied ALPN protocols. /// - /// Note that if other TLS crate features are enabled, Rustls v0.22 will be used. + /// Note that if other TLS crate features are enabled, Rustls v0.23 will be used. + fn build_tls(protocols: Vec>) -> OurTlsConnector { + use actix_tls::connect::rustls_0_23::{self, reexports::ClientConfig}; + + cfg_if::cfg_if! { + if #[cfg(feature = "rustls-0_23-webpki-roots")] { + let certs = rustls_0_23::webpki_roots_cert_store(); + } else if #[cfg(feature = "rustls-0_23-native-roots")] { + let certs = rustls_0_23::native_roots_cert_store().expect("Failed to find native root certificates"); + } + } + + let mut config = ClientConfig::builder() + .with_root_certificates(certs) + .with_no_client_auth(); + + config.alpn_protocols = protocols; + + OurTlsConnector::Rustls023(std::sync::Arc::new(config)) + } + + } else if #[cfg(any(feature = "rustls-0_22-webpki-roots", feature = "rustls-0_22-native-roots"))] { + /// Build TLS connector with Rustls v0.22, based on supplied ALPN protocols. fn build_tls(protocols: Vec>) -> OurTlsConnector { use actix_tls::connect::rustls_0_22::{self, reexports::ClientConfig}; @@ -107,7 +136,7 @@ impl Connector<()> { if #[cfg(feature = "rustls-0_22-webpki-roots")] { let certs = rustls_0_22::webpki_roots_cert_store(); } else if #[cfg(feature = "rustls-0_22-native-roots")] { - let certs = rustls_0_22::native_roots_cert_store(); + let certs = rustls_0_22::native_roots_cert_store().expect("Failed to find native root certificates"); } } @@ -278,6 +307,19 @@ where self } + /// Sets custom Rustls v0.23 `ClientConfig` instance. + #[cfg(any( + feature = "rustls-0_23-webpki-roots", + feature = "rustls-0_23-native-roots", + ))] + pub fn rustls_0_23( + mut self, + connector: std::sync::Arc, + ) -> Self { + self.tls = OurTlsConnector::Rustls023(connector); + self + } + /// Sets maximum supported HTTP major version. /// /// Supported versions are HTTP/1.1 and HTTP/2. @@ -588,6 +630,43 @@ where Some(actix_service::boxed::rc_service(tls_service)) } + + #[cfg(any( + feature = "rustls-0_23-webpki-roots", + feature = "rustls-0_23-native-roots", + ))] + OurTlsConnector::Rustls023(tls) => { + const H2: &[u8] = b"h2"; + + use actix_tls::connect::rustls_0_23::{reexports::AsyncTlsStream, TlsConnector}; + + #[allow(non_local_definitions)] + impl IntoConnectionIo for TcpConnection> { + fn into_connection_io(self) -> (Box, Protocol) { + let sock = self.into_parts().0; + let h2 = sock + .get_ref() + .1 + .alpn_protocol() + .map_or(false, |protos| protos.windows(2).any(|w| w == H2)); + if h2 { + (Box::new(sock), Protocol::Http2) + } else { + (Box::new(sock), Protocol::Http1) + } + } + } + + let handshake_timeout = self.config.handshake_timeout; + + let tls_service = TlsConnectorService { + tcp_service: tcp_service_inner, + tls_service: TlsConnector::service(tls), + timeout: handshake_timeout, + }; + + Some(actix_service::boxed::rc_service(tls_service)) + } }; let tcp_config = self.config.no_disconnect_timeout();