mirror of
https://github.com/chatmail/core.git
synced 2026-05-08 09:26:29 +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::capabilities::Capabilities;
|
||||||
use super::session::Session;
|
use super::session::Session;
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::login_param::build_tls;
|
|
||||||
use crate::net::connect_tcp;
|
use crate::net::connect_tcp;
|
||||||
use crate::net::session::SessionStream;
|
use crate::net::session::SessionStream;
|
||||||
|
use crate::net::tls::wrap_tls;
|
||||||
use crate::socks::Socks5Config;
|
use crate::socks::Socks5Config;
|
||||||
|
|
||||||
/// IMAP write and read timeout.
|
/// IMAP write and read timeout.
|
||||||
@@ -95,8 +95,7 @@ impl Client {
|
|||||||
strict_tls: bool,
|
strict_tls: bool,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let tcp_stream = connect_tcp(context, hostname, port, IMAP_TIMEOUT, strict_tls).await?;
|
let tcp_stream = connect_tcp(context, hostname, port, IMAP_TIMEOUT, strict_tls).await?;
|
||||||
let tls = build_tls(strict_tls);
|
let tls_stream = wrap_tls(strict_tls, hostname, tcp_stream).await?;
|
||||||
let tls_stream = tls.connect(hostname, tcp_stream).await?;
|
|
||||||
let buffered_stream = BufWriter::new(tls_stream);
|
let buffered_stream = BufWriter::new(tls_stream);
|
||||||
let session_stream: Box<dyn SessionStream> = Box::new(buffered_stream);
|
let session_stream: Box<dyn SessionStream> = Box::new(buffered_stream);
|
||||||
let mut client = ImapClient::new(session_stream);
|
let mut client = ImapClient::new(session_stream);
|
||||||
@@ -142,9 +141,7 @@ impl Client {
|
|||||||
.context("STARTTLS command failed")?;
|
.context("STARTTLS command failed")?;
|
||||||
let tcp_stream = client.into_inner();
|
let tcp_stream = client.into_inner();
|
||||||
|
|
||||||
let tls = build_tls(strict_tls);
|
let tls_stream = wrap_tls(strict_tls, hostname, tcp_stream)
|
||||||
let tls_stream = tls
|
|
||||||
.connect(hostname, tcp_stream)
|
|
||||||
.await
|
.await
|
||||||
.context("STARTTLS upgrade failed")?;
|
.context("STARTTLS upgrade failed")?;
|
||||||
|
|
||||||
@@ -165,8 +162,7 @@ impl Client {
|
|||||||
let socks5_stream = socks5_config
|
let socks5_stream = socks5_config
|
||||||
.connect(context, domain, port, IMAP_TIMEOUT, strict_tls)
|
.connect(context, domain, port, IMAP_TIMEOUT, strict_tls)
|
||||||
.await?;
|
.await?;
|
||||||
let tls = build_tls(strict_tls);
|
let tls_stream = wrap_tls(strict_tls, domain, socks5_stream).await?;
|
||||||
let tls_stream = tls.connect(domain, socks5_stream).await?;
|
|
||||||
let buffered_stream = BufWriter::new(tls_stream);
|
let buffered_stream = BufWriter::new(tls_stream);
|
||||||
let session_stream: Box<dyn SessionStream> = Box::new(buffered_stream);
|
let session_stream: Box<dyn SessionStream> = Box::new(buffered_stream);
|
||||||
let mut client = ImapClient::new(session_stream);
|
let mut client = ImapClient::new(session_stream);
|
||||||
@@ -221,9 +217,7 @@ impl Client {
|
|||||||
.context("STARTTLS command failed")?;
|
.context("STARTTLS command failed")?;
|
||||||
let socks5_stream = client.into_inner();
|
let socks5_stream = client.into_inner();
|
||||||
|
|
||||||
let tls = build_tls(strict_tls);
|
let tls_stream = wrap_tls(strict_tls, hostname, socks5_stream)
|
||||||
let tls_stream = tls
|
|
||||||
.connect(hostname, socks5_stream)
|
|
||||||
.await
|
.await
|
||||||
.context("STARTTLS upgrade failed")?;
|
.context("STARTTLS upgrade failed")?;
|
||||||
let buffered_stream = BufWriter::new(tls_stream);
|
let buffered_stream = BufWriter::new(tls_stream);
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use anyhow::{ensure, Result};
|
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::constants::{DC_LP_AUTH_FLAGS, DC_LP_AUTH_NORMAL, DC_LP_AUTH_OAUTH2};
|
||||||
use crate::provider::{get_provider_by_id, Provider};
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -378,13 +354,4 @@ mod tests {
|
|||||||
assert_eq!(param, loaded);
|
assert_eq!(param, loaded);
|
||||||
Ok(())
|
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;
|
use crate::tools::time;
|
||||||
|
|
||||||
pub(crate) mod session;
|
pub(crate) mod session;
|
||||||
|
pub(crate) mod tls;
|
||||||
|
|
||||||
async fn connect_tcp_inner(addr: SocketAddr, timeout_val: Duration) -> Result<TcpStream> {
|
async fn connect_tcp_inner(addr: SocketAddr, timeout_val: Duration) -> Result<TcpStream> {
|
||||||
let tcp_stream = timeout(timeout_val, TcpStream::connect(addr))
|
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::config::Config;
|
||||||
use crate::contact::{Contact, ContactId};
|
use crate::contact::{Contact, ContactId};
|
||||||
use crate::events::EventType;
|
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::Message;
|
||||||
use crate::message::{self, MsgId};
|
use crate::message::{self, MsgId};
|
||||||
use crate::mimefactory::MimeFactory;
|
use crate::mimefactory::MimeFactory;
|
||||||
use crate::net::connect_tcp;
|
use crate::net::connect_tcp;
|
||||||
use crate::net::session::SessionStream;
|
use crate::net::session::SessionStream;
|
||||||
|
use crate::net::tls::wrap_tls;
|
||||||
use crate::oauth2::get_oauth2_access_token;
|
use crate::oauth2::get_oauth2_access_token;
|
||||||
use crate::provider::Socket;
|
use crate::provider::Socket;
|
||||||
use crate::socks::Socks5Config;
|
use crate::socks::Socks5Config;
|
||||||
@@ -119,8 +120,7 @@ impl Smtp {
|
|||||||
let socks5_stream = socks5_config
|
let socks5_stream = socks5_config
|
||||||
.connect(context, hostname, port, SMTP_TIMEOUT, strict_tls)
|
.connect(context, hostname, port, SMTP_TIMEOUT, strict_tls)
|
||||||
.await?;
|
.await?;
|
||||||
let tls = build_tls(strict_tls);
|
let tls_stream = wrap_tls(strict_tls, hostname, socks5_stream).await?;
|
||||||
let tls_stream = tls.connect(hostname, socks5_stream).await?;
|
|
||||||
let buffered_stream = BufWriter::new(tls_stream);
|
let buffered_stream = BufWriter::new(tls_stream);
|
||||||
let session_stream: Box<dyn SessionStream> = Box::new(buffered_stream);
|
let session_stream: Box<dyn SessionStream> = Box::new(buffered_stream);
|
||||||
let client = smtp::SmtpClient::new().smtp_utf8(true);
|
let client = smtp::SmtpClient::new().smtp_utf8(true);
|
||||||
@@ -144,9 +144,7 @@ impl Smtp {
|
|||||||
let client = smtp::SmtpClient::new().smtp_utf8(true);
|
let client = smtp::SmtpClient::new().smtp_utf8(true);
|
||||||
let transport = SmtpTransport::new(client, socks5_stream).await?;
|
let transport = SmtpTransport::new(client, socks5_stream).await?;
|
||||||
let tcp_stream = transport.starttls().await?;
|
let tcp_stream = transport.starttls().await?;
|
||||||
let tls = build_tls(strict_tls);
|
let tls_stream = wrap_tls(strict_tls, hostname, tcp_stream)
|
||||||
let tls_stream = tls
|
|
||||||
.connect(hostname, tcp_stream)
|
|
||||||
.await
|
.await
|
||||||
.context("STARTTLS upgrade failed")?;
|
.context("STARTTLS upgrade failed")?;
|
||||||
let buffered_stream = BufWriter::new(tls_stream);
|
let buffered_stream = BufWriter::new(tls_stream);
|
||||||
@@ -181,8 +179,7 @@ impl Smtp {
|
|||||||
strict_tls: bool,
|
strict_tls: bool,
|
||||||
) -> Result<SmtpTransport<Box<dyn SessionStream>>> {
|
) -> Result<SmtpTransport<Box<dyn SessionStream>>> {
|
||||||
let tcp_stream = connect_tcp(context, hostname, port, SMTP_TIMEOUT, false).await?;
|
let tcp_stream = connect_tcp(context, hostname, port, SMTP_TIMEOUT, false).await?;
|
||||||
let tls = build_tls(strict_tls);
|
let tls_stream = wrap_tls(strict_tls, hostname, tcp_stream).await?;
|
||||||
let tls_stream = tls.connect(hostname, tcp_stream).await?;
|
|
||||||
let buffered_stream = BufWriter::new(tls_stream);
|
let buffered_stream = BufWriter::new(tls_stream);
|
||||||
let session_stream: Box<dyn SessionStream> = Box::new(buffered_stream);
|
let session_stream: Box<dyn SessionStream> = Box::new(buffered_stream);
|
||||||
let client = smtp::SmtpClient::new().smtp_utf8(true);
|
let client = smtp::SmtpClient::new().smtp_utf8(true);
|
||||||
@@ -203,9 +200,7 @@ impl Smtp {
|
|||||||
let client = smtp::SmtpClient::new().smtp_utf8(true);
|
let client = smtp::SmtpClient::new().smtp_utf8(true);
|
||||||
let transport = SmtpTransport::new(client, tcp_stream).await?;
|
let transport = SmtpTransport::new(client, tcp_stream).await?;
|
||||||
let tcp_stream = transport.starttls().await?;
|
let tcp_stream = transport.starttls().await?;
|
||||||
let tls = build_tls(strict_tls);
|
let tls_stream = wrap_tls(strict_tls, hostname, tcp_stream)
|
||||||
let tls_stream = tls
|
|
||||||
.connect(hostname, tcp_stream)
|
|
||||||
.await
|
.await
|
||||||
.context("STARTTLS upgrade failed")?;
|
.context("STARTTLS upgrade failed")?;
|
||||||
let buffered_stream = BufWriter::new(tls_stream);
|
let buffered_stream = BufWriter::new(tls_stream);
|
||||||
|
|||||||
Reference in New Issue
Block a user