diff --git a/Cargo.lock b/Cargo.lock index 7572437d9..9fd0b7a97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -658,6 +658,7 @@ dependencies = [ "strum_macros 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "thread-local-object 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", "webpki-roots 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index 638d2bc43..8a6ac95ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,7 @@ sanitize-filename = "0.2.1" stop-token = { version = "0.1.1", features = ["unstable"] } rustls = "0.16.0" webpki-roots = "0.18.0" +webpki = "0.21.0" [dev-dependencies] tempfile = "3.0" diff --git a/src/imap_client.rs b/src/imap_client.rs index 532580f9b..582cd7f35 100644 --- a/src/imap_client.rs +++ b/src/imap_client.rs @@ -8,7 +8,7 @@ use async_std::net::{self, TcpStream}; use async_std::prelude::*; use async_tls::client::TlsStream; -use crate::login_param::CertificateChecks; +use crate::login_param::{dc_build_tls, CertificateChecks}; const DCC_IMAP_DEBUG: &str = "DCC_IMAP_DEBUG"; @@ -34,11 +34,10 @@ impl Client { pub async fn connect_secure>( addr: A, domain: S, - _certificate_checks: CertificateChecks, + certificate_checks: CertificateChecks, ) -> ImapResult { let stream = TcpStream::connect(addr).await?; - let tls = async_tls::TlsConnector::new(); - + let tls = dc_build_tls(certificate_checks); let tls_stream = tls.connect(domain.as_ref(), stream)?.await?; let mut client = ImapClient::new(tls_stream); diff --git a/src/login_param.rs b/src/login_param.rs index 103d6f5c1..4cab089fc 100644 --- a/src/login_param.rs +++ b/src/login_param.rs @@ -3,6 +3,10 @@ use std::fmt; use crate::context::Context; use crate::error::Error; +use async_std::sync::Arc; +use async_tls; +use rustls; +use webpki; #[derive(Copy, Clone, Debug, Display, FromPrimitive)] #[repr(i32)] @@ -251,28 +255,46 @@ fn get_readable_flags(flags: i32) -> String { res } -// pub fn dc_build_tls( -// certificate_checks: CertificateChecks, -// ) -> Result { -// let mut tls_builder = native_tls::TlsConnector::builder(); -// match certificate_checks { -// CertificateChecks::Automatic => { -// // Same as AcceptInvalidCertificates for now. -// // TODO: use provider database when it becomes available -// tls_builder -// .danger_accept_invalid_hostnames(true) -// .danger_accept_invalid_certs(true) -// } -// CertificateChecks::Strict => &mut tls_builder, -// CertificateChecks::AcceptInvalidHostnames => { -// tls_builder.danger_accept_invalid_hostnames(true) -// } -// CertificateChecks::AcceptInvalidCertificates => tls_builder -// .danger_accept_invalid_hostnames(true) -// .danger_accept_invalid_certs(true), -// } -// .build() -// } +pub struct NoCertificateVerification {} + +impl rustls::ServerCertVerifier for NoCertificateVerification { + fn verify_server_cert( + &self, + _roots: &rustls::RootCertStore, + _presented_certs: &[rustls::Certificate], + _dns_name: webpki::DNSNameRef<'_>, + _ocsp: &[u8], + ) -> Result { + Ok(rustls::ServerCertVerified::assertion()) + } +} + +pub fn dc_build_tls(certificate_checks: CertificateChecks) -> async_tls::TlsConnector { + let mut config = rustls::ClientConfig::new(); + match certificate_checks { + CertificateChecks::Strict => {} + CertificateChecks::Automatic => { + // Same as AcceptInvalidCertificates for now. + // TODO: use provider database when it becomes available + config + .dangerous() + .set_certificate_verifier(Arc::new(NoCertificateVerification {})); + } + CertificateChecks::AcceptInvalidCertificates => { + // TODO: only accept invalid certs + config + .dangerous() + .set_certificate_verifier(Arc::new(NoCertificateVerification {})); + } + CertificateChecks::AcceptInvalidHostnames => { + // TODO: only accept invalid hostnames + config + .dangerous() + .set_certificate_verifier(Arc::new(NoCertificateVerification {})); + } + } + Arc::new(config).into() +} #[cfg(test)] mod tests {