Fix crashes when entering an empty or incorrect password

This commit is contained in:
Jakub Hlusička 2026-03-01 01:10:52 +01:00
parent 014b099986
commit 18d8443891

View file

@ -55,11 +55,18 @@ pub mod window_adapter;
slint::include_modules!(); slint::include_modules!();
#[derive(Clone, Copy)]
struct EmptyPassword;
fn spectre_derive_user_key( fn spectre_derive_user_key(
username: &CStr, username: &CStr,
password: &CStr, password: &CStr,
encrypted_key: Option<Key>, encrypted_key: Option<Key>,
) -> SpectreUserKey { ) -> Result<SpectreUserKey, EmptyPassword> {
if password.is_empty() {
return Err(EmptyPassword);
}
if let Some(encrypted_key) = encrypted_key { if let Some(encrypted_key) = encrypted_key {
ACTIVE_ENCRYPTED_USER_KEY.lock(|user_key| { ACTIVE_ENCRYPTED_USER_KEY.lock(|user_key| {
user_key.set(encrypted_key); user_key.set(encrypted_key);
@ -84,7 +91,7 @@ fn spectre_derive_user_key(
// TODO: Erase memory before freeing // TODO: Erase memory before freeing
__spre_free(user_key as *const _ as *mut _); __spre_free(user_key as *const _ as *mut _);
user_key_stack Ok(user_key_stack)
} }
} }
@ -338,14 +345,16 @@ impl State {
fn process_callback_message( fn process_callback_message(
state_rc: &Rc<RefCell<State>, PsramAllocator>, state_rc: &Rc<RefCell<State>, PsramAllocator>,
message: CallbackMessage, mut message: CallbackMessage,
) { ) {
let view = state_rc.borrow().view; let view = state_rc.borrow().view;
match view { while let Some(next_message) = match view {
AppState::Login => StateLogin::process_callback_message(state_rc, message), AppState::Login => StateLogin::process_callback_message(state_rc, message),
AppState::Users => StateUsers::process_callback_message(state_rc, message), AppState::Users => StateUsers::process_callback_message(state_rc, message),
AppState::UserEdit => StateUserEdit::process_callback_message(state_rc, message), AppState::UserEdit => StateUserEdit::process_callback_message(state_rc, message),
AppState::UserSites => StateUserSites::process_callback_message(state_rc, message), AppState::UserSites => StateUserSites::process_callback_message(state_rc, message),
} {
message = next_message
} }
} }
@ -392,7 +401,8 @@ trait AppViewTrait {
fn process_callback_message( fn process_callback_message(
_state_rc: &Rc<RefCell<State>, PsramAllocator>, _state_rc: &Rc<RefCell<State>, PsramAllocator>,
_message: CallbackMessage, _message: CallbackMessage,
) { ) -> Option<CallbackMessage> {
None
} }
} }
@ -403,7 +413,7 @@ impl AppViewTrait for StateLogin {
fn process_callback_message( fn process_callback_message(
state_rc: &Rc<RefCell<State>, PsramAllocator>, state_rc: &Rc<RefCell<State>, PsramAllocator>,
message: CallbackMessage, message: CallbackMessage,
) { ) -> Option<CallbackMessage> {
let mut state = state_rc.borrow_mut(); let mut state = state_rc.borrow_mut();
match message { match message {
CallbackMessage::Login(CallbackMessageLogin::PwAccepted { CallbackMessage::Login(CallbackMessageLogin::PwAccepted {
@ -413,14 +423,18 @@ impl AppViewTrait for StateLogin {
}) => { }) => {
let Some(user) = state.users.users.row_data(user_index as usize) else { let Some(user) = state.users.users.row_data(user_index as usize) else {
error!("Failed to find a user with index {user_index}."); error!("Failed to find a user with index {user_index}.");
return; return None;
}; };
let username_c = CString::new(&*user.username) let username_c = CString::new(&*user.username)
.expect("Username cannot be converted to a C string."); .expect("Username cannot be converted to a C string.");
let password_c = let password_c =
CString::new(&*password).expect("Password cannot be converted to a C string."); CString::new(&*password).expect("Password cannot be converted to a C string.");
let user_key = let Ok(user_key) =
spectre_derive_user_key(&username_c, &password_c, Some(user.encrypted_key)); spectre_derive_user_key(&username_c, &password_c, Some(user.encrypted_key))
else {
error!("Password empty.");
return None;
};
// { // {
// let mut write = db.write_transaction().await; // let mut write = db.write_transaction().await;
@ -459,14 +473,10 @@ impl AppViewTrait for StateLogin {
// } // }
if user.key_id != user_key.keyID.bytes { if user.key_id != user_key.keyID.bytes {
State::process_callback_message( return Some(CallbackMessage::Login(CallbackMessageLogin::LoginResult {
state_rc,
CallbackMessage::Login(CallbackMessageLogin::LoginResult {
username: user.username, username: user.username,
result: LoginResult::Failure, result: LoginResult::Failure,
}), }));
);
return;
} }
slint::spawn_local({ slint::spawn_local({
@ -549,6 +559,8 @@ impl AppViewTrait for StateLogin {
} }
_ => (), _ => (),
} }
None
} }
} }
@ -559,7 +571,7 @@ impl AppViewTrait for StateUsers {
fn process_callback_message( fn process_callback_message(
state_rc: &Rc<RefCell<State>, PsramAllocator>, state_rc: &Rc<RefCell<State>, PsramAllocator>,
message: CallbackMessage, message: CallbackMessage,
) { ) -> Option<CallbackMessage> {
let mut state = state_rc.borrow_mut(); let mut state = state_rc.borrow_mut();
match message { match message {
CallbackMessage::Escape => { CallbackMessage::Escape => {
@ -577,6 +589,8 @@ impl AppViewTrait for StateUsers {
} }
_ => (), _ => (),
} }
None
} }
} }
@ -592,7 +606,7 @@ impl AppViewTrait for StateUserEdit {
fn process_callback_message( fn process_callback_message(
state_rc: &Rc<RefCell<State>, PsramAllocator>, state_rc: &Rc<RefCell<State>, PsramAllocator>,
message: CallbackMessage, message: CallbackMessage,
) { ) -> Option<CallbackMessage> {
let state = state_rc.clone(); let state = state_rc.clone();
let mut state = state.borrow_mut(); let mut state = state.borrow_mut();
match message { match message {
@ -630,7 +644,7 @@ impl AppViewTrait for StateUserEdit {
}) => { }) => {
let Some(password) = state.state_user_edit.password.as_ref() else { let Some(password) = state.state_user_edit.password.as_ref() else {
warn!("Attempted to compute a key ID when no password has been entered."); warn!("Attempted to compute a key ID when no password has been entered.");
return; return None;
}; };
let mut key: Key = [0; _]; let mut key: Key = [0; _];
@ -654,14 +668,18 @@ impl AppViewTrait for StateUserEdit {
} }
}; };
state.window.set_user_edit_key_error(message); state.window.set_user_edit_key_error(message);
return; return None;
} }
let username_c = CString::new(&*state.state_user_edit.username) let username_c = CString::new(&*state.state_user_edit.username)
.expect("Username cannot be converted to a C string."); .expect("Username cannot be converted to a C string.");
let password_c = let password_c =
CString::new(&**password).expect("Password cannot be converted to a C string."); CString::new(&**password).expect("Password cannot be converted to a C string.");
let user_key = spectre_derive_user_key(&username_c, &password_c, Some(key)); let Ok(user_key) = spectre_derive_user_key(&username_c, &password_c, Some(key))
else {
error!("Password empty.");
return None;
};
state.window.set_user_edit_key_error(SharedString::new()); state.window.set_user_edit_key_error(SharedString::new());
state.window.set_user_edit_key_id( state.window.set_user_edit_key_id(
@ -683,7 +701,7 @@ impl AppViewTrait for StateUserEdit {
)) = state.state_user_edit.encrypted_key.take() )) = state.state_user_edit.encrypted_key.take()
else { else {
warn!("Encrypted key is not set."); warn!("Encrypted key is not set.");
return; return None;
}; };
// If a user with that username already exists, overwrite it. // If a user with that username already exists, overwrite it.
@ -730,6 +748,8 @@ impl AppViewTrait for StateUserEdit {
} }
_ => (), _ => (),
} }
None
} }
} }
@ -745,7 +765,7 @@ impl AppViewTrait for StateUserSites {
fn process_callback_message( fn process_callback_message(
state_rc: &Rc<RefCell<State>, PsramAllocator>, state_rc: &Rc<RefCell<State>, PsramAllocator>,
message: CallbackMessage, message: CallbackMessage,
) { ) -> Option<CallbackMessage> {
let state = state_rc.clone(); let state = state_rc.clone();
let mut state = state.borrow_mut(); let mut state = state.borrow_mut();
match message { match message {
@ -763,12 +783,12 @@ impl AppViewTrait for StateUserSites {
}) => { }) => {
let Some(user_sites) = state.state_user_sites.as_mut() else { let Some(user_sites) = state.state_user_sites.as_mut() else {
error!("User sites uninitialized."); error!("User sites uninitialized.");
return; return None;
}; };
let Some(site_list_entry) = user_sites.site_list.row_data(site_list_index as usize) let Some(site_list_entry) = user_sites.site_list.row_data(site_list_index as usize)
else { else {
error!("Invalid site list entry index: {site_list_index}"); error!("Invalid site list entry index: {site_list_index}");
return; return None;
}; };
warn!("Site name accepted: {site_list_entry:?}"); warn!("Site name accepted: {site_list_entry:?}");
let site_name = match site_list_entry { let site_name = match site_list_entry {
@ -809,6 +829,8 @@ impl AppViewTrait for StateUserSites {
} }
_ => (), _ => (),
} }
None
} }
} }