use std::fs::File; use std::io::BufReader; use std::sync::Arc; use std::time::SystemTime; use rustls::{Certificate, DistinguishedNames, Error, RootCertStore}; use rustls::server::{AllowAnyAuthenticatedClient, ClientCertVerified, ClientCertVerifier}; use rustls_pemfile::certs; use crate::server_config::ServerConfig; pub struct CustomCertClientVerifier { upstream_cert_verifier: Box>, } impl CustomCertClientVerifier { pub fn new(conf: Arc) -> Self { let cert_path = conf.tls_client_auth_root_cert.as_deref() .expect("No root certificates for client authentication provided!"); let cert_file = &mut BufReader::new(File::open(cert_path) .expect("Failed to read root certificates for client authentication!")); let root_certs = certs(cert_file).unwrap() .into_iter() .map(Certificate) .collect::>(); if root_certs.is_empty() { log::error!("No certificates found for client authentication!"); panic!(); } let mut store = RootCertStore::empty(); for cert in root_certs { store.add(&cert).expect("Failed to add certificate to root store"); } Self { upstream_cert_verifier: Box::new(AllowAnyAuthenticatedClient::new(store)), } } } impl ClientCertVerifier for CustomCertClientVerifier { fn offer_client_auth(&self) -> bool { true } fn client_auth_mandatory(&self) -> Option { Some(true) } fn client_auth_root_subjects(&self) -> Option { Some(vec![]) } fn verify_client_cert(&self, end_entity: &Certificate, intermediates: &[Certificate], now: SystemTime) -> Result { self.upstream_cert_verifier.verify_client_cert(end_entity, intermediates, now) } }