From 50020b969e9e1b3aac4e0003a6b5197870893c41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Ml=C3=A1dek?= Date: Thu, 4 Apr 2024 21:07:29 +0200 Subject: [PATCH] fix: don't reveal whether a user exists --- cli/src/routes.rs | 2 +- db/src/lib.rs | 32 +++++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/cli/src/routes.rs b/cli/src/routes.rs index 2ebc252..c30ef88 100644 --- a/cli/src/routes.rs +++ b/cli/src/routes.rs @@ -96,7 +96,7 @@ pub async fn login( _ => Ok(HttpResponse::Ok().json(json!({ "key": token }))), } } - Err(e) => Err(ErrorUnauthorized(e)), + Err(_) => Err(ErrorUnauthorized("Invalid credentials.")), } } diff --git a/db/src/lib.rs b/db/src/lib.rs index 8a1eb06..3ff39b8 100644 --- a/db/src/lib.rs +++ b/db/src/lib.rs @@ -314,13 +314,21 @@ impl UpEndConnection { .filter(dsl::username.eq(username)) .load::(&conn)?; - let user = user_result.first().ok_or(anyhow!("User not found"))?; - - let parsed_hash = PasswordHash::new(&user.password).map_err(|e| anyhow!(e))?; - let argon2 = Argon2::default(); - argon2 - .verify_password(password.as_ref(), &parsed_hash) - .map_err(|e| anyhow!(e)) + match user_result.first() { + Some(user) => { + let parsed_hash = PasswordHash::new(&user.password).map_err(|e| anyhow!(e))?; + let argon2 = Argon2::default(); + argon2 + .verify_password(password.as_ref(), &parsed_hash) + .map_err(|e| anyhow!(e)) + } + None => { + let argon2 = Argon2::default(); + let _ = argon2 + .verify_password(password.as_ref(), &PasswordHash::new(&DUMMY_HASH).unwrap()); + Err(anyhow!("user not found")) + } + } } pub fn retrieve_entry(&self, hash: &UpMultihash) -> Result> { @@ -538,6 +546,16 @@ impl UpEndConnection { } } +lazy_static! { + static ref DUMMY_HASH: String = Argon2::default() + .hash_password( + "password".as_ref(), + &password_hash::SaltString::generate(&mut password_hash::rand_core::OsRng) + ) + .unwrap() + .to_string(); +} + #[cfg(test)] mod test { use upend_base::constants::{ATTR_IN, ATTR_LABEL};