diff options
author | metamuffin <metamuffin@disroot.org> | 2024-08-19 03:14:34 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-08-19 03:14:34 +0200 |
commit | d06821468e9a6e0d62c4b1ced21b1290e7a5bc47 (patch) | |
tree | 0ef2cade2bfb6a24f2bb3e65b074df81afd5b5dd /src | |
parent | 6c3524c381467483a025eda5e7e5f0ded53094fa (diff) | |
download | gnix-d06821468e9a6e0d62c4b1ced21b1290e7a5bc47.tar gnix-d06821468e9a6e0d62c4b1ced21b1290e7a5bc47.tar.bz2 gnix-d06821468e9a6e0d62c4b1ced21b1290e7a5bc47.tar.zst |
fallback cert
Diffstat (limited to 'src')
-rw-r--r-- | src/certs.rs | 24 | ||||
-rw-r--r-- | src/config.rs | 1 | ||||
-rw-r--r-- | src/main.rs | 2 |
3 files changed, 24 insertions, 3 deletions
diff --git a/src/certs.rs b/src/certs.rs index 27aab51..84d0fca 100644 --- a/src/certs.rs +++ b/src/certs.rs @@ -19,6 +19,7 @@ use webpki::EndEntityCert; pub struct CertPool { provider: &'static Arc<CryptoProvider>, domains: HashMap<String, Arc<CertifiedKey>>, + fallback: Option<Arc<CertifiedKey>>, } impl Default for CertPool { @@ -26,16 +27,30 @@ impl Default for CertPool { Self { provider: CryptoProvider::get_default().unwrap(), domains: Default::default(), + fallback: None, } } } impl CertPool { - pub fn load(roots: &[PathBuf]) -> Result<Self> { + pub fn load(roots: &[PathBuf], fallback: Option<PathBuf>) -> Result<Self> { let mut s = Self::default(); for r in roots { s.load_recursive(&r)?; } + if let Some(path) = fallback { + let keypath = path.join("privkey.pem"); + let certpath = if path.join("fullchain.pem").exists() { + path.join("fullchain.pem") + } else { + path.join("cert.pem") + }; + let certs = load_certs(&certpath)?; + let key = load_private_key(&keypath)?; + let skey = s.provider.key_provider.load_private_key(key)?; + let ck = CertifiedKey::new(certs.clone(), skey.clone()); + s.fallback = Some(Arc::new(ck)) + } Ok(s) } @@ -74,7 +89,12 @@ impl CertPool { impl ResolvesServerCert for CertPool { fn resolve(&self, client_hello: ClientHello<'_>) -> Option<Arc<CertifiedKey>> { - Some(self.domains.get(client_hello.server_name()?)?.clone()) + Some( + self.domains + .get(client_hello.server_name()?) + .or(self.fallback.as_ref())? + .clone(), + ) } } diff --git a/src/config.rs b/src/config.rs index 6a22657..a6f7d1b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -61,6 +61,7 @@ pub struct HttpsConfig { pub bind: Vec<SocketAddr>, #[serde(deserialize_with = "seq_or_not")] pub cert_path: Vec<PathBuf>, + pub cert_fallback: Option<PathBuf>, } // try deser Vec<T> but fall back to deser T and putting that in Vec diff --git a/src/main.rs b/src/main.rs index 56a9b19..e286924 100644 --- a/src/main.rs +++ b/src/main.rs @@ -146,7 +146,7 @@ async fn serve_https(state: Arc<State>) -> Result<()> { None => return Ok(()), }; let tls_config = { - let certs = CertPool::load(&https_config.cert_path)?; + let certs = CertPool::load(&https_config.cert_path, https_config.cert_fallback.clone())?; let mut cfg = rustls::ServerConfig::builder() .with_no_client_auth() .with_cert_resolver(Arc::new(certs)); |