diff --git a/Cargo.toml b/Cargo.toml index 6d681e6d5..16a4bb023 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -112,7 +112,7 @@ pin-project-lite = "0.2.0" ipnet = "2.3" # Optional deps... -rustls-pemfile = { version = "1.0", optional = true } +rustls-pemfile = { version = "2.0", optional = true } ## default-tls hyper-tls = { version = "0.5", optional = true } @@ -120,10 +120,10 @@ native-tls-crate = { version = "0.2.10", optional = true, package = "native-tls" tokio-native-tls = { version = "0.3.0", optional = true } # rustls-tls -hyper-rustls = { version = "0.24.0", default-features = false, optional = true } -rustls = { version = "0.21.6", features = ["dangerous_configuration"], optional = true } -tokio-rustls = { version = "0.24", optional = true } -webpki-roots = { version = "0.25", optional = true } +hyper-rustls = { version = "0.26.0", default-features = false, optional = true } +rustls = { version = "0.22.2", optional = true } +tokio-rustls = { version = "0.25", optional = true } +webpki-roots = { version = "0.26", optional = true } rustls-native-certs = { version = "0.6", optional = true } ## cookies diff --git a/src/async_impl/client.rs b/src/async_impl/client.rs index 8acecc596..f18a50c6d 100644 --- a/src/async_impl/client.rs +++ b/src/async_impl/client.rs @@ -464,18 +464,9 @@ impl ClientBuilder { #[cfg(feature = "rustls-tls-webpki-roots")] if config.tls_built_in_root_certs { - use rustls::OwnedTrustAnchor; - - let trust_anchors = - webpki_roots::TLS_SERVER_ROOTS.iter().map(|trust_anchor| { - OwnedTrustAnchor::from_subject_spki_name_constraints( - trust_anchor.subject, - trust_anchor.spki, - trust_anchor.name_constraints, - ) - }); - - root_cert_store.add_trust_anchors(trust_anchors); + root_cert_store + .roots + .extend_from_slice(webpki_roots::TLS_SERVER_ROOTS); } #[cfg(feature = "rustls-tls-native-roots")] @@ -530,12 +521,13 @@ impl ClientBuilder { } // Build TLS config - let config_builder = rustls::ClientConfig::builder() - .with_safe_default_cipher_suites() - .with_safe_default_kx_groups() - .with_protocol_versions(&versions) - .map_err(crate::error::builder)? - .with_root_certificates(root_cert_store); + let config_builder = if config.certs_verification { + rustls::ClientConfig::builder().with_root_certificates(root_cert_store) + } else { + rustls::ClientConfig::builder() + .dangerous() + .with_custom_certificate_verifier(Arc::new(NoVerifier)) + }; // Finalize TLS config let mut tls = if let Some(id) = config.identity { @@ -544,12 +536,6 @@ impl ClientBuilder { config_builder.with_no_client_auth() }; - // Certificate verifier - if !config.certs_verification { - tls.dangerous() - .set_certificate_verifier(Arc::new(NoVerifier)); - } - tls.enable_sni = config.tls_sni; // ALPN protocol diff --git a/src/connect.rs b/src/connect.rs index b6b51130e..2365a495c 100644 --- a/src/connect.rs +++ b/src/connect.rs @@ -366,8 +366,7 @@ impl Connector { tls_proxy, } => { if dst.scheme() == Some(&Scheme::HTTPS) { - use rustls::ServerName; - use std::convert::TryFrom; + use rustls::pki_types::ServerName; use tokio_rustls::TlsConnector as RustlsConnector; let host = dst.host().ok_or("no host in url")?.to_string(); diff --git a/src/tls.rs b/src/tls.rs index 717a6abbc..234433498 100644 --- a/src/tls.rs +++ b/src/tls.rs @@ -46,8 +46,11 @@ #[cfg(feature = "__rustls")] use rustls::{ - client::HandshakeSignatureValid, client::ServerCertVerified, client::ServerCertVerifier, - DigitallySignedStruct, Error as TLSError, ServerName, + client::danger::HandshakeSignatureValid, + client::danger::ServerCertVerified, + client::danger::ServerCertVerifier, + pki_types::{ServerName, UnixTime}, + DigitallySignedStruct, Error as TLSError, SignatureScheme, }; use std::{ fmt, @@ -71,13 +74,11 @@ enum Cert { } /// Represents a private key and X509 cert as a client certificate. -#[derive(Clone)] pub struct Identity { #[cfg_attr(not(any(feature = "native-tls", feature = "__rustls")), allow(unused))] inner: ClientCert, } -#[derive(Clone)] enum ClientCert { #[cfg(feature = "native-tls")] Pkcs12(native_tls_crate::Identity), @@ -85,8 +86,8 @@ enum ClientCert { Pkcs8(native_tls_crate::Identity), #[cfg(feature = "__rustls")] Pem { - key: rustls::PrivateKey, - certs: Vec, + key: rustls::pki_types::PrivateKeyDer<'static>, + certs: Vec>, }, } @@ -181,14 +182,14 @@ impl Certificate { match self.original { Cert::Der(buf) => root_cert_store - .add(&rustls::Certificate(buf)) + .add(rustls::pki_types::CertificateDer::from(buf)) .map_err(crate::error::builder)?, Cert::Pem(buf) => { let mut reader = Cursor::new(buf); let certs = Self::read_pem_certs(&mut reader)?; for c in certs { root_cert_store - .add(&rustls::Certificate(c)) + .add(rustls::pki_types::CertificateDer::from(c)) .map_err(crate::error::builder)?; } } @@ -198,6 +199,8 @@ impl Certificate { fn read_pem_certs(reader: &mut impl BufRead) -> crate::Result>> { rustls_pemfile::certs(reader) + .map(|c| c.map(|c| c.to_vec())) + .collect::>() .map_err(|_| crate::error::builder("invalid certificate encoding")) } } @@ -308,8 +311,8 @@ impl Identity { let (key, certs) = { let mut pem = Cursor::new(buf); - let mut sk = Vec::::new(); - let mut certs = Vec::::new(); + let mut sk = Vec::::new(); + let mut certs = Vec::::new(); for item in std::iter::from_fn(|| rustls_pemfile::read_one(&mut pem).transpose()) { match item.map_err(|_| { @@ -317,12 +320,10 @@ impl Identity { "Invalid identity PEM file", ))) })? { - rustls_pemfile::Item::X509Certificate(cert) => { - certs.push(rustls::Certificate(cert)) - } - rustls_pemfile::Item::PKCS8Key(key) => sk.push(rustls::PrivateKey(key)), - rustls_pemfile::Item::RSAKey(key) => sk.push(rustls::PrivateKey(key)), - rustls_pemfile::Item::ECKey(key) => sk.push(rustls::PrivateKey(key)), + rustls_pemfile::Item::X509Certificate(cert) => certs.push(cert), + rustls_pemfile::Item::Pkcs1Key(key) => sk.push(key.into()), + rustls_pemfile::Item::Pkcs8Key(key) => sk.push(key.into()), + rustls_pemfile::Item::Sec1Key(key) => sk.push(key.into()), _ => { return Err(crate::error::builder(TLSError::General(String::from( "No valid certificate was found", @@ -365,7 +366,7 @@ impl Identity { self, config_builder: rustls::ConfigBuilder< rustls::ClientConfig, - rustls::client::WantsTransparencyPolicyOrClientCert, + rustls::client::WantsClientCert, >, ) -> crate::Result { match self.inner { @@ -491,18 +492,18 @@ impl Default for TlsBackend { } #[cfg(feature = "__rustls")] +#[derive(Debug)] pub(crate) struct NoVerifier; #[cfg(feature = "__rustls")] impl ServerCertVerifier for NoVerifier { fn verify_server_cert( &self, - _end_entity: &rustls::Certificate, - _intermediates: &[rustls::Certificate], - _server_name: &ServerName, - _scts: &mut dyn Iterator, + _end_entity: &rustls::pki_types::CertificateDer<'_>, + _intermediates: &[rustls::pki_types::CertificateDer<'_>], + _server_name: &ServerName<'_>, _ocsp_response: &[u8], - _now: std::time::SystemTime, + _now: UnixTime, ) -> Result { Ok(ServerCertVerified::assertion()) } @@ -510,7 +511,7 @@ impl ServerCertVerifier for NoVerifier { fn verify_tls12_signature( &self, _message: &[u8], - _cert: &rustls::Certificate, + _cert: &rustls::pki_types::CertificateDer, _dss: &DigitallySignedStruct, ) -> Result { Ok(HandshakeSignatureValid::assertion()) @@ -519,11 +520,29 @@ impl ServerCertVerifier for NoVerifier { fn verify_tls13_signature( &self, _message: &[u8], - _cert: &rustls::Certificate, + _cert: &rustls::pki_types::CertificateDer, _dss: &DigitallySignedStruct, ) -> Result { Ok(HandshakeSignatureValid::assertion()) } + + fn supported_verify_schemes(&self) -> Vec { + vec![ + SignatureScheme::ECDSA_NISTP256_SHA256, + SignatureScheme::ECDSA_NISTP384_SHA384, + SignatureScheme::ECDSA_NISTP521_SHA512, + SignatureScheme::ECDSA_SHA1_Legacy, + SignatureScheme::ED25519, + SignatureScheme::ED448, + SignatureScheme::RSA_PKCS1_SHA1, + SignatureScheme::RSA_PKCS1_SHA256, + SignatureScheme::RSA_PKCS1_SHA384, + SignatureScheme::RSA_PKCS1_SHA512, + SignatureScheme::RSA_PSS_SHA256, + SignatureScheme::RSA_PSS_SHA384, + SignatureScheme::RSA_PSS_SHA512, + ] + } } /// Hyper extension carrying extra TLS layer information.