connclass: resolve hash= independently of token order — the fold only ran if password= had already been parsed, so "hash=sha256 password=<hex>" (hash first) stored the digest as a plaintext password and every login to that class failed; build() now combines <algo>:<digest> after the full token pass
This commit is contained in:
parent
928026c49e
commit
e200779d27
1 changed files with 19 additions and 13 deletions
|
|
@ -69,18 +69,10 @@ fn apply(c: &mut ConnClass, k: &str, v: &str) {
|
||||||
c.ssl_trusted = v.eq_ignore_ascii_case("trusted");
|
c.ssl_trusted = v.eq_ignore_ascii_case("trusted");
|
||||||
}
|
}
|
||||||
"password" | "pass" => c.password = Some(v.to_string()),
|
"password" | "pass" => c.password = Some(v.to_string()),
|
||||||
"hash" => {
|
// `hash=` names the algorithm of a hashed password; it's folded into the
|
||||||
// name the algorithm of a hashed password: fold it into the stored
|
// stored credential in build() *after* the whole token pass, so it works
|
||||||
// credential (`<algo>:<digest>`) that verify() auto-detects, unless the
|
// regardless of whether it appears before or after `password=`.
|
||||||
// password value already carries its own prefix.
|
"hash" => {}
|
||||||
if let Some(pw) = c.password.take() {
|
|
||||||
c.password = Some(if pw.contains(':') {
|
|
||||||
pw
|
|
||||||
} else {
|
|
||||||
format!("{v}:{pw}")
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"port" => c.ports.extend(list(v).filter_map(|p| p.parse::<u16>().ok())),
|
"port" => c.ports.extend(list(v).filter_map(|p| p.parse::<u16>().ok())),
|
||||||
"localmax" => c.localmax = v.parse().ok(),
|
"localmax" => c.localmax = v.parse().ok(),
|
||||||
"globalmax" => c.globalmax = v.parse().ok(),
|
"globalmax" => c.globalmax = v.parse().ok(),
|
||||||
|
|
@ -146,11 +138,25 @@ fn build(s: &Server, name: &str) -> Option<ConnClass> {
|
||||||
resolvehostnames: true,
|
resolvehostnames: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
for tok in toks {
|
// resolve the hash algorithm independently of token order (see `apply`'s `hash`)
|
||||||
|
let hash_algo = toks
|
||||||
|
.iter()
|
||||||
|
.find_map(|t| t.strip_prefix("hash="))
|
||||||
|
.map(str::to_string);
|
||||||
|
for tok in &toks {
|
||||||
if let Some((k, v)) = tok.split_once('=') {
|
if let Some((k, v)) = tok.split_once('=') {
|
||||||
apply(&mut c, k, v);
|
apply(&mut c, k, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// fold `<algo>:<digest>` into the credential verify() auto-detects, unless the
|
||||||
|
// password already carries its own prefix.
|
||||||
|
if let (Some(algo), Some(pw)) = (hash_algo, c.password.take()) {
|
||||||
|
c.password = Some(if pw.contains(':') {
|
||||||
|
pw
|
||||||
|
} else {
|
||||||
|
format!("{algo}:{pw}")
|
||||||
|
});
|
||||||
|
}
|
||||||
if c.allow.is_empty() {
|
if c.allow.is_empty() {
|
||||||
c.allow.push("*".to_string()); // an unqualified class matches everyone
|
c.allow.push("*".to_string()); // an unqualified class matches everyone
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue