mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
feat: add option to trust any TLS certificate for IMAP connections
This commit is contained in:
@@ -16,7 +16,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
use crate::modules::error::code::ErrorCode;
|
||||
use crate::modules::settings::proxy::Proxy;
|
||||
use crate::modules::utils::tls::establish_tls_stream;
|
||||
@@ -56,17 +55,19 @@ pub(crate) async fn establish_tcp_connection_with_timeout(
|
||||
Ok(Box::pin(timeout_stream))
|
||||
}
|
||||
|
||||
pub(crate) async fn establish_tls_connection(
|
||||
pub async fn establish_tls_connection(
|
||||
address: SocketAddr,
|
||||
server_hostname: &str,
|
||||
alpn_protocols: &[&str],
|
||||
use_proxy: Option<u64>,
|
||||
dangerous: bool,
|
||||
) -> BichonResult<impl SessionStream> {
|
||||
// Establish the TCP connection with timeout
|
||||
let tcp_stream = establish_tcp_connection_with_timeout(address, use_proxy).await?;
|
||||
|
||||
// Wrap the TCP stream with TLS encryption
|
||||
let tls_stream = establish_tls_stream(server_hostname, alpn_protocols, tcp_stream).await?;
|
||||
let tls_stream =
|
||||
establish_tls_stream(server_hostname, alpn_protocols, tcp_stream, dangerous).await?;
|
||||
|
||||
// Return the TLS stream wrapped in a SessionStream
|
||||
Ok(tls_stream)
|
||||
|
||||
+72
-14
@@ -16,7 +16,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
use crate::{
|
||||
modules::{
|
||||
error::{code::ErrorCode, BichonResult},
|
||||
@@ -24,38 +23,44 @@ use crate::{
|
||||
},
|
||||
raise_error,
|
||||
};
|
||||
use rustls::RootCertStore;
|
||||
use rustls::{
|
||||
client::danger::{ServerCertVerified, ServerCertVerifier},
|
||||
RootCertStore,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub async fn establish_tls_stream(
|
||||
server_hostname: &str,
|
||||
alpn_protocols: &[&str],
|
||||
stream: impl SessionStream + 'static,
|
||||
dangerous: bool,
|
||||
) -> BichonResult<impl SessionStream> {
|
||||
let tls_stream = establish_rustls_stream(server_hostname, alpn_protocols, stream).await?;
|
||||
let tls_stream =
|
||||
establish_rustls_stream(server_hostname, alpn_protocols, stream, dangerous).await?;
|
||||
let boxed_stream: Box<dyn SessionStream> = Box::new(tls_stream);
|
||||
Ok(boxed_stream)
|
||||
}
|
||||
|
||||
pub async fn establish_rustls_stream(
|
||||
async fn establish_rustls_stream(
|
||||
server_hostname: &str,
|
||||
alpn_protocols: &[&str],
|
||||
stream: impl SessionStream,
|
||||
dangerous: bool,
|
||||
) -> BichonResult<impl SessionStream> {
|
||||
// Create a root certificate store and add default trusted roots
|
||||
let root_store = RootCertStore {
|
||||
roots: webpki_roots::TLS_SERVER_ROOTS.into(),
|
||||
};
|
||||
|
||||
// Configure the Rustls client with the root certs and no client authentication
|
||||
let mut config = rustls::ClientConfig::builder()
|
||||
//builder_with_provider(
|
||||
// rustls::crypto::ring::default_provider().into(),
|
||||
// )
|
||||
// .with_protocol_versions(&[&rustls::version::TLS13])
|
||||
// .unwrap()
|
||||
.with_root_certificates(root_store)
|
||||
.with_no_client_auth();
|
||||
let mut config = if dangerous {
|
||||
rustls::ClientConfig::builder()
|
||||
.dangerous()
|
||||
.with_custom_certificate_verifier(Arc::new(SkipCertVerification))
|
||||
.with_no_client_auth()
|
||||
} else {
|
||||
rustls::ClientConfig::builder()
|
||||
.with_root_certificates(root_store)
|
||||
.with_no_client_auth()
|
||||
};
|
||||
|
||||
// Set the ALPN protocols
|
||||
config.alpn_protocols = alpn_protocols
|
||||
@@ -76,3 +81,56 @@ pub async fn establish_rustls_stream(
|
||||
|
||||
Ok(tls_stream)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SkipCertVerification;
|
||||
|
||||
impl ServerCertVerifier for SkipCertVerification {
|
||||
fn verify_server_cert(
|
||||
&self,
|
||||
_end_entity: &rustls::pki_types::CertificateDer<'_>,
|
||||
_intermediates: &[rustls::pki_types::CertificateDer<'_>],
|
||||
_server_name: &rustls::pki_types::ServerName<'_>,
|
||||
_ocsp_response: &[u8],
|
||||
_now: rustls::pki_types::UnixTime,
|
||||
) -> Result<ServerCertVerified, rustls::Error> {
|
||||
// Always return a valid certificate verification result
|
||||
Ok(ServerCertVerified::assertion())
|
||||
}
|
||||
|
||||
fn verify_tls12_signature(
|
||||
&self,
|
||||
_message: &[u8],
|
||||
_cert: &rustls::pki_types::CertificateDer<'_>,
|
||||
_dss: &rustls::DigitallySignedStruct,
|
||||
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
|
||||
Ok(rustls::client::danger::HandshakeSignatureValid::assertion())
|
||||
}
|
||||
|
||||
fn verify_tls13_signature(
|
||||
&self,
|
||||
_message: &[u8],
|
||||
_cert: &rustls::pki_types::CertificateDer<'_>,
|
||||
_dss: &rustls::DigitallySignedStruct,
|
||||
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
|
||||
Ok(rustls::client::danger::HandshakeSignatureValid::assertion())
|
||||
}
|
||||
|
||||
fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
|
||||
vec![
|
||||
rustls::SignatureScheme::RSA_PKCS1_SHA1,
|
||||
rustls::SignatureScheme::ECDSA_SHA1_Legacy,
|
||||
rustls::SignatureScheme::RSA_PKCS1_SHA256,
|
||||
rustls::SignatureScheme::ECDSA_NISTP256_SHA256,
|
||||
rustls::SignatureScheme::RSA_PKCS1_SHA384,
|
||||
rustls::SignatureScheme::ECDSA_NISTP384_SHA384,
|
||||
rustls::SignatureScheme::RSA_PKCS1_SHA512,
|
||||
rustls::SignatureScheme::ECDSA_NISTP521_SHA512,
|
||||
rustls::SignatureScheme::RSA_PSS_SHA256,
|
||||
rustls::SignatureScheme::RSA_PSS_SHA384,
|
||||
rustls::SignatureScheme::RSA_PSS_SHA512,
|
||||
rustls::SignatureScheme::ED25519,
|
||||
rustls::SignatureScheme::ED448,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user