done
This commit is contained in:
@@ -14,8 +14,6 @@ use futures_io::{
|
||||
};
|
||||
#[cfg(feature = "async-std1-rustls")]
|
||||
use futures_rustls::client::TlsStream as AsyncStd1RustlsStream;
|
||||
#[cfg(any(feature = "tokio1-rustls", feature = "async-std1-rustls"))]
|
||||
use rustls::pki_types::ServerName;
|
||||
#[cfg(feature = "tokio1-boring-tls")]
|
||||
use tokio1_boring::SslStream as Tokio1SslStream;
|
||||
#[cfg(feature = "tokio1")]
|
||||
@@ -319,11 +317,9 @@ impl AsyncNetworkStream {
|
||||
tcp_stream: Box<dyn AsyncTokioStream>,
|
||||
tls_parameters: TlsParameters,
|
||||
) -> Result<InnerAsyncNetworkStream, Error> {
|
||||
let domain = tls_parameters.domain().to_owned();
|
||||
|
||||
match tls_parameters.connector {
|
||||
match tls_parameters.inner {
|
||||
#[cfg(feature = "native-tls")]
|
||||
InnerTlsParameters::NativeTls { connector } => {
|
||||
InnerTlsParameters::NativeTls(inner) => {
|
||||
#[cfg(not(feature = "tokio1-native-tls"))]
|
||||
panic!("built without the tokio1-native-tls feature");
|
||||
|
||||
@@ -331,16 +327,16 @@ impl AsyncNetworkStream {
|
||||
return {
|
||||
use tokio1_native_tls_crate::TlsConnector;
|
||||
|
||||
let connector = TlsConnector::from(connector);
|
||||
let connector = TlsConnector::from(inner.connector);
|
||||
let stream = connector
|
||||
.connect(&domain, tcp_stream)
|
||||
.connect(&inner.server_name, tcp_stream)
|
||||
.await
|
||||
.map_err(error::connection)?;
|
||||
Ok(InnerAsyncNetworkStream::Tokio1NativeTls(stream))
|
||||
};
|
||||
}
|
||||
#[cfg(feature = "rustls")]
|
||||
InnerTlsParameters::Rustls { config } => {
|
||||
InnerTlsParameters::Rustls(inner) => {
|
||||
#[cfg(not(feature = "tokio1-rustls"))]
|
||||
panic!("built without the tokio1-rustls feature");
|
||||
|
||||
@@ -348,31 +344,25 @@ impl AsyncNetworkStream {
|
||||
return {
|
||||
use tokio1_rustls::TlsConnector;
|
||||
|
||||
let domain = ServerName::try_from(domain.as_str())
|
||||
.map_err(|_| error::connection("domain isn't a valid DNS name"))?;
|
||||
|
||||
let connector = TlsConnector::from(config);
|
||||
let connector = TlsConnector::from(inner.connector);
|
||||
let stream = connector
|
||||
.connect(domain.to_owned(), tcp_stream)
|
||||
.connect(inner.server_name.inner(), tcp_stream)
|
||||
.await
|
||||
.map_err(error::connection)?;
|
||||
Ok(InnerAsyncNetworkStream::Tokio1Rustls(stream))
|
||||
};
|
||||
}
|
||||
#[cfg(feature = "boring-tls")]
|
||||
InnerTlsParameters::BoringTls {
|
||||
connector,
|
||||
accept_invalid_hostnames,
|
||||
} => {
|
||||
InnerTlsParameters::BoringTls(inner) => {
|
||||
#[cfg(not(feature = "tokio1-boring-tls"))]
|
||||
panic!("built without the tokio1-boring-tls feature");
|
||||
|
||||
#[cfg(feature = "tokio1-boring-tls")]
|
||||
return {
|
||||
let mut config = connector.configure().map_err(error::connection)?;
|
||||
config.set_verify_hostname(accept_invalid_hostnames);
|
||||
let mut config = inner.connector.configure().map_err(error::connection)?;
|
||||
config.set_verify_hostname(inner.extra_info.accept_invalid_hostnames);
|
||||
|
||||
let stream = tokio1_boring::connect(config, &domain, tcp_stream)
|
||||
let stream = tokio1_boring::connect(config, &inner.server_name, tcp_stream)
|
||||
.await
|
||||
.map_err(error::connection)?;
|
||||
Ok(InnerAsyncNetworkStream::Tokio1BoringTls(stream))
|
||||
|
||||
@@ -12,7 +12,7 @@ use boring::ssl::SslStream;
|
||||
#[cfg(feature = "native-tls")]
|
||||
use native_tls::TlsStream;
|
||||
#[cfg(feature = "rustls")]
|
||||
use rustls::{pki_types::ServerName, ClientConnection, StreamOwned};
|
||||
use rustls::{ClientConnection, StreamOwned};
|
||||
use socket2::{Domain, Protocol, Type};
|
||||
|
||||
#[cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls"))]
|
||||
@@ -172,33 +172,33 @@ impl NetworkStream {
|
||||
tcp_stream: TcpStream,
|
||||
tls_parameters: &TlsParameters,
|
||||
) -> Result<InnerNetworkStream, Error> {
|
||||
Ok(match &tls_parameters.connector {
|
||||
Ok(match &tls_parameters.inner {
|
||||
#[cfg(feature = "native-tls")]
|
||||
InnerTlsParameters::NativeTls { connector } => {
|
||||
let stream = connector
|
||||
.connect(tls_parameters.domain(), tcp_stream)
|
||||
InnerTlsParameters::NativeTls(inner) => {
|
||||
let stream = inner
|
||||
.connector
|
||||
.connect(&inner.server_name, tcp_stream)
|
||||
.map_err(error::connection)?;
|
||||
InnerNetworkStream::NativeTls(stream)
|
||||
}
|
||||
#[cfg(feature = "rustls")]
|
||||
InnerTlsParameters::Rustls { config } => {
|
||||
let domain = ServerName::try_from(tls_parameters.domain())
|
||||
.map_err(|_| error::connection("domain isn't a valid DNS name"))?;
|
||||
let connection = ClientConnection::new(Arc::clone(config), domain.to_owned())
|
||||
.map_err(error::connection)?;
|
||||
InnerTlsParameters::Rustls(inner) => {
|
||||
let connection = ClientConnection::new(
|
||||
Arc::clone(&inner.connector),
|
||||
inner.server_name.inner_ref().clone(),
|
||||
)
|
||||
.map_err(error::connection)?;
|
||||
let stream = StreamOwned::new(connection, tcp_stream);
|
||||
InnerNetworkStream::Rustls(stream)
|
||||
}
|
||||
#[cfg(feature = "boring-tls")]
|
||||
InnerTlsParameters::BoringTls {
|
||||
connector,
|
||||
accept_invalid_hostnames,
|
||||
} => {
|
||||
let stream = connector
|
||||
InnerTlsParameters::BoringTls(inner) => {
|
||||
let stream = inner
|
||||
.connector
|
||||
.configure()
|
||||
.map_err(error::connection)?
|
||||
.verify_hostname(*accept_invalid_hostnames)
|
||||
.connect(tls_parameters.domain(), tcp_stream)
|
||||
.verify_hostname(inner.extra_info.accept_invalid_hostnames)
|
||||
.connect(&inner.server_name, tcp_stream)
|
||||
.map_err(error::connection)?;
|
||||
InnerNetworkStream::BoringTls(stream)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::transport::smtp::error::{self, Error};
|
||||
|
||||
pub(super) fn build_connector(
|
||||
builder: super::TlsParametersBuilder<super::BoringTls>,
|
||||
) -> Result<SslConnector, Error> {
|
||||
) -> Result<(Box<str>, SslConnector), Error> {
|
||||
let mut tls_builder = SslConnector::builder(SslMethod::tls_client()).map_err(error::tls)?;
|
||||
|
||||
if builder.accept_invalid_certs {
|
||||
@@ -49,7 +49,7 @@ pub(super) fn build_connector(
|
||||
tls_builder
|
||||
.set_min_proto_version(Some(min_tls_version))
|
||||
.map_err(error::tls)?;
|
||||
Ok(tls_builder.build())
|
||||
Ok((builder.server_name.into_boxed_str(), tls_builder.build()))
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::fmt::{self, Debug};
|
||||
|
||||
use super::TlsBackend;
|
||||
#[cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls"))]
|
||||
use crate::transport::smtp::{error, Error};
|
||||
|
||||
@@ -143,9 +144,7 @@ pub enum CertificateStore {
|
||||
/// Parameters to use for secure clients
|
||||
#[derive(Clone)]
|
||||
pub struct TlsParameters {
|
||||
pub(crate) connector: InnerTlsParameters,
|
||||
/// The domain name which is expected in the TLS certificate from the server
|
||||
pub(super) domain: String,
|
||||
pub(in crate::transport::smtp) inner: InnerTlsParameters,
|
||||
}
|
||||
|
||||
/// Builder for `TlsParameters`
|
||||
@@ -306,7 +305,7 @@ impl TlsParametersBuilder {
|
||||
builder = builder.identify_with(identity.native_tls);
|
||||
}
|
||||
|
||||
builder.build_legacy()
|
||||
builder.build().map(TlsParameters::from_inner)
|
||||
}
|
||||
|
||||
/// Creates a new `TlsParameters` using boring-tls with the provided configuration
|
||||
@@ -345,7 +344,7 @@ impl TlsParametersBuilder {
|
||||
builder = builder.identify_with(identity.boring_tls);
|
||||
}
|
||||
|
||||
builder.build_legacy()
|
||||
builder.build().map(TlsParameters::from_inner)
|
||||
}
|
||||
|
||||
/// Creates a new `TlsParameters` using rustls with the provided configuration
|
||||
@@ -386,24 +385,19 @@ impl TlsParametersBuilder {
|
||||
builder = builder.identify_with(identity.rustls_tls);
|
||||
}
|
||||
|
||||
builder.build_legacy()
|
||||
builder.build().map(TlsParameters::from_inner)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
pub(crate) enum InnerTlsParameters {
|
||||
pub(in crate::transport::smtp) enum InnerTlsParameters {
|
||||
#[cfg(feature = "native-tls")]
|
||||
NativeTls { connector: native_tls::TlsConnector },
|
||||
NativeTls(super::TlsParameters<super::NativeTls>),
|
||||
#[cfg(feature = "rustls")]
|
||||
Rustls {
|
||||
config: std::sync::Arc<rustls::ClientConfig>,
|
||||
},
|
||||
Rustls(super::TlsParameters<super::Rustls>),
|
||||
#[cfg(feature = "boring-tls")]
|
||||
BoringTls {
|
||||
connector: boring::ssl::SslConnector,
|
||||
accept_invalid_hostnames: bool,
|
||||
},
|
||||
BoringTls(super::TlsParameters<super::BoringTls>),
|
||||
}
|
||||
|
||||
impl TlsParameters {
|
||||
@@ -415,7 +409,9 @@ impl TlsParameters {
|
||||
doc(cfg(any(feature = "native-tls", feature = "rustls", feature = "boring-tls")))
|
||||
)]
|
||||
pub fn new(domain: String) -> Result<Self, Error> {
|
||||
TlsParametersBuilder::new(domain).build()
|
||||
super::TlsParametersBuilder::<super::DefaultTlsBackend>::new(domain)
|
||||
.build()
|
||||
.map(Self::from_inner)
|
||||
}
|
||||
|
||||
/// Creates a new `TlsParameters` builder
|
||||
@@ -427,25 +423,42 @@ impl TlsParameters {
|
||||
#[cfg(feature = "native-tls")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))]
|
||||
pub fn new_native(domain: String) -> Result<Self, Error> {
|
||||
TlsParametersBuilder::new(domain).build_native()
|
||||
super::TlsParametersBuilder::<super::NativeTls>::new(domain)
|
||||
.build()
|
||||
.map(Self::from_inner)
|
||||
}
|
||||
|
||||
/// Creates a new `TlsParameters` using rustls
|
||||
#[cfg(feature = "rustls")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
|
||||
pub fn new_rustls(domain: String) -> Result<Self, Error> {
|
||||
TlsParametersBuilder::new(domain).build_rustls()
|
||||
super::TlsParametersBuilder::<super::Rustls>::new(domain)
|
||||
.build()
|
||||
.map(Self::from_inner)
|
||||
}
|
||||
|
||||
/// Creates a new `TlsParameters` using boring
|
||||
#[cfg(feature = "boring-tls")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "boring-tls")))]
|
||||
pub fn new_boring(domain: String) -> Result<Self, Error> {
|
||||
TlsParametersBuilder::new(domain).build_boring()
|
||||
super::TlsParametersBuilder::<super::BoringTls>::new(domain)
|
||||
.build()
|
||||
.map(Self::from_inner)
|
||||
}
|
||||
|
||||
fn from_inner<B: TlsBackend>(inner: super::TlsParameters<B>) -> Self {
|
||||
B::__build_current_tls_parameters(inner)
|
||||
}
|
||||
|
||||
pub fn domain(&self) -> &str {
|
||||
&self.domain
|
||||
match &self.inner {
|
||||
#[cfg(feature = "native-tls")]
|
||||
InnerTlsParameters::NativeTls(inner) => &inner.server_name,
|
||||
#[cfg(feature = "rustls")]
|
||||
InnerTlsParameters::Rustls(inner) => inner.server_name.as_ref(),
|
||||
#[cfg(feature = "boring-tls")]
|
||||
InnerTlsParameters::BoringTls(inner) => &inner.server_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,7 +484,7 @@ impl Certificate {
|
||||
#[cfg(feature = "boring-tls")]
|
||||
boring_tls: super::boring_tls::Certificate::from_der(&der)?,
|
||||
#[cfg(feature = "rustls")]
|
||||
rustls: vec![super::rustls::Certificate::from_der(der)?],
|
||||
rustls: vec![super::rustls::Certificate::from_der(der)],
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -11,9 +11,27 @@ pub(super) mod native_tls;
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
|
||||
pub(super) mod rustls;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(private_bounds)]
|
||||
pub(in crate::transport::smtp) struct TlsParameters<B: TlsBackend> {
|
||||
pub(in crate::transport::smtp) server_name: B::ServerName,
|
||||
pub(in crate::transport::smtp) connector: B::Connector,
|
||||
pub(in crate::transport::smtp) extra_info: B::ExtraInfo,
|
||||
}
|
||||
|
||||
impl<B: TlsBackend> Clone for TlsParameters<B> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
server_name: self.server_name.clone(),
|
||||
connector: self.connector.clone(),
|
||||
extra_info: self.extra_info.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TlsParametersBuilder<B: TlsBackend> {
|
||||
domain: String,
|
||||
server_name: String,
|
||||
cert_store: B::CertificateStore,
|
||||
root_certs: Vec<B::Certificate>,
|
||||
identity: Option<B::Identity>,
|
||||
@@ -23,9 +41,9 @@ struct TlsParametersBuilder<B: TlsBackend> {
|
||||
}
|
||||
|
||||
impl<B: TlsBackend> TlsParametersBuilder<B> {
|
||||
fn new(domain: String) -> Self {
|
||||
fn new(server_name: String) -> Self {
|
||||
Self {
|
||||
domain,
|
||||
server_name,
|
||||
cert_store: Default::default(),
|
||||
root_certs: Vec::new(),
|
||||
identity: None,
|
||||
@@ -65,13 +83,17 @@ impl<B: TlsBackend> TlsParametersBuilder<B> {
|
||||
self
|
||||
}
|
||||
|
||||
fn build_legacy(self) -> Result<self::current::TlsParameters, Error> {
|
||||
let domain = self.domain.clone();
|
||||
let connector = B::__build_legacy_connector(self)?;
|
||||
Ok(self::current::TlsParameters { connector, domain })
|
||||
fn build(self) -> Result<TlsParameters<B>, Error> {
|
||||
let (server_name, connector, extra_info) = B::__build_connector(self)?;
|
||||
Ok(TlsParameters {
|
||||
server_name,
|
||||
connector,
|
||||
extra_info,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(private_bounds)]
|
||||
trait TlsBackend: private::SealedTlsBackend {
|
||||
type CertificateStore: Default;
|
||||
type Certificate;
|
||||
@@ -79,55 +101,33 @@ trait TlsBackend: private::SealedTlsBackend {
|
||||
type MinTlsVersion: Default;
|
||||
|
||||
#[doc(hidden)]
|
||||
fn __build_connector(builder: TlsParametersBuilder<Self>) -> Result<Self::Connector, Error>;
|
||||
fn __build_connector(
|
||||
builder: TlsParametersBuilder<Self>,
|
||||
) -> Result<(Self::ServerName, Self::Connector, Self::ExtraInfo), Error>;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[allow(private_interfaces)]
|
||||
fn __build_legacy_connector(
|
||||
builder: TlsParametersBuilder<Self>,
|
||||
) -> Result<self::current::InnerTlsParameters, Error>;
|
||||
fn __build_current_tls_parameters(inner: TlsParameters<Self>) -> self::current::TlsParameters;
|
||||
}
|
||||
|
||||
#[cfg(feature = "boring-tls")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "boring-tls")))]
|
||||
#[derive(Debug)]
|
||||
#[allow(missing_copy_implementations)]
|
||||
#[non_exhaustive]
|
||||
pub(super) struct BoringTls;
|
||||
#[cfg(feature = "native-tls")]
|
||||
type DefaultTlsBackend = NativeTls;
|
||||
|
||||
#[cfg(feature = "boring-tls")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "boring-tls")))]
|
||||
impl TlsBackend for BoringTls {
|
||||
type CertificateStore = self::boring_tls::CertificateStore;
|
||||
type Certificate = self::boring_tls::Certificate;
|
||||
type Identity = self::boring_tls::Identity;
|
||||
type MinTlsVersion = self::boring_tls::MinTlsVersion;
|
||||
#[cfg(all(feature = "rustls", not(feature = "native-tls")))]
|
||||
type DefaultTlsBackend = Rustls;
|
||||
|
||||
#[allow(private_interfaces)]
|
||||
fn __build_connector(builder: TlsParametersBuilder<Self>) -> Result<Self::Connector, Error> {
|
||||
self::boring_tls::build_connector(builder)
|
||||
}
|
||||
|
||||
#[allow(private_interfaces)]
|
||||
fn __build_legacy_connector(
|
||||
builder: TlsParametersBuilder<Self>,
|
||||
) -> Result<self::current::InnerTlsParameters, Error> {
|
||||
let accept_invalid_hostnames = builder.accept_invalid_hostnames;
|
||||
Self::__build_connector(builder).map(|connector| {
|
||||
self::current::InnerTlsParameters::BoringTls {
|
||||
connector,
|
||||
accept_invalid_hostnames,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
#[cfg(all(
|
||||
feature = "boring-tls",
|
||||
not(feature = "native-tls"),
|
||||
not(feature = "rustls")
|
||||
))]
|
||||
type DefaultTlsBackend = BoringTls;
|
||||
|
||||
#[cfg(feature = "native-tls")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))]
|
||||
#[derive(Debug)]
|
||||
#[allow(missing_copy_implementations)]
|
||||
#[non_exhaustive]
|
||||
pub(super) struct NativeTls;
|
||||
pub(in crate::transport::smtp) struct NativeTls;
|
||||
|
||||
#[cfg(feature = "native-tls")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))]
|
||||
@@ -137,17 +137,17 @@ impl TlsBackend for NativeTls {
|
||||
type Identity = self::native_tls::Identity;
|
||||
type MinTlsVersion = self::native_tls::MinTlsVersion;
|
||||
|
||||
#[allow(private_interfaces)]
|
||||
fn __build_connector(builder: TlsParametersBuilder<Self>) -> Result<Self::Connector, Error> {
|
||||
fn __build_connector(
|
||||
builder: TlsParametersBuilder<Self>,
|
||||
) -> Result<(Self::ServerName, Self::Connector, Self::ExtraInfo), Error> {
|
||||
self::native_tls::build_connector(builder)
|
||||
.map(|(server_name, connector)| (server_name, connector, ()))
|
||||
}
|
||||
|
||||
#[allow(private_interfaces)]
|
||||
fn __build_legacy_connector(
|
||||
builder: TlsParametersBuilder<Self>,
|
||||
) -> Result<self::current::InnerTlsParameters, Error> {
|
||||
Self::__build_connector(builder)
|
||||
.map(|connector| self::current::InnerTlsParameters::NativeTls { connector })
|
||||
fn __build_current_tls_parameters(inner: TlsParameters<Self>) -> self::current::TlsParameters {
|
||||
self::current::TlsParameters {
|
||||
inner: self::current::InnerTlsParameters::NativeTls(inner),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ impl TlsBackend for NativeTls {
|
||||
#[derive(Debug)]
|
||||
#[allow(missing_copy_implementations)]
|
||||
#[non_exhaustive]
|
||||
pub(super) struct Rustls;
|
||||
pub(in crate::transport::smtp) struct Rustls;
|
||||
|
||||
#[cfg(feature = "rustls")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
|
||||
@@ -166,37 +166,90 @@ impl TlsBackend for Rustls {
|
||||
type Identity = self::rustls::Identity;
|
||||
type MinTlsVersion = self::rustls::MinTlsVersion;
|
||||
|
||||
#[allow(private_interfaces)]
|
||||
fn __build_connector(builder: TlsParametersBuilder<Self>) -> Result<Self::Connector, Error> {
|
||||
fn __build_connector(
|
||||
builder: TlsParametersBuilder<Self>,
|
||||
) -> Result<(Self::ServerName, Self::Connector, Self::ExtraInfo), Error> {
|
||||
self::rustls::build_connector(builder)
|
||||
.map(|(server_name, connector)| (server_name, connector, ()))
|
||||
}
|
||||
|
||||
#[allow(private_interfaces)]
|
||||
fn __build_legacy_connector(
|
||||
builder: TlsParametersBuilder<Self>,
|
||||
) -> Result<self::current::InnerTlsParameters, Error> {
|
||||
Self::__build_connector(builder)
|
||||
.map(|config| self::current::InnerTlsParameters::Rustls { config })
|
||||
fn __build_current_tls_parameters(inner: TlsParameters<Self>) -> self::current::TlsParameters {
|
||||
self::current::TlsParameters {
|
||||
inner: self::current::InnerTlsParameters::Rustls(inner),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod private {
|
||||
pub(super) trait SealedTlsBackend: Sized {
|
||||
type Connector;
|
||||
#[cfg(feature = "boring-tls")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "boring-tls")))]
|
||||
#[derive(Debug)]
|
||||
#[allow(missing_copy_implementations)]
|
||||
#[non_exhaustive]
|
||||
pub(in crate::transport::smtp) struct BoringTls;
|
||||
|
||||
#[cfg(feature = "boring-tls")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "boring-tls")))]
|
||||
impl TlsBackend for BoringTls {
|
||||
type CertificateStore = self::boring_tls::CertificateStore;
|
||||
type Certificate = self::boring_tls::Certificate;
|
||||
type Identity = self::boring_tls::Identity;
|
||||
type MinTlsVersion = self::boring_tls::MinTlsVersion;
|
||||
|
||||
fn __build_connector(
|
||||
builder: TlsParametersBuilder<Self>,
|
||||
) -> Result<(Self::ServerName, Self::Connector, Self::ExtraInfo), Error> {
|
||||
let accept_invalid_hostnames = builder.accept_invalid_hostnames;
|
||||
self::boring_tls::build_connector(builder).map(|(server_name, connector)| {
|
||||
(
|
||||
server_name,
|
||||
connector,
|
||||
BoringTlsExtraInfo {
|
||||
accept_invalid_hostnames,
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "boring-tls")]
|
||||
impl SealedTlsBackend for super::BoringTls {
|
||||
type Connector = boring::ssl::SslConnector;
|
||||
fn __build_current_tls_parameters(inner: TlsParameters<Self>) -> self::current::TlsParameters {
|
||||
self::current::TlsParameters {
|
||||
inner: self::current::InnerTlsParameters::BoringTls(inner),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "boring-tls")]
|
||||
#[derive(Debug, Clone)]
|
||||
pub(in crate::transport::smtp) struct BoringTlsExtraInfo {
|
||||
pub(super) accept_invalid_hostnames: bool,
|
||||
}
|
||||
|
||||
mod private {
|
||||
pub(in crate::transport::smtp) trait SealedTlsBackend:
|
||||
Sized
|
||||
{
|
||||
type ServerName: Clone + AsRef<str>;
|
||||
type Connector: Clone;
|
||||
type ExtraInfo: Clone;
|
||||
}
|
||||
|
||||
#[cfg(feature = "native-tls")]
|
||||
impl SealedTlsBackend for super::NativeTls {
|
||||
type ServerName = Box<str>;
|
||||
type Connector = native_tls::TlsConnector;
|
||||
type ExtraInfo = ();
|
||||
}
|
||||
|
||||
#[cfg(feature = "rustls")]
|
||||
impl SealedTlsBackend for super::Rustls {
|
||||
type ServerName = super::rustls::ServerName;
|
||||
type Connector = std::sync::Arc<rustls::client::ClientConfig>;
|
||||
type ExtraInfo = ();
|
||||
}
|
||||
|
||||
#[cfg(feature = "boring-tls")]
|
||||
impl SealedTlsBackend for super::BoringTls {
|
||||
type ServerName = Box<str>;
|
||||
type Connector = boring::ssl::SslConnector;
|
||||
type ExtraInfo = super::BoringTlsExtraInfo;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::transport::smtp::error::{self, Error};
|
||||
|
||||
pub(super) fn build_connector(
|
||||
builder: super::TlsParametersBuilder<super::NativeTls>,
|
||||
) -> Result<TlsConnector, Error> {
|
||||
) -> Result<(Box<str>, TlsConnector), Error> {
|
||||
let mut tls_builder = TlsConnector::builder();
|
||||
|
||||
match builder.cert_store {
|
||||
@@ -32,7 +32,8 @@ pub(super) fn build_connector(
|
||||
tls_builder.identity(identity.0);
|
||||
}
|
||||
|
||||
tls_builder.build().map_err(error::tls)
|
||||
let connector = tls_builder.build().map_err(error::tls)?;
|
||||
Ok((builder.server_name.into_boxed_str(), connector))
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
|
||||
@@ -6,7 +6,7 @@ use std::{
|
||||
use rustls::{
|
||||
client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
|
||||
crypto::{verify_tls12_signature, verify_tls13_signature, CryptoProvider},
|
||||
pki_types::{self, ServerName, UnixTime},
|
||||
pki_types::{self, UnixTime},
|
||||
server::ParsedCertificate,
|
||||
ClientConfig, DigitallySignedStruct, RootCertStore, SignatureScheme,
|
||||
};
|
||||
@@ -15,7 +15,7 @@ use crate::transport::smtp::error::{self, Error};
|
||||
|
||||
pub(super) fn build_connector(
|
||||
builder: super::TlsParametersBuilder<super::Rustls>,
|
||||
) -> Result<Arc<ClientConfig>, Error> {
|
||||
) -> Result<(ServerName, Arc<ClientConfig>), Error> {
|
||||
let just_version3 = &[&rustls::version::TLS13];
|
||||
let supported_versions = match builder.min_tls_version {
|
||||
MinTlsVersion::Tlsv12 => rustls::ALL_VERSIONS,
|
||||
@@ -74,7 +74,42 @@ pub(super) fn build_connector(
|
||||
} else {
|
||||
tls.with_no_client_auth()
|
||||
};
|
||||
Ok(Arc::new(tls))
|
||||
let server_name = ServerName::try_from(builder.server_name)?;
|
||||
Ok((server_name, Arc::new(tls)))
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(in crate::transport::smtp) struct ServerName {
|
||||
val: pki_types::ServerName<'static>,
|
||||
str_val: Box<str>,
|
||||
}
|
||||
|
||||
impl ServerName {
|
||||
#[allow(dead_code)]
|
||||
pub(in crate::transport::smtp) fn inner(self) -> pki_types::ServerName<'static> {
|
||||
self.val
|
||||
}
|
||||
|
||||
pub(in crate::transport::smtp) fn inner_ref(&self) -> &pki_types::ServerName<'static> {
|
||||
&self.val
|
||||
}
|
||||
|
||||
fn try_from(value: String) -> Result<Self, crate::transport::smtp::Error> {
|
||||
let val: pki_types::ServerName<'_> = value
|
||||
.as_str()
|
||||
.try_into()
|
||||
.map_err(crate::transport::smtp::error::tls)?;
|
||||
Ok(Self {
|
||||
val: val.to_owned(),
|
||||
str_val: value.into_boxed_str(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for ServerName {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.str_val
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
@@ -122,8 +157,8 @@ impl Certificate {
|
||||
.map_err(|_| error::tls("invalid certificate"))
|
||||
}
|
||||
|
||||
pub(super) fn from_der(der: Vec<u8>) -> Result<Self, Error> {
|
||||
Ok(Self(der.into()))
|
||||
pub(super) fn from_der(der: Vec<u8>) -> Self {
|
||||
Self(der.into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +228,7 @@ impl ServerCertVerifier for InvalidCertsVerifier {
|
||||
&self,
|
||||
end_entity: &pki_types::CertificateDer<'_>,
|
||||
intermediates: &[pki_types::CertificateDer<'_>],
|
||||
server_name: &ServerName<'_>,
|
||||
server_name: &pki_types::ServerName<'_>,
|
||||
_ocsp_response: &[u8],
|
||||
now: UnixTime,
|
||||
) -> Result<ServerCertVerified, rustls::Error> {
|
||||
|
||||
Reference in New Issue
Block a user