Compare commits

..

No commits in common. "8e8fa85206d5305e2596e696418ba0e53793402b" and "32b888b3c1d1d11e6d5aa22b5bbb087fdaf85da0" have entirely different histories.

6 changed files with 129 additions and 99 deletions

7
Cargo.lock generated
View file

@ -702,7 +702,7 @@ dependencies = [
"once_cell", "once_cell",
"ring 0.17.8", "ring 0.17.8",
"rustls-pki-types", "rustls-pki-types",
"rustls-webpki 0.102.7", "rustls-webpki 0.102.6",
"subtle", "subtle",
"zeroize", "zeroize",
] ]
@ -734,9 +734,9 @@ dependencies = [
[[package]] [[package]]
name = "rustls-webpki" name = "rustls-webpki"
version = "0.102.7" version = "0.102.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84678086bd54edf2b415183ed7a94d0efb049f1b646a33e22a36f3794be6ae56" checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e"
dependencies = [ dependencies = [
"ring 0.17.8", "ring 0.17.8",
"rustls-pki-types", "rustls-pki-types",
@ -887,7 +887,6 @@ dependencies = [
"hickory-client", "hickory-client",
"mime", "mime",
"num_enum", "num_enum",
"rustls-webpki 0.102.7",
"sha2", "sha2",
"tokio", "tokio",
"tokio-rustls 0.26.0", "tokio-rustls 0.26.0",

View file

@ -25,7 +25,6 @@ tokio-rustls = { version = "0.26.0", default-features = false, features = ["ring
dashmap = { version = "6.0.1", optional = true } dashmap = { version = "6.0.1", optional = true }
hickory-client = { version = "0.24.1", optional = true } hickory-client = { version = "0.24.1", optional = true }
async-trait = "0.1.81" async-trait = "0.1.81"
rustls-webpki = "0.102.7"
[dev-dependencies] [dev-dependencies]
tokio = { version = "1.39.2", features = ["macros", "rt-multi-thread"] } tokio = { version = "1.39.2", features = ["macros", "rt-multi-thread"] }

88
src/certs/allow_all.rs Normal file
View file

@ -0,0 +1,88 @@
//! Custom verifier for Rustls accepting any TLS cert
//! (usually called "insecure mode")
use std::sync::Arc;
use tokio_rustls::rustls::{
self,
client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
crypto::CryptoProvider,
};
/// Custom verifier for Rustls accepting any TLS certificate
#[derive(Debug)]
pub struct AllowAllCertVerifier(Arc<CryptoProvider>);
impl Default for AllowAllCertVerifier {
/// Same as [`AllowAllCertVerifier::new()`].
fn default() -> Self {
Self::new()
}
}
impl AllowAllCertVerifier {
/// Constructor for this verifier.
pub fn new() -> Self {
AllowAllCertVerifier(
CryptoProvider::get_default()
.cloned()
.unwrap_or_else(|| Arc::new(rustls::crypto::ring::default_provider())),
)
}
}
impl From<Arc<CryptoProvider>> for AllowAllCertVerifier {
#[inline]
fn from(value: Arc<CryptoProvider>) -> Self {
AllowAllCertVerifier(value)
}
}
impl ServerCertVerifier for AllowAllCertVerifier {
#[inline]
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> {
Ok(ServerCertVerified::assertion())
}
#[inline]
fn verify_tls12_signature(
&self,
message: &[u8],
cert: &rustls::pki_types::CertificateDer<'_>,
dss: &rustls::DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, rustls::Error> {
rustls::crypto::verify_tls12_signature(
message,
cert,
dss,
&self.0.signature_verification_algorithms,
)
}
#[inline]
fn verify_tls13_signature(
&self,
message: &[u8],
cert: &rustls::pki_types::CertificateDer<'_>,
dss: &rustls::DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, rustls::Error> {
rustls::crypto::verify_tls13_signature(
message,
cert,
dss,
&self.0.signature_verification_algorithms,
)
}
#[inline]
fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
self.0.signature_verification_algorithms.supported_schemes()
}
}

View file

@ -1,7 +1,7 @@
//! Everything related to TLS certs verification //! Everything related to TLS certs verification
pub mod allow_all;
pub mod fingerprint; pub mod fingerprint;
pub mod verifier;
#[cfg(feature = "file-sscv")] #[cfg(feature = "file-sscv")]
pub mod file_sscv; pub mod file_sscv;

View file

@ -1,139 +1,83 @@
//! Custom verifier for Rustls allowing self-signed certs //! Internal custom Rustls verifier
//! but performing other required checks; //! allowing verification both with webpki trust roots (when enabled)
//! mostly for internal use //! and with implementaions of our own [`SelfsignedCertVerifier`]
use crate::certs::SelfsignedCertVerifier;
use std::sync::Arc; use std::sync::Arc;
pub use tokio_rustls::rustls::pki_types::{CertificateDer, ServerName, UnixTime};
use tokio_rustls::rustls::{ use tokio_rustls::rustls::{
self, self,
client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}, client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
crypto::CryptoProvider,
}; };
use webpki::EndEntityCert; pub struct CustomCertVerifier {
pub(crate) provider: Arc<rustls::crypto::CryptoProvider>,
/// Custom verifier for Rustls accepting any TLS certificate pub(crate) ss_verifier: Box<dyn SelfsignedCertVerifier>,
#[derive(Debug)]
pub struct InternalCertVerifier(Arc<CryptoProvider>);
impl Default for InternalCertVerifier {
/// Same as [`AllowAllCertVerifier::new()`].
fn default() -> Self {
Self::new()
}
} }
impl InternalCertVerifier { impl ServerCertVerifier for CustomCertVerifier {
/// Constructor for this verifier.
pub fn new() -> Self {
InternalCertVerifier(
CryptoProvider::get_default()
.cloned()
.unwrap_or_else(|| Arc::new(rustls::crypto::ring::default_provider())),
)
}
}
impl From<Arc<CryptoProvider>> for InternalCertVerifier {
#[inline]
fn from(value: Arc<CryptoProvider>) -> Self {
InternalCertVerifier(value)
}
}
impl ServerCertVerifier for InternalCertVerifier {
fn verify_server_cert( fn verify_server_cert(
&self, &self,
end_entity: &rustls::pki_types::CertificateDer<'_>, end_entity: &CertificateDer<'_>,
_intermediates: &[rustls::pki_types::CertificateDer<'_>], _intermediates: &[CertificateDer<'_>],
server_name: &rustls::pki_types::ServerName<'_>, server_name: &ServerName<'_>,
_ocsp_response: &[u8], _ocsp_response: &[u8],
now: rustls::pki_types::UnixTime, now: UnixTime,
) -> Result<ServerCertVerified, rustls::Error> { ) -> Result<ServerCertVerified, rustls::Error> {
let cert = EndEntityCert::try_from(end_entity).map_err(pki_error)?; // TODO: certificate validation (domain, expiry, etc.)
match cert.verify_for_usage(
self.0.signature_verification_algorithms.all,
&[], // no trusted anchors (i.e. CAs)
&[], // i think there's no point in passing intermediates without CAs
now, // `now` as the time for expiration check
webpki::KeyUsage::server_auth(),
None, // no CRLs
None, // no verify_path callback
) {
Ok(_) => Ok(()), // unreachable
Err(webpki::Error::UnknownIssuer) => {
// trust anchors verification is done after
// any other issuer-independent checks (including expiration),
// so this error can be safely ignored as
// we are working with self-signed certificates.
// for reference -- fn webpki::verify_cert::build_chain_inner
// (NOTE: should be re-checked on every rustls update)
Ok(())
}
Err(e) => Err(e),
}
.map_err(pki_error)?;
cert.verify_is_valid_for_subject_name(server_name)
.map_err(pki_error)?;
if self
.ss_verifier
.verify(end_entity, server_name.to_str().as_ref(), now)?
{
Ok(ServerCertVerified::assertion()) Ok(ServerCertVerified::assertion())
} else {
Err(rustls::Error::InvalidCertificate(
rustls::CertificateError::ApplicationVerificationFailure,
))
}
} }
#[inline]
fn verify_tls12_signature( fn verify_tls12_signature(
&self, &self,
message: &[u8], message: &[u8],
cert: &rustls::pki_types::CertificateDer<'_>, cert: &CertificateDer<'_>,
dss: &rustls::DigitallySignedStruct, dss: &rustls::DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, rustls::Error> { ) -> Result<HandshakeSignatureValid, rustls::Error> {
rustls::crypto::verify_tls12_signature( rustls::crypto::verify_tls12_signature(
message, message,
cert, cert,
dss, dss,
&self.0.signature_verification_algorithms, &self.provider.signature_verification_algorithms,
) )
} }
#[inline]
fn verify_tls13_signature( fn verify_tls13_signature(
&self, &self,
message: &[u8], message: &[u8],
cert: &rustls::pki_types::CertificateDer<'_>, cert: &CertificateDer<'_>,
dss: &rustls::DigitallySignedStruct, dss: &rustls::DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, rustls::Error> { ) -> Result<HandshakeSignatureValid, rustls::Error> {
rustls::crypto::verify_tls13_signature( rustls::crypto::verify_tls13_signature(
message, message,
cert, cert,
dss, dss,
&self.0.signature_verification_algorithms, &self.provider.signature_verification_algorithms,
) )
} }
#[inline]
fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> { fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
self.0.signature_verification_algorithms.supported_schemes() self.provider
.signature_verification_algorithms
.supported_schemes()
} }
} }
pub fn pki_error(e: webpki::Error) -> rustls::CertificateError { impl std::fmt::Debug for CustomCertVerifier {
// partially copied from private fn rustls::webpki::pki_error(e) fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use rustls::{CertificateError, OtherError}; write!(f, "CustomCertVerifier {{ provider: {:?} }}", self.provider)
use webpki::Error::*;
match e {
BadDer | BadDerTime | TrailingData(_) => CertificateError::BadEncoding,
CertNotValidYet => CertificateError::NotValidYet,
CertExpired | InvalidCertValidity => CertificateError::Expired,
UnknownIssuer => CertificateError::UnknownIssuer,
CertNotValidForName => CertificateError::NotValidForName,
CertRevoked => CertificateError::Revoked,
UnknownRevocationStatus => CertificateError::UnknownRevocationStatus,
InvalidSignatureForPublicKey
| UnsupportedSignatureAlgorithm
| UnsupportedSignatureAlgorithmForPublicKey => CertificateError::BadSignature,
_ => CertificateError::Other(OtherError(Arc::new(e))),
} }
} }

View file

@ -3,7 +3,7 @@
use std::sync::Arc; use std::sync::Arc;
use crate::{ use crate::{
certs::{verifier::InternalCertVerifier, SelfsignedCertVerifier}, certs::{allow_all::AllowAllCertVerifier, SelfsignedCertVerifier},
Client, Client,
}; };
@ -56,7 +56,7 @@ impl ClientBuilder {
}) })
.unwrap() .unwrap()
.dangerous() .dangerous()
.with_custom_certificate_verifier(Arc::new(InternalCertVerifier::from(provider))); .with_custom_certificate_verifier(Arc::new(AllowAllCertVerifier::from(provider)));
// TODO // TODO
let tls_config = tls_config.with_no_client_auth(); let tls_config = tls_config.with_no_client_auth();