From a71da2d0a4e93034397134b17078a27829264043 Mon Sep 17 00:00:00 2001 From: Timshel Date: Wed, 6 Aug 2025 19:26:32 +0200 Subject: [PATCH] Perform same checks when setting kdf --- src/api/core/accounts.rs | 75 ++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 41 deletions(-) diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs index 2c954a2e..dedd6c9b 100644 --- a/src/api/core/accounts.rs +++ b/src/api/core/accounts.rs @@ -67,15 +67,22 @@ pub fn routes() -> Vec { ] } +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct KDFData { + kdf: i32, + kdf_iterations: i32, + kdf_memory: Option, + kdf_parallelism: Option, +} + #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RegisterData { email: String, - kdf: Option, - kdf_iterations: Option, - kdf_memory: Option, - kdf_parallelism: Option, + #[serde(flatten)] + kdf: KDFData, #[serde(alias = "userSymmetricKey")] key: String, @@ -101,10 +108,9 @@ pub struct RegisterData { #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SetPasswordData { - kdf: Option, - kdf_iterations: Option, - kdf_memory: Option, - kdf_parallelism: Option, + #[serde(flatten)] + kdf: KDFData, + key: String, keys: Option, master_password_hash: String, @@ -281,16 +287,7 @@ pub async fn _register(data: Json, email_verification: bool, mut c // Make sure we don't leave a lingering invitation. Invitation::take(&email, &mut conn).await; - if let Some(client_kdf_type) = data.kdf { - user.client_kdf_type = client_kdf_type; - } - - if let Some(client_kdf_iter) = data.kdf_iterations { - user.client_kdf_iter = client_kdf_iter; - } - - user.client_kdf_memory = data.kdf_memory; - user.client_kdf_parallelism = data.kdf_parallelism; + set_kdf_data(&mut user, data.kdf)?; user.set_password(&data.master_password_hash, Some(data.key), true, None); user.password_hint = password_hint; @@ -353,16 +350,7 @@ async fn post_set_password(data: Json, headers: Headers, mut co let password_hint = clean_password_hint(&data.master_password_hint); enforce_password_hint_setting(&password_hint)?; - if let Some(client_kdf_iter) = data.kdf_iterations { - user.client_kdf_iter = client_kdf_iter; - } - - if let Some(client_kdf_type) = data.kdf { - user.client_kdf_type = client_kdf_type; - } - - user.client_kdf_memory = data.kdf_memory; - user.client_kdf_parallelism = data.kdf_parallelism; + set_kdf_data(&mut user, data.kdf)?; user.set_password( &data.master_password_hash, @@ -552,25 +540,15 @@ async fn post_password(data: Json, headers: Headers, mut conn: D #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct ChangeKdfData { - kdf: i32, - kdf_iterations: i32, - kdf_memory: Option, - kdf_parallelism: Option, + #[serde(flatten)] + kdf: KDFData, master_password_hash: String, new_master_password_hash: String, key: String, } -#[post("/accounts/kdf", data = "")] -async fn post_kdf(data: Json, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { - let data: ChangeKdfData = data.into_inner(); - let mut user = headers.user; - - if !user.check_valid_password(&data.master_password_hash) { - err!("Invalid password") - } - +fn set_kdf_data(user: &mut User, data: KDFData) -> EmptyResult { if data.kdf == UserKdfType::Pbkdf2 as i32 && data.kdf_iterations < 100_000 { err!("PBKDF2 KDF iterations must be at least 100000.") } @@ -601,6 +579,21 @@ async fn post_kdf(data: Json, headers: Headers, mut conn: DbConn, } user.client_kdf_iter = data.kdf_iterations; user.client_kdf_type = data.kdf; + + Ok(()) +} + +#[post("/accounts/kdf", data = "")] +async fn post_kdf(data: Json, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { + let data: ChangeKdfData = data.into_inner(); + let mut user = headers.user; + + if !user.check_valid_password(&data.master_password_hash) { + err!("Invalid password") + } + + set_kdf_data(&mut user, data.kdf)?; + user.set_password(&data.new_master_password_hash, Some(data.key), true, None); let save_result = user.save(&mut conn).await;