mirror of
https://github.com/YGGverse/agate.git
synced 2026-04-09 13:05:29 +00:00
improve comments
This commit is contained in:
parent
564424702a
commit
5dbb4be864
1 changed files with 20 additions and 8 deletions
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue