Browse Source

Apply PR 7747 review changes to emergency access

pull/7746/head
tom27052006 1 week ago
parent
commit
6525041dc7
  1. 32
      src/api/core/accounts.rs
  2. 43
      src/api/core/emergency_access.rs
  3. 4
      src/db/models/user.rs

32
src/api/core/accounts.rs

@ -708,18 +708,32 @@ fn set_kdf_data(user: &mut User, data: &KDFData) -> EmptyResult {
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct AuthenticationData {
pub(super) struct AuthenticationData {
salt: String,
kdf: KDFData,
master_password_authentication_hash: String,
pub(super) kdf: KDFData,
pub(super) master_password_authentication_hash: String,
}
impl AuthenticationData {
pub(super) fn check(&self, user: &User, unlock: &UnlockData) -> EmptyResult {
if self.kdf != unlock.kdf {
err!("KDF settings must be equal for authentication and unlock")
}
if self.salt != user.master_password_salt() || self.salt != unlock.salt {
err!("Invalid master password salt")
}
Ok(())
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct UnlockData {
pub(super) struct UnlockData {
salt: String,
kdf: KDFData,
master_key_wrapped_user_key: String,
pub(super) master_key_wrapped_user_key: String,
}
#[derive(Deserialize)]
@ -738,13 +752,7 @@ async fn post_kdf(data: Json<ChangeKdfData>, headers: Headers, conn: DbConn, nt:
err!("Invalid password")
}
if data.authentication_data.kdf != data.unlock_data.kdf {
err!("KDF settings must be equal for authentication and unlock")
}
if headers.user.email != data.authentication_data.salt || headers.user.email != data.unlock_data.salt {
err!("Invalid master password salt")
}
data.authentication_data.check(&headers.user, &data.unlock_data)?;
let mut user = headers.user;

43
src/api/core/emergency_access.rs

@ -6,7 +6,10 @@ use crate::{
CONFIG,
api::{
EmptyResult, JsonResult,
core::{CipherSyncData, CipherSyncType, accounts::KDFData},
core::{
CipherSyncData, CipherSyncType,
accounts::{AuthenticationData, UnlockData},
},
},
auth::{Headers, decode_emergency_access_invite},
db::{
@ -615,29 +618,13 @@ async fn takeover_emergency_access(emer_id: EmergencyAccessId, headers: Headers,
"kdfMemory": grantor_user.client_kdf_memory,
"kdfParallelism": grantor_user.client_kdf_parallelism,
"keyEncrypted": &emergency_access.key_encrypted,
"salt": master_password_salt(&grantor_user),
"salt": grantor_user.master_password_salt(),
"object": "emergencyAccessTakeover",
});
Ok(Json(result))
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct EmergencyAccessAuthenticationData {
salt: String,
kdf: KDFData,
master_password_authentication_hash: String,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct EmergencyAccessUnlockData {
salt: String,
kdf: KDFData,
master_key_wrapped_user_key: String,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct EmergencyAccessPasswordData {
@ -646,8 +633,8 @@ struct EmergencyAccessPasswordData {
key: Option<String>,
// Current payload
authentication_data: Option<EmergencyAccessAuthenticationData>,
unlock_data: Option<EmergencyAccessUnlockData>,
authentication_data: Option<AuthenticationData>,
unlock_data: Option<UnlockData>,
}
#[post("/emergency-access/<emer_id>/password", data = "<data>")]
@ -678,22 +665,12 @@ async fn password_emergency_access(
let (new_master_password_hash, new_key) =
if let (Some(authentication_data), Some(unlock_data)) = (data.authentication_data, data.unlock_data) {
if authentication_data.kdf != unlock_data.kdf {
err!("KDF settings must be equal for authentication and unlock")
}
if authentication_data.salt != unlock_data.salt {
err!("Invalid master password salt")
}
authentication_data.check(&grantor_user, &unlock_data)?;
if !authentication_data.kdf.matches_user(&grantor_user) {
err!("KDF settings do not match the grantor account")
}
if authentication_data.salt != master_password_salt(&grantor_user) {
err!("Invalid master password salt")
}
(authentication_data.master_password_authentication_hash, unlock_data.master_key_wrapped_user_key)
} else if let (Some(new_master_password_hash), Some(new_key)) = (data.new_master_password_hash, data.key) {
(new_master_password_hash, new_key)
@ -746,10 +723,6 @@ async fn policies_emergency_access(emer_id: EmergencyAccessId, headers: Headers,
})))
}
fn master_password_salt(user: &User) -> String {
user.email.trim().to_lowercase()
}
fn is_valid_request(
emergency_access: &EmergencyAccess,
requesting_user_id: &UserId,

4
src/db/models/user.rs

@ -166,6 +166,10 @@ impl User {
)
}
pub fn master_password_salt(&self) -> String {
self.email.trim().to_lowercase()
}
pub fn check_valid_recovery_code(&self, recovery_code: &str) -> bool {
if let Some(ref totp_recover) = self.totp_recover {
crypto::ct_eq(recovery_code, totp_recover.to_lowercase())

Loading…
Cancel
Save