Compare commits
No commits in common. "8e8fa85206d5305e2596e696418ba0e53793402b" and "32b888b3c1d1d11e6d5aa22b5bbb087fdaf85da0" have entirely different histories.
8e8fa85206
...
32b888b3c1
6 changed files with 129 additions and 99 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -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",
|
||||||
|
|
|
@ -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
88
src/certs/allow_all.rs
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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))),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Add table
Reference in a new issue