mirror of
https://github.com/chatmail/core.git
synced 2026-05-20 23:36:30 +03:00
fix: do not request ALPN on standard ports and when using STARTTLS
Apparently some providers fail TLS connection with "no_application_protocol" alert even when requesting "imap" protocol for IMAP connection and "smtp" protocol for SMTP connection. Fixes <https://github.com/deltachat/deltachat-core-rust/issues/5892>.
This commit is contained in:
@@ -38,6 +38,16 @@ impl DerefMut for Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts port number to ALPN list.
|
||||||
|
fn alpn(port: u16) -> &'static [&'static str] {
|
||||||
|
if port == 993 {
|
||||||
|
// Do not request ALPN on standard port.
|
||||||
|
&[]
|
||||||
|
} else {
|
||||||
|
&["imap"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Determine server capabilities.
|
/// Determine server capabilities.
|
||||||
///
|
///
|
||||||
/// If server supports ID capability, send our client ID.
|
/// If server supports ID capability, send our client ID.
|
||||||
@@ -157,7 +167,7 @@ impl Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn connect_secure(addr: SocketAddr, hostname: &str, strict_tls: bool) -> Result<Self> {
|
async fn connect_secure(addr: SocketAddr, hostname: &str, strict_tls: bool) -> Result<Self> {
|
||||||
let tls_stream = connect_tls_inner(addr, hostname, strict_tls, "imap").await?;
|
let tls_stream = connect_tls_inner(addr, hostname, strict_tls, alpn(addr.port())).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 = Client::new(session_stream);
|
let mut client = Client::new(session_stream);
|
||||||
@@ -197,7 +207,7 @@ impl Client {
|
|||||||
let buffered_tcp_stream = client.into_inner();
|
let buffered_tcp_stream = client.into_inner();
|
||||||
let tcp_stream = buffered_tcp_stream.into_inner();
|
let tcp_stream = buffered_tcp_stream.into_inner();
|
||||||
|
|
||||||
let tls_stream = wrap_tls(strict_tls, host, "imap", tcp_stream)
|
let tls_stream = wrap_tls(strict_tls, host, &[], tcp_stream)
|
||||||
.await
|
.await
|
||||||
.context("STARTTLS upgrade failed")?;
|
.context("STARTTLS upgrade failed")?;
|
||||||
|
|
||||||
@@ -217,7 +227,7 @@ impl Client {
|
|||||||
let socks5_stream = socks5_config
|
let socks5_stream = socks5_config
|
||||||
.connect(context, domain, port, strict_tls)
|
.connect(context, domain, port, strict_tls)
|
||||||
.await?;
|
.await?;
|
||||||
let tls_stream = wrap_tls(strict_tls, domain, "imap", socks5_stream).await?;
|
let tls_stream = wrap_tls(strict_tls, domain, alpn(port), 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 = Client::new(session_stream);
|
let mut client = Client::new(session_stream);
|
||||||
@@ -270,7 +280,7 @@ impl Client {
|
|||||||
let buffered_socks5_stream = client.into_inner();
|
let buffered_socks5_stream = client.into_inner();
|
||||||
let socks5_stream: Socks5Stream<_> = buffered_socks5_stream.into_inner();
|
let socks5_stream: Socks5Stream<_> = buffered_socks5_stream.into_inner();
|
||||||
|
|
||||||
let tls_stream = wrap_tls(strict_tls, hostname, "imap", socks5_stream)
|
let tls_stream = wrap_tls(strict_tls, 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);
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ pub(crate) async fn connect_tls_inner(
|
|||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
host: &str,
|
host: &str,
|
||||||
strict_tls: bool,
|
strict_tls: bool,
|
||||||
alpn: &str,
|
alpn: &[&str],
|
||||||
) -> Result<TlsStream<Pin<Box<TimeoutStream<TcpStream>>>>> {
|
) -> Result<TlsStream<Pin<Box<TimeoutStream<TcpStream>>>>> {
|
||||||
let tcp_stream = connect_tcp_inner(addr).await?;
|
let tcp_stream = connect_tcp_inner(addr).await?;
|
||||||
let tls_stream = wrap_tls(strict_tls, host, alpn, tcp_stream).await?;
|
let tls_stream = wrap_tls(strict_tls, host, alpn, tcp_stream).await?;
|
||||||
|
|||||||
@@ -32,10 +32,10 @@ pub fn build_tls(strict_tls: bool, alpns: &[&str]) -> TlsConnector {
|
|||||||
pub async fn wrap_tls<T: AsyncRead + AsyncWrite + Unpin>(
|
pub async fn wrap_tls<T: AsyncRead + AsyncWrite + Unpin>(
|
||||||
strict_tls: bool,
|
strict_tls: bool,
|
||||||
hostname: &str,
|
hostname: &str,
|
||||||
alpn: &str,
|
alpn: &[&str],
|
||||||
stream: T,
|
stream: T,
|
||||||
) -> Result<TlsStream<T>> {
|
) -> Result<TlsStream<T>> {
|
||||||
let tls = build_tls(strict_tls, &[alpn]);
|
let tls = build_tls(strict_tls, alpn);
|
||||||
let tls_stream = tls.connect(hostname, stream).await?;
|
let tls_stream = tls.connect(hostname, stream).await?;
|
||||||
Ok(tls_stream)
|
Ok(tls_stream)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,16 @@ use crate::provider::Socket;
|
|||||||
use crate::socks::Socks5Config;
|
use crate::socks::Socks5Config;
|
||||||
use crate::tools::time;
|
use crate::tools::time;
|
||||||
|
|
||||||
|
/// Converts port number to ALPN list.
|
||||||
|
fn alpn(port: u16) -> &'static [&'static str] {
|
||||||
|
if port == 465 {
|
||||||
|
// Do not request ALPN on standard port.
|
||||||
|
&[]
|
||||||
|
} else {
|
||||||
|
&["smtp"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns TLS, STARTTLS or plaintext connection
|
/// Returns TLS, STARTTLS or plaintext connection
|
||||||
/// using SOCKS5 or direct connection depending on the given configuration.
|
/// using SOCKS5 or direct connection depending on the given configuration.
|
||||||
///
|
///
|
||||||
@@ -113,7 +123,7 @@ async fn connect_secure_socks5(
|
|||||||
let socks5_stream = socks5_config
|
let socks5_stream = socks5_config
|
||||||
.connect(context, hostname, port, strict_tls)
|
.connect(context, hostname, port, strict_tls)
|
||||||
.await?;
|
.await?;
|
||||||
let tls_stream = wrap_tls(strict_tls, hostname, "smtp", socks5_stream).await?;
|
let tls_stream = wrap_tls(strict_tls, hostname, alpn(port), socks5_stream).await?;
|
||||||
let mut buffered_stream = BufStream::new(tls_stream);
|
let mut buffered_stream = BufStream::new(tls_stream);
|
||||||
skip_smtp_greeting(&mut buffered_stream).await?;
|
skip_smtp_greeting(&mut buffered_stream).await?;
|
||||||
let session_stream: Box<dyn SessionBufStream> = Box::new(buffered_stream);
|
let session_stream: Box<dyn SessionBufStream> = Box::new(buffered_stream);
|
||||||
@@ -135,7 +145,7 @@ async fn connect_starttls_socks5(
|
|||||||
let client = SmtpClient::new().smtp_utf8(true);
|
let client = SmtpClient::new().smtp_utf8(true);
|
||||||
let transport = SmtpTransport::new(client, BufStream::new(socks5_stream)).await?;
|
let transport = SmtpTransport::new(client, BufStream::new(socks5_stream)).await?;
|
||||||
let tcp_stream = transport.starttls().await?.into_inner();
|
let tcp_stream = transport.starttls().await?.into_inner();
|
||||||
let tls_stream = wrap_tls(strict_tls, hostname, "smtp", tcp_stream)
|
let tls_stream = wrap_tls(strict_tls, hostname, &[], tcp_stream)
|
||||||
.await
|
.await
|
||||||
.context("STARTTLS upgrade failed")?;
|
.context("STARTTLS upgrade failed")?;
|
||||||
let buffered_stream = BufStream::new(tls_stream);
|
let buffered_stream = BufStream::new(tls_stream);
|
||||||
@@ -163,7 +173,7 @@ async fn connect_secure(
|
|||||||
hostname: &str,
|
hostname: &str,
|
||||||
strict_tls: bool,
|
strict_tls: bool,
|
||||||
) -> Result<Box<dyn SessionBufStream>> {
|
) -> Result<Box<dyn SessionBufStream>> {
|
||||||
let tls_stream = connect_tls_inner(addr, hostname, strict_tls, "smtp").await?;
|
let tls_stream = connect_tls_inner(addr, hostname, strict_tls, alpn(addr.port())).await?;
|
||||||
let mut buffered_stream = BufStream::new(tls_stream);
|
let mut buffered_stream = BufStream::new(tls_stream);
|
||||||
skip_smtp_greeting(&mut buffered_stream).await?;
|
skip_smtp_greeting(&mut buffered_stream).await?;
|
||||||
let session_stream: Box<dyn SessionBufStream> = Box::new(buffered_stream);
|
let session_stream: Box<dyn SessionBufStream> = Box::new(buffered_stream);
|
||||||
@@ -181,7 +191,7 @@ async fn connect_starttls(
|
|||||||
let client = async_smtp::SmtpClient::new().smtp_utf8(true);
|
let client = async_smtp::SmtpClient::new().smtp_utf8(true);
|
||||||
let transport = async_smtp::SmtpTransport::new(client, BufStream::new(tcp_stream)).await?;
|
let transport = async_smtp::SmtpTransport::new(client, BufStream::new(tcp_stream)).await?;
|
||||||
let tcp_stream = transport.starttls().await?.into_inner();
|
let tcp_stream = transport.starttls().await?.into_inner();
|
||||||
let tls_stream = wrap_tls(strict_tls, host, "smtp", tcp_stream)
|
let tls_stream = wrap_tls(strict_tls, host, &[], tcp_stream)
|
||||||
.await
|
.await
|
||||||
.context("STARTTLS upgrade failed")?;
|
.context("STARTTLS upgrade failed")?;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user