tokio_rustls_acme/
resolver.rs1use 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}