From ec21bad7e6db647fc746cce2ca384c8e25bbd6a6 Mon Sep 17 00:00:00 2001 From: Emmanuel Bosquet Date: Tue, 13 Feb 2024 18:06:29 +0100 Subject: [PATCH] fix removal of certificate with identical fingerprint --- lib/src/tls.rs | 77 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 4 deletions(-) diff --git a/lib/src/tls.rs b/lib/src/tls.rs index 87666caf9..d77431641 100644 --- a/lib/src/tls.rs +++ b/lib/src/tls.rs @@ -88,7 +88,12 @@ impl TryFrom<&AddCertificate> for CertifiedKeyWrapper { parse_pem(cert.certificate.as_bytes()).map_err(CertificateResolverError::ParsePem)?; let x509 = parse_x509(&pem.contents).map_err(CertificateResolverError::ParseX509)?; - let overriding_names = get_cn_and_san_attributes(&x509); + + let overriding_names = if add.certificate.names.is_empty() { + get_cn_and_san_attributes(&x509) + } else { + add.certificate.names.clone() + }; let expiration = add .expired_at @@ -176,9 +181,6 @@ impl CertificateResolver { return Ok(cert_to_add.fingerprint); } - self.certificates - .insert(cert_to_add.fingerprint.to_owned(), cert_to_add.clone()); - for new_name in &cert_to_add.names { self.domains.remove(&new_name.to_owned().into_bytes()); @@ -205,6 +207,9 @@ impl CertificateResolver { self.certificates.remove(outdated); } + self.certificates + .insert(cert_to_add.fingerprint.to_owned(), cert_to_add.clone()); + Ok(cert_to_add.fingerprint.to_owned()) } @@ -495,6 +500,70 @@ mod tests { Ok(()) } + #[test] + fn properly_replace_outdated_cert() -> Result<(), Box> { + let address = SocketAddress::new_v4(127, 0, 0, 1, 8080); + let mut resolver = CertificateResolver::default(); + + let first_certificate = CertificateAndKey { + certificate: String::from(include_str!("../assets/tests/certificate-1y.pem")), + key: String::from(include_str!("../assets/tests/key.pem")), + names: vec!["localhost".into()], + ..Default::default() + }; + let first = resolver.add_certificate(&AddCertificate { + address: address.clone(), + certificate: first_certificate, + expired_at: None, + })?; + if resolver.get_certificate(&first).is_none() { + return Err("failed to retrieve first certificate".into()); + } + println!("{:#?}", resolver); + match resolver.domain_lookup("localhost".as_bytes(), true) { + Some((_, fingerprint)) if fingerprint == &first => {} + Some((domain, fingerprint)) => { + return Err(format!( + "failed to lookup first inserted certificate. domain: {:?}, fingerprint: {}", + domain, fingerprint + ) + .into()) + } + _ => return Err("failed to lookup first inserted certificate".into()), + } + + let second_certificate = CertificateAndKey { + certificate: String::from(include_str!("../assets/tests/certificate-2y.pem")), + key: String::from(include_str!("../assets/tests/key.pem")), + names: vec!["localhost".into(), "lolcatho.st".into()], + ..Default::default() + }; + let second = resolver.add_certificate(&AddCertificate { + address, + certificate: second_certificate, + expired_at: None, + })?; + println!("\n{:#?}\n", resolver); + + if resolver.get_certificate(&second).is_none() { + return Err("failed to retrieve second certificate".into()); + } + + match resolver.domain_lookup("localhost".as_bytes(), true) { + Some((_, fingerprint)) if fingerprint == &second => {} + Some((domain, fingerprint)) => { + return Err(format!( + "failed to lookup second inserted certificate. domain: {:?}, fingerprint: {}", + domain, fingerprint + ) + .into()) + } + _ => return Err("the former certificate has not been overriden by the new one".into()), + } + + Ok(()) + } + #[test] fn replacement() -> Result<(), Box> { let address = SocketAddress::new_v4(127, 0, 0, 1, 8080);