mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
Move TLS support to net::tls module
This commit is contained in:
@@ -11,9 +11,9 @@ use tokio::io::BufWriter;
|
||||
use super::capabilities::Capabilities;
|
||||
use super::session::Session;
|
||||
use crate::context::Context;
|
||||
use crate::login_param::build_tls;
|
||||
use crate::net::connect_tcp;
|
||||
use crate::net::session::SessionStream;
|
||||
use crate::net::tls::wrap_tls;
|
||||
use crate::socks::Socks5Config;
|
||||
|
||||
/// IMAP write and read timeout.
|
||||
@@ -95,8 +95,7 @@ impl Client {
|
||||
strict_tls: bool,
|
||||
) -> Result<Self> {
|
||||
let tcp_stream = connect_tcp(context, hostname, port, IMAP_TIMEOUT, strict_tls).await?;
|
||||
let tls = build_tls(strict_tls);
|
||||
let tls_stream = tls.connect(hostname, tcp_stream).await?;
|
||||
let tls_stream = wrap_tls(strict_tls, hostname, tcp_stream).await?;
|
||||
let buffered_stream = BufWriter::new(tls_stream);
|
||||
let session_stream: Box<dyn SessionStream> = Box::new(buffered_stream);
|
||||
let mut client = ImapClient::new(session_stream);
|
||||
@@ -142,9 +141,7 @@ impl Client {
|
||||
.context("STARTTLS command failed")?;
|
||||
let tcp_stream = client.into_inner();
|
||||
|
||||
let tls = build_tls(strict_tls);
|
||||
let tls_stream = tls
|
||||
.connect(hostname, tcp_stream)
|
||||
let tls_stream = wrap_tls(strict_tls, hostname, tcp_stream)
|
||||
.await
|
||||
.context("STARTTLS upgrade failed")?;
|
||||
|
||||
@@ -165,8 +162,7 @@ impl Client {
|
||||
let socks5_stream = socks5_config
|
||||
.connect(context, domain, port, IMAP_TIMEOUT, strict_tls)
|
||||
.await?;
|
||||
let tls = build_tls(strict_tls);
|
||||
let tls_stream = tls.connect(domain, socks5_stream).await?;
|
||||
let tls_stream = wrap_tls(strict_tls, domain, socks5_stream).await?;
|
||||
let buffered_stream = BufWriter::new(tls_stream);
|
||||
let session_stream: Box<dyn SessionStream> = Box::new(buffered_stream);
|
||||
let mut client = ImapClient::new(session_stream);
|
||||
@@ -221,9 +217,7 @@ impl Client {
|
||||
.context("STARTTLS command failed")?;
|
||||
let socks5_stream = client.into_inner();
|
||||
|
||||
let tls = build_tls(strict_tls);
|
||||
let tls_stream = tls
|
||||
.connect(hostname, socks5_stream)
|
||||
let tls_stream = wrap_tls(strict_tls, hostname, socks5_stream)
|
||||
.await
|
||||
.context("STARTTLS upgrade failed")?;
|
||||
let buffered_stream = BufWriter::new(tls_stream);
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
use std::fmt;
|
||||
|
||||
use anyhow::{ensure, Result};
|
||||
use async_native_tls::Certificate;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use crate::constants::{DC_LP_AUTH_FLAGS, DC_LP_AUTH_NORMAL, DC_LP_AUTH_OAUTH2};
|
||||
use crate::provider::{get_provider_by_id, Provider};
|
||||
@@ -306,28 +304,6 @@ fn unset_empty(s: &str) -> &str {
|
||||
}
|
||||
}
|
||||
|
||||
// this certificate is missing on older android devices (eg. lg with android6 from 2017)
|
||||
// certificate downloaded from https://letsencrypt.org/certificates/
|
||||
static LETSENCRYPT_ROOT: Lazy<Certificate> = Lazy::new(|| {
|
||||
Certificate::from_der(include_bytes!(
|
||||
"../assets/root-certificates/letsencrypt/isrgrootx1.der"
|
||||
))
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
pub fn build_tls(strict_tls: bool) -> async_native_tls::TlsConnector {
|
||||
let tls_builder =
|
||||
async_native_tls::TlsConnector::new().add_root_certificate(LETSENCRYPT_ROOT.clone());
|
||||
|
||||
if strict_tls {
|
||||
tls_builder
|
||||
} else {
|
||||
tls_builder
|
||||
.danger_accept_invalid_hostnames(true)
|
||||
.danger_accept_invalid_certs(true)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -378,13 +354,4 @@ mod tests {
|
||||
assert_eq!(param, loaded);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_build_tls() -> Result<()> {
|
||||
// we are using some additional root certificates.
|
||||
// make sure, they do not break construction of TlsConnector
|
||||
let _ = build_tls(true);
|
||||
let _ = build_tls(false);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ use crate::context::Context;
|
||||
use crate::tools::time;
|
||||
|
||||
pub(crate) mod session;
|
||||
pub(crate) mod tls;
|
||||
|
||||
async fn connect_tcp_inner(addr: SocketAddr, timeout_val: Duration) -> Result<TcpStream> {
|
||||
let tcp_stream = timeout(timeout_val, TcpStream::connect(addr))
|
||||
|
||||
50
src/net/tls.rs
Normal file
50
src/net/tls.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
//! TLS support.
|
||||
|
||||
use anyhow::Result;
|
||||
use async_native_tls::{Certificate, TlsConnector, TlsStream};
|
||||
use once_cell::sync::Lazy;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
// this certificate is missing on older android devices (eg. lg with android6 from 2017)
|
||||
// certificate downloaded from https://letsencrypt.org/certificates/
|
||||
static LETSENCRYPT_ROOT: Lazy<Certificate> = Lazy::new(|| {
|
||||
Certificate::from_der(include_bytes!(
|
||||
"../../assets/root-certificates/letsencrypt/isrgrootx1.der"
|
||||
))
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
pub fn build_tls(strict_tls: bool) -> TlsConnector {
|
||||
let tls_builder = TlsConnector::new().add_root_certificate(LETSENCRYPT_ROOT.clone());
|
||||
|
||||
if strict_tls {
|
||||
tls_builder
|
||||
} else {
|
||||
tls_builder
|
||||
.danger_accept_invalid_hostnames(true)
|
||||
.danger_accept_invalid_certs(true)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn wrap_tls<T: AsyncRead + AsyncWrite + Unpin>(
|
||||
strict_tls: bool,
|
||||
hostname: &str,
|
||||
stream: T,
|
||||
) -> Result<TlsStream<T>> {
|
||||
let tls = build_tls(strict_tls);
|
||||
let tls_stream = tls.connect(hostname, stream).await?;
|
||||
Ok(tls_stream)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_build_tls() {
|
||||
// we are using some additional root certificates.
|
||||
// make sure, they do not break construction of TlsConnector
|
||||
let _ = build_tls(true);
|
||||
let _ = build_tls(false);
|
||||
}
|
||||
}
|
||||
17
src/smtp.rs
17
src/smtp.rs
@@ -13,12 +13,13 @@ use tokio::task;
|
||||
use crate::config::Config;
|
||||
use crate::contact::{Contact, ContactId};
|
||||
use crate::events::EventType;
|
||||
use crate::login_param::{build_tls, CertificateChecks, LoginParam, ServerLoginParam};
|
||||
use crate::login_param::{CertificateChecks, LoginParam, ServerLoginParam};
|
||||
use crate::message::Message;
|
||||
use crate::message::{self, MsgId};
|
||||
use crate::mimefactory::MimeFactory;
|
||||
use crate::net::connect_tcp;
|
||||
use crate::net::session::SessionStream;
|
||||
use crate::net::tls::wrap_tls;
|
||||
use crate::oauth2::get_oauth2_access_token;
|
||||
use crate::provider::Socket;
|
||||
use crate::socks::Socks5Config;
|
||||
@@ -119,8 +120,7 @@ impl Smtp {
|
||||
let socks5_stream = socks5_config
|
||||
.connect(context, hostname, port, SMTP_TIMEOUT, strict_tls)
|
||||
.await?;
|
||||
let tls = build_tls(strict_tls);
|
||||
let tls_stream = tls.connect(hostname, socks5_stream).await?;
|
||||
let tls_stream = wrap_tls(strict_tls, hostname, socks5_stream).await?;
|
||||
let buffered_stream = BufWriter::new(tls_stream);
|
||||
let session_stream: Box<dyn SessionStream> = Box::new(buffered_stream);
|
||||
let client = smtp::SmtpClient::new().smtp_utf8(true);
|
||||
@@ -144,9 +144,7 @@ impl Smtp {
|
||||
let client = smtp::SmtpClient::new().smtp_utf8(true);
|
||||
let transport = SmtpTransport::new(client, socks5_stream).await?;
|
||||
let tcp_stream = transport.starttls().await?;
|
||||
let tls = build_tls(strict_tls);
|
||||
let tls_stream = tls
|
||||
.connect(hostname, tcp_stream)
|
||||
let tls_stream = wrap_tls(strict_tls, hostname, tcp_stream)
|
||||
.await
|
||||
.context("STARTTLS upgrade failed")?;
|
||||
let buffered_stream = BufWriter::new(tls_stream);
|
||||
@@ -181,8 +179,7 @@ impl Smtp {
|
||||
strict_tls: bool,
|
||||
) -> Result<SmtpTransport<Box<dyn SessionStream>>> {
|
||||
let tcp_stream = connect_tcp(context, hostname, port, SMTP_TIMEOUT, false).await?;
|
||||
let tls = build_tls(strict_tls);
|
||||
let tls_stream = tls.connect(hostname, tcp_stream).await?;
|
||||
let tls_stream = wrap_tls(strict_tls, hostname, tcp_stream).await?;
|
||||
let buffered_stream = BufWriter::new(tls_stream);
|
||||
let session_stream: Box<dyn SessionStream> = Box::new(buffered_stream);
|
||||
let client = smtp::SmtpClient::new().smtp_utf8(true);
|
||||
@@ -203,9 +200,7 @@ impl Smtp {
|
||||
let client = smtp::SmtpClient::new().smtp_utf8(true);
|
||||
let transport = SmtpTransport::new(client, tcp_stream).await?;
|
||||
let tcp_stream = transport.starttls().await?;
|
||||
let tls = build_tls(strict_tls);
|
||||
let tls_stream = tls
|
||||
.connect(hostname, tcp_stream)
|
||||
let tls_stream = wrap_tls(strict_tls, hostname, tcp_stream)
|
||||
.await
|
||||
.context("STARTTLS upgrade failed")?;
|
||||
let buffered_stream = BufWriter::new(tls_stream);
|
||||
|
||||
Reference in New Issue
Block a user