fix: security and correctness audit fixes (v0.4.1)
PAM conv callback: check msg_style (password only for ECHO_OFF), handle strdup OOM with proper cleanup, null-check PAM handle. Fingerprint: self-wire D-Bus g-signal in start() via Rc<RefCell<>> and connect_local — VerifyStatus signals are now actually dispatched. VerifyStop before VerifyStart in restart_verify. Lockscreen: password entry stays active after faillock threshold (PAM decides lockout, not UI), use Zeroizing<String> from GTK entry. Release builds exit(1) without ext-session-lock-v1 support. Config: fingerprint_enabled as Option<bool> so empty user config does not override system config. Dead code: remove unused i18n strings and fingerprint accessors, parameterize faillock_warning max_attempts.
This commit is contained in:
+26
-9
@@ -10,6 +10,8 @@ use std::cell::RefCell;
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
use crate::auth;
|
||||
use crate::config::Config;
|
||||
use crate::fingerprint::FingerprintListener;
|
||||
@@ -24,6 +26,7 @@ const FAILLOCK_MAX_ATTEMPTS: u32 = 3;
|
||||
struct LockscreenState {
|
||||
failed_attempts: u32,
|
||||
fp_listener: FingerprintListener,
|
||||
fp_listener_rc: Option<Rc<RefCell<FingerprintListener>>>,
|
||||
}
|
||||
|
||||
/// Create a lockscreen window for a single monitor.
|
||||
@@ -54,6 +57,7 @@ pub fn create_lockscreen_window(
|
||||
let state = Rc::new(RefCell::new(LockscreenState {
|
||||
failed_attempts: 0,
|
||||
fp_listener,
|
||||
fp_listener_rc: None,
|
||||
}));
|
||||
|
||||
// Root overlay for background + centered content
|
||||
@@ -205,7 +209,7 @@ pub fn create_lockscreen_window(
|
||||
#[weak]
|
||||
password_entry,
|
||||
move |entry| {
|
||||
let password = entry.text().to_string();
|
||||
let password = Zeroizing::new(entry.text().to_string());
|
||||
if password.is_empty() {
|
||||
return;
|
||||
}
|
||||
@@ -223,14 +227,18 @@ pub fn create_lockscreen_window(
|
||||
password_entry,
|
||||
async move {
|
||||
let user = username.clone();
|
||||
let pass = password.clone();
|
||||
let pass = Zeroizing::new((*password).clone());
|
||||
let result = gio::spawn_blocking(move || {
|
||||
auth::authenticate(&user, &pass)
|
||||
}).await;
|
||||
|
||||
match result {
|
||||
Ok(true) => {
|
||||
state.borrow_mut().fp_listener.stop();
|
||||
let s = state.borrow();
|
||||
if let Some(ref fp_rc) = s.fp_listener_rc {
|
||||
fp_rc.borrow_mut().stop();
|
||||
}
|
||||
drop(s);
|
||||
unlock_cb();
|
||||
}
|
||||
_ => {
|
||||
@@ -241,13 +249,15 @@ pub fn create_lockscreen_window(
|
||||
password_entry.set_text("");
|
||||
|
||||
if count >= FAILLOCK_MAX_ATTEMPTS {
|
||||
// Show warning but keep entry active — PAM decides lockout
|
||||
error_label.set_text(strings.faillock_locked);
|
||||
error_label.set_visible(true);
|
||||
password_entry.set_sensitive(false);
|
||||
password_entry.set_sensitive(true);
|
||||
password_entry.grab_focus();
|
||||
} else {
|
||||
password_entry.set_sensitive(true);
|
||||
password_entry.grab_focus();
|
||||
if let Some(warning) = faillock_warning(count, strings) {
|
||||
if let Some(warning) = faillock_warning(count, FAILLOCK_MAX_ATTEMPTS, strings) {
|
||||
error_label.set_text(&warning);
|
||||
} else {
|
||||
error_label.set_text(strings.wrong_password);
|
||||
@@ -325,10 +335,17 @@ pub fn create_lockscreen_window(
|
||||
));
|
||||
};
|
||||
|
||||
state
|
||||
.borrow_mut()
|
||||
.fp_listener
|
||||
.start(&user.username, on_success, on_failure);
|
||||
// Extract the fp_listener into its own Rc<RefCell<>> for signal self-wiring
|
||||
let fp_rc = {
|
||||
let mut s = state.borrow_mut();
|
||||
let listener = std::mem::replace(&mut s.fp_listener, FingerprintListener::new());
|
||||
Rc::new(RefCell::new(listener))
|
||||
};
|
||||
|
||||
FingerprintListener::start(&fp_rc, &user.username, on_success, on_failure);
|
||||
|
||||
// Store back the Rc reference for stop() on unlock
|
||||
state.borrow_mut().fp_listener_rc = Some(fp_rc);
|
||||
}
|
||||
|
||||
// Fade-in on map
|
||||
|
||||
Reference in New Issue
Block a user