diff --git a/Cargo.lock b/Cargo.lock index e6f8648cf..b7396d431 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1979,6 +1979,7 @@ dependencies = [ "serde", "serde_json", "slab", + "subtle", "thiserror", "tokio", "tokio-native-tls", diff --git a/rumqttd/CHANGELOG.md b/rumqttd/CHANGELOG.md index ba5c627eb..6d981ffd7 100644 --- a/rumqttd/CHANGELOG.md +++ b/rumqttd/CHANGELOG.md @@ -28,7 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Make write method return the number of bytes written correctly everywhere ### Security - +- Implement constant-time password comparison in authentication logic --- ## [rumqttd 0.19.0] - 12-12-2023 diff --git a/rumqttd/Cargo.toml b/rumqttd/Cargo.toml index 3b2b9af7b..2de4f4201 100644 --- a/rumqttd/Cargo.toml +++ b/rumqttd/Cargo.toml @@ -38,6 +38,7 @@ clap = { version = "4.4", features = ["derive"] } axum = "0.7.4" rand = "0.8.5" uuid = { version = "1.7.0", features = ["v4", "fast-rng"] } +subtle = "2.5" [features] default = ["use-rustls", "websocket"] diff --git a/rumqttd/src/link/remote.rs b/rumqttd/src/link/remote.rs index 69fc439d7..e289802de 100644 --- a/rumqttd/src/link/remote.rs +++ b/rumqttd/src/link/remote.rs @@ -12,6 +12,7 @@ use std::collections::VecDeque; use std::io; use std::sync::Arc; use std::time::Duration; +use subtle::ConstantTimeEq; use tokio::time::error::Elapsed; use tokio::{select, time}; use tracing::{trace, Span}; @@ -254,15 +255,13 @@ async fn handle_auth( } if let Some(pairs) = &config.auth { - let static_auth_verified = pairs - .iter() - .any(|(user, pass)| (user, pass) == (username, password)); - - if !static_auth_verified { - return Err(Error::InvalidAuth); + if let Some(stored_password) = pairs.get(username) { + if stored_password.as_bytes().ct_eq(password.as_bytes()).into() { + return Ok(()); + } } - return Ok(()); + return Err(Error::InvalidAuth); } Err(Error::InvalidAuth)