Move the tools' arguments and the host rules to proto
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
//! Host names and patterns, shared by `brokerd` and the egress proxy so both check hosts with the
|
||||
//! same rules.
|
||||
|
||||
/// A host label is 1 to 63 bytes of `a-z`, `0-9` or `-`, and neither starts nor ends with `-`.
|
||||
fn valid_label(label: &str) -> bool {
|
||||
if !(1..=63).contains(&label.len()) {
|
||||
return false;
|
||||
}
|
||||
let bytes = label.as_bytes();
|
||||
if bytes.iter().next() == Some(&b'-') || bytes.iter().last() == Some(&b'-') {
|
||||
return false;
|
||||
}
|
||||
bytes
|
||||
.iter()
|
||||
.all(|&byte| matches!(byte, b'a'..=b'z' | b'0'..=b'9' | b'-'))
|
||||
}
|
||||
|
||||
/// A host is 1 to 253 bytes of dot-separated labels, each a whole non-dot name, and the last label
|
||||
/// starts with a letter. That last rule keeps out every spelling of an IPv4 address.
|
||||
pub fn valid_host(host: &str) -> bool {
|
||||
if !(1..=253).contains(&host.len()) {
|
||||
return false;
|
||||
}
|
||||
let labels: Vec<&str> = host.split('.').collect();
|
||||
if labels.len() < 2 {
|
||||
return false;
|
||||
}
|
||||
for label in &labels {
|
||||
if !valid_label(label) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
match labels.iter().last() {
|
||||
Some(last) => matches!(last.bytes().next(), Some(byte) if byte.is_ascii_lowercase()),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// A host, or `*.` followed by a host. Nothing else.
|
||||
pub fn valid_host_pattern(pattern: &str) -> bool {
|
||||
match pattern.strip_prefix("*.") {
|
||||
Some(base) => valid_host(base),
|
||||
None => valid_host(pattern),
|
||||
}
|
||||
}
|
||||
|
||||
/// Does `pattern` match `host`? Without `*.` the strings must be equal; with `*.base` the host must
|
||||
/// end in `.base` with something before the dot.
|
||||
pub fn host_matches(pattern: &str, host: &str) -> bool {
|
||||
let base = match pattern.strip_prefix("*.") {
|
||||
Some(base) => base,
|
||||
None => return pattern == host,
|
||||
};
|
||||
match host.strip_suffix(base) {
|
||||
Some(before) => match before.strip_suffix('.') {
|
||||
Some(prefix) => !prefix.is_empty(),
|
||||
None => false,
|
||||
},
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user