diff --git a/Cargo.toml b/Cargo.toml index 0ef1fda..1ef40f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,7 +65,7 @@ tokio-socks = { version = "0.5.1", optional = true } # Feature - TLS native-tls = { version = "0.2.0", optional = true } -tokio-rustls = { version = "0.22.0", optional = true } +tokio-rustls = { version = "0.22.0", features = ["dangerous_configuration"], optional = true } tokio-native-tls = { version = "0.3.0", optional = true } webpki-roots = { version = "0.20.0", optional = true } diff --git a/src/client/conn.rs b/src/client/conn.rs index ad9f938..6db62d5 100644 --- a/src/client/conn.rs +++ b/src/client/conn.rs @@ -38,7 +38,7 @@ use webpki_roots::TLS_SERVER_ROOTS; #[cfg(feature = "tls-rust")] use tokio_rustls::{ client::TlsStream, - rustls::{internal::pemfile::certs, ClientConfig, PrivateKey}, + rustls::{self, internal::pemfile::certs, ClientConfig, PrivateKey}, webpki::DNSNameRef, TlsConnector, }; @@ -202,6 +202,10 @@ impl Connection { } } + if config.dangerously_accept_invalid_certs() { + builder.danger_accept_invalid_certs(true); + } + let connector: tokio_native_tls::TlsConnector = builder.build()?.into(); let domain = config.server()?; @@ -265,6 +269,10 @@ impl Connection { } } + if config.dangerously_accept_invalid_certs() { + builder.dangerous().set_certificate_verifier(Arc::new(DangerousAcceptAllVerifier)); + } + let connector = TlsConnector::from(Arc::new(builder)); let domain = DNSNameRef::try_from_ascii_str(config.server()?)?; @@ -363,3 +371,19 @@ impl Sink for Connection { } } } + +#[cfg(feature = "tls-rust")] +struct DangerousAcceptAllVerifier; + +#[cfg(feature = "tls-rust")] +impl rustls::ServerCertVerifier for DangerousAcceptAllVerifier { + fn verify_server_cert( + &self, + _: &rustls::RootCertStore, + _: &[rustls::Certificate], + _: DNSNameRef, + _: &[u8] + ) -> Result { + return Ok(rustls::ServerCertVerified::assertion()); + } +} diff --git a/src/client/data/config.rs b/src/client/data/config.rs index 1f2216a..7fe13a2 100644 --- a/src/client/data/config.rs +++ b/src/client/data/config.rs @@ -137,6 +137,13 @@ pub struct Config { #[cfg(any(feature = "tls-native", feature = "tls-rust"))] #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))] pub client_cert_pass: Option, + /// On `true`, all certificate validations are skipped. Defaults to `false`. + /// + /// # Warning + /// You should think very carefully before using this method. If invalid hostnames are trusted, *any* valid + /// certificate for *any* site will be trusted for use. This introduces significant vulnerabilities, and should + /// only be used as a last resort. + pub dangerously_accept_invalid_certs: Option, /// The encoding type used for this connection. /// This is typically UTF-8, but could be something else. #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))] @@ -513,6 +520,12 @@ impl Config { self.cert_path.as_ref().map(String::as_str) } + /// Gets whether or not to dangerously accept invalid certificates. + /// This defaults to `false` when not specified. + pub fn dangerously_accept_invalid_certs(&self) -> bool { + self.dangerously_accept_invalid_certs.as_ref().cloned().unwrap_or(false) + } + /// Gets the path to the client authentication certificate in DER format if specified. #[cfg(any(feature = "tls-native", feature = "tls-rust"))] pub fn client_cert_path(&self) -> Option<&str> {