use crate::fingerprint::Fingerprint; use rustls::{client::{ServerCertVerified, ServerCertVerifier}, Certificate}; use super::store::CertificateStore; pub struct Verifier<'a, T: CertificateStore> { store: &'a T, } impl<'a, T: CertificateStore + Sync> ServerCertVerifier for Verifier<'a, T> { fn verify_server_cert( &self, end_entity: &Certificate, _intermediates: &[Certificate], server_name: &rustls::ServerName, _scts: &mut dyn Iterator, _ocsp_response: &[u8], _now: std::time::SystemTime, ) -> Result { let fp = end_entity.fingerprint().map_err(|e| rustls::Error::General(e.to_string()))?; let name = match server_name { rustls::ServerName::DnsName(n) => n.as_ref().to_string(), rustls::ServerName::IpAddress(ip) => ip.to_string(), _ => todo!() }; if let Some(fingerprint) = match server_name { rustls::ServerName::DnsName(n) => self.store.get(n.as_ref()), rustls::ServerName::IpAddress(ip) => self.store.get(&ip.to_string()), _ => todo!(), } { if fingerprint == fp.1 && name == fp.0 { return Ok(ServerCertVerified::assertion()); } } else { // todo: need a way to update `self.store`. Probably will require // an Arc> for interior mutability } return Err(rustls::Error::General("Unrecognized certificate".to_string())); } }