use rustls::client::danger::HandshakeSignatureValid;
use rustls::pki_types::{CertificateDer, UnixTime};
use rustls::server::danger::{ClientCertVerified, ClientCertVerifier};
use rustls::{DigitallySignedStruct, DistinguishedName, Error, SignatureScheme};
use std::collections::HashSet;
use std::fmt::{Debug, Formatter};
use std::sync::Arc;
pub(crate) struct CustomClientCertVerifier {
pub(crate) default_verifier: Arc<dyn ClientCertVerifier>,
pub(crate) allowed_names_set: HashSet<String>,
}
impl Debug for CustomClientCertVerifier {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CustomClientCertVerifier").finish()
}
}
impl ClientCertVerifier for CustomClientCertVerifier {
fn root_hint_subjects(&self) -> &[DistinguishedName] {
self.default_verifier.root_hint_subjects()
}
fn verify_client_cert(&self, end_entity: &CertificateDer<'_>, intermediates: &[CertificateDer<'_>], now: UnixTime) -> Result<ClientCertVerified, Error> {
let verified = self.default_verifier.verify_client_cert(end_entity, intermediates, now)?;
let (_, cert) = x509_parser::parse_x509_certificate(end_entity.as_ref()).map_err(|_| Error::General("Failed to parse client certificate".into()))?;
let cn = cert.subject().iter_common_name().next().and_then(|attr| attr.as_str().ok()).unwrap_or("");
if !self.allowed_names_set.contains(cn) {
return Err(Error::General("Invalid client certificate subject".into()));
}
Ok(verified)
}
fn verify_tls12_signature(&self, message: &[u8], cert: &CertificateDer<'_>, dss: &DigitallySignedStruct) -> Result<HandshakeSignatureValid, Error> {
self.default_verifier.verify_tls12_signature(message, cert, dss)
}
fn verify_tls13_signature(&self, message: &[u8], cert: &CertificateDer<'_>, dss: &DigitallySignedStruct) -> Result<HandshakeSignatureValid, Error> {
self.default_verifier.verify_tls13_signature(message, cert, dss)
}
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
self.default_verifier.supported_verify_schemes()
}
}