tokio_rustls_acme/
resolver.rs

1use crate::acme::ACME_TLS_ALPN_NAME;
2use rustls::server::{ClientHello, ResolvesServerCert};
3use rustls::sign::CertifiedKey;
4use std::collections::BTreeMap;
5use std::sync::Arc;
6use std::sync::Mutex;
7
8#[derive(Debug)]
9pub struct ResolvesServerCertAcme {
10    inner: Mutex<Inner>,
11}
12
13#[derive(Debug)]
14struct Inner {
15    cert: Option<Arc<CertifiedKey>>,
16    auth_keys: BTreeMap<String, Arc<CertifiedKey>>,
17}
18
19impl ResolvesServerCertAcme {
20    pub(crate) fn new() -> Arc<Self> {
21        Arc::new(Self {
22            inner: Mutex::new(Inner {
23                cert: None,
24                auth_keys: Default::default(),
25            }),
26        })
27    }
28    pub(crate) fn set_cert(&self, cert: Arc<CertifiedKey>) {
29        self.inner.lock().unwrap().cert = Some(cert);
30    }
31    pub(crate) fn set_auth_key(&self, domain: String, cert: Arc<CertifiedKey>) {
32        self.inner.lock().unwrap().auth_keys.insert(domain, cert);
33    }
34}
35
36impl ResolvesServerCert for ResolvesServerCertAcme {
37    fn resolve(&self, client_hello: ClientHello) -> Option<Arc<CertifiedKey>> {
38        let is_acme_challenge = client_hello
39            .alpn()
40            .into_iter()
41            .flatten()
42            .eq([ACME_TLS_ALPN_NAME]);
43        if is_acme_challenge {
44            match client_hello.server_name() {
45                None => {
46                    log::debug!("client did not supply SNI");
47                    None
48                }
49                Some(domain) => {
50                    let domain = domain.to_owned();
51                    let domain: String = AsRef::<str>::as_ref(&domain).into();
52                    self.inner.lock().unwrap().auth_keys.get(&domain).cloned()
53                }
54            }
55        } else {
56            self.inner.lock().unwrap().cert.clone()
57        }
58    }
59}