auth: constant-time compare for VHOST and WEBIRC secrets — both used plain == on the config password, unlike oper/RPC/JWT secrets which already route through ct_eq; expose password_hash::ct_eq as the shared comparator and use it (usernames stay plain == — not secret)
This commit is contained in:
parent
c72b966e0a
commit
a09dfc74df
2 changed files with 13 additions and 3 deletions
|
|
@ -43,7 +43,12 @@ impl Command for Vhost {
|
||||||
let host = s.conf_all("vhost").iter().find_map(|line| {
|
let host = s.conf_all("vhost").iter().find_map(|line| {
|
||||||
let mut it = line.split_whitespace();
|
let mut it = line.split_whitespace();
|
||||||
match (it.next(), it.next(), it.next()) {
|
match (it.next(), it.next(), it.next()) {
|
||||||
(Some(u), Some(p), Some(h)) if u == user && p == pass => Some(h.to_string()),
|
(Some(u), Some(p), Some(h))
|
||||||
|
if u == user
|
||||||
|
&& crate::modules::password_hash::ct_eq(p.as_bytes(), pass.as_bytes()) =>
|
||||||
|
{
|
||||||
|
Some(h.to_string())
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -104,7 +109,11 @@ impl Command for WebIrc {
|
||||||
let Some(gw) = s
|
let Some(gw) = s
|
||||||
.webirc
|
.webirc
|
||||||
.iter()
|
.iter()
|
||||||
.find(|g| g.password == *pass && !g.ipmask.is_empty() && glob_match(&g.ipmask, &from))
|
.find(|g| {
|
||||||
|
crate::modules::password_hash::ct_eq(g.password.as_bytes(), pass.as_bytes())
|
||||||
|
&& !g.ipmask.is_empty()
|
||||||
|
&& glob_match(&g.ipmask, &from)
|
||||||
|
})
|
||||||
.map(|g| g.name.clone())
|
.map(|g| g.name.clone())
|
||||||
else {
|
else {
|
||||||
s.notice_star(uid, "WEBIRC: invalid credentials");
|
s.notice_star(uid, "WEBIRC: invalid credentials");
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,8 @@ fn unhex(s: &str) -> Option<Vec<u8>> {
|
||||||
|
|
||||||
/// Constant-time equality (guards against timing attacks on the compare).
|
/// Constant-time equality (guards against timing attacks on the compare).
|
||||||
/// `openssl::memcmp::eq` requires equal-length inputs, so short-circuit first.
|
/// `openssl::memcmp::eq` requires equal-length inputs, so short-circuit first.
|
||||||
fn ct_eq(a: &[u8], b: &[u8]) -> bool {
|
/// Shared comparator for any secret check (passwords, gateway/vhost secrets).
|
||||||
|
pub fn ct_eq(a: &[u8], b: &[u8]) -> bool {
|
||||||
a.len() == b.len() && openssl::memcmp::eq(a, b)
|
a.len() == b.len() && openssl::memcmp::eq(a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue