improve comments

This commit is contained in:
Johann150 2021-03-03 23:09:29 +01:00
parent 564424702a
commit 5dbb4be864
No known key found for this signature in database
GPG key ID: 9EE6577A2A06F8F1

View file

@ -18,7 +18,8 @@ use {
/// A struct that holds all loaded certificates and the respective domain /// A struct that holds all loaded certificates and the respective domain
/// names. /// names.
pub(crate) struct CertStore { pub(crate) struct CertStore {
// use a Vec of pairs instead of a HashMap because order matters /// Stores the certificates and the domains they apply to, sorted by domain
/// names, longest matches first
certs: Vec<(String, CertifiedKey)>, certs: Vec<(String, CertifiedKey)>,
} }
@ -133,7 +134,8 @@ impl CertStore {
// load all certificates from directories // load all certificates from directories
let mut certs = vec![]; let mut certs = vec![];
// try to load fallback certificate and key // Try to load fallback certificate and key directly from the top level
// certificate directory. It will be loaded as the `.` domain.
match load_domain(certs_dir, ".".to_string()) { match load_domain(certs_dir, ".".to_string()) {
Err(CertLoadError::EmptyDomain(_)) => { /* there are no fallback keys */ } Err(CertLoadError::EmptyDomain(_)) => { /* there are no fallback keys */ }
Err(CertLoadError::NoReadCertDir) => unreachable!(), Err(CertLoadError::NoReadCertDir) => unreachable!(),
@ -153,8 +155,9 @@ impl CertStore {
Err(CertLoadError::MissingCert(_)) => { Err(CertLoadError::MissingCert(_)) => {
return Err(CertLoadError::MissingCert("fallback".to_string())) return Err(CertLoadError::MissingCert("fallback".to_string()))
} }
// if there are files, just push them because there is no domain // For the fallback keys there is no domain name to verify them
// name to check against // against, so we can skip that step and only have to do it for the
// other keys below.
Ok(key) => certs.push((String::new(), key)), Ok(key) => certs.push((String::new(), key)),
} }
@ -165,6 +168,8 @@ impl CertStore {
.filter(|x| x.path().is_dir()) .filter(|x| x.path().is_dir())
{ {
let path = file.path(); let path = file.path();
// the filename should be the domain name
let filename = path let filename = path
.file_name() .file_name()
.and_then(OsStr::to_str) .and_then(OsStr::to_str)
@ -184,14 +189,17 @@ impl CertStore {
} }
certs.sort_unstable_by(|(a, _), (b, _)| { certs.sort_unstable_by(|(a, _), (b, _)| {
// try to match as many as possible. If one is a substring of the other, // Try to match as many domain segments as possible. If one is a
// the `zip` will make them look equal and make the length decide. // substring of the other, the `zip` will only compare the smaller
// length of either a or b and the for loop will not decide.
for (a_part, b_part) in a.split('.').rev().zip(b.split('.').rev()) { for (a_part, b_part) in a.split('.').rev().zip(b.split('.').rev()) {
if a_part != b_part { if a_part != b_part {
// What we sort by here is not really important, but `str`
// already implements Ord, making it easier for us.
return a_part.cmp(b_part); return a_part.cmp(b_part);
} }
} }
// longer domains first // Sort longer domains first.
a.len().cmp(&b.len()).reverse() a.len().cmp(&b.len()).reverse()
}); });
@ -203,13 +211,17 @@ impl ResolvesServerCert for CertStore {
fn resolve(&self, client_hello: rustls::ClientHello<'_>) -> Option<CertifiedKey> { fn resolve(&self, client_hello: rustls::ClientHello<'_>) -> Option<CertifiedKey> {
if let Some(name) = client_hello.server_name() { if let Some(name) = client_hello.server_name() {
let name: &str = name.into(); let name: &str = name.into();
// The certificate list is sorted so the longest match will always
// appear first. We have to find the first that is either this
// domain or a parent domain of the current one.
self.certs self.certs
.iter() .iter()
.find(|(s, _)| name.ends_with(s)) .find(|(s, _)| name.ends_with(s))
// only the key is interesting
.map(|(_, k)| k) .map(|(_, k)| k)
.cloned() .cloned()
} else { } else {
// This kind of resolver requires SNI // This kind of resolver requires SNI.
None None
} }
} }