use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use rustls::server::{ClientHello, ResolvesServerCert};
use rustls::sign::CertifiedKey;
use tracing::debug;
#[derive(Clone, Debug, Default)]
pub struct DynCertResolver {
certs: Arc<RwLock<HashMap<String, Arc<CertifiedKey>>>>,
}
impl DynCertResolver {
pub fn new() -> Self {
Self {
certs: Arc::new(RwLock::new(HashMap::new())),
}
}
pub fn add_cert(&self, domain: &str, key: Arc<CertifiedKey>) {
self.certs
.write()
.expect("cert store poisoned")
.insert(domain.to_string(), key);
}
pub fn has_cert(&self, domain: &str) -> bool {
self.certs
.read()
.expect("cert store poisoned")
.contains_key(domain)
}
}
impl ResolvesServerCert for DynCertResolver {
fn resolve(&self, client_hello: ClientHello<'_>) -> Option<Arc<CertifiedKey>> {
let sni = client_hello.server_name()?;
let certs = self.certs.read().expect("cert store poisoned");
let key = certs.get(sni).cloned();
if key.is_none() {
debug!(sni, "No cert for SNI hostname");
}
key
}
}