summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-11-25 10:43:05 +0100
committermetamuffin <metamuffin@disroot.org>2024-11-25 10:43:17 +0100
commit163c801aa8ecbc5b037a8c19267893a2bc636f87 (patch)
tree68c23e26ffcedb8861809652e02553f728f7085b
parentcc5d7c08cca9cb4a14f1f99355262b9b3ff04b0c (diff)
downloadgnix-163c801aa8ecbc5b037a8c19267893a2bc636f87.tar
gnix-163c801aa8ecbc5b037a8c19267893a2bc636f87.tar.bz2
gnix-163c801aa8ecbc5b037a8c19267893a2bc636f87.tar.zst
support wildcard certificate autoselection
-rw-r--r--src/certs.rs20
1 files changed, 17 insertions, 3 deletions
diff --git a/src/certs.rs b/src/certs.rs
index 84d0fca..05a25c7 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>>,
+ wildcards: HashMap<String, Arc<CertifiedKey>>,
fallback: Option<Arc<CertifiedKey>>,
}
@@ -27,6 +28,7 @@ impl Default for CertPool {
Self {
provider: CryptoProvider::get_default().unwrap(),
domains: Default::default(),
+ wildcards: Default::default(),
fallback: None,
}
}
@@ -77,9 +79,14 @@ impl CertPool {
for c in &certs {
let eec = EndEntityCert::try_from(c).unwrap();
for name in eec.valid_dns_names() {
- debug!("loaded key for {name:?}");
let ck = CertifiedKey::new(certs.clone(), skey.clone());
- self.domains.insert(name.to_owned(), Arc::new(ck));
+ if let Some(name) = name.strip_prefix("*.") {
+ debug!("loaded wildcard key for {name:?}");
+ self.wildcards.insert(name.to_owned(), Arc::new(ck));
+ } else {
+ debug!("loaded key for {name:?}");
+ self.domains.insert(name.to_owned(), Arc::new(ck));
+ }
}
}
}
@@ -89,9 +96,16 @@ impl CertPool {
impl ResolvesServerCert for CertPool {
fn resolve(&self, client_hello: ClientHello<'_>) -> Option<Arc<CertifiedKey>> {
+ let sname = client_hello.server_name()?;
Some(
self.domains
- .get(client_hello.server_name()?)
+ .get(sname)
+ .or_else(|| {
+ // Removing first label seems fine since wildcards are not recursive.
+ sname
+ .split_once(".")
+ .and_then(|(_, sname)| self.wildcards.get(sname))
+ })
.or(self.fallback.as_ref())?
.clone(),
)