fix: audit fixes — fprintd path validation, progressive faillock warning (v0.6.7)
All checks were successful
Update PKGBUILD version / update-pkgver (push) Successful in 1s
All checks were successful
Update PKGBUILD version / update-pkgver (push) Successful in 1s
- Validate fprintd device path prefix (/net/reactivated/Fprint/Device/) before creating D-Bus proxy (prevents use of unexpected object paths) - faillock_warning now warns at remaining <= 2 attempts (not just == 1), improving UX for higher max_attempts configurations
This commit is contained in:
parent
af5b7c8912
commit
59c509dcbb
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -575,7 +575,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "moonlock"
|
||||
version = "0.6.5"
|
||||
version = "0.6.7"
|
||||
dependencies = [
|
||||
"gdk-pixbuf",
|
||||
"gdk4",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "moonlock"
|
||||
version = "0.6.6"
|
||||
version = "0.6.7"
|
||||
edition = "2024"
|
||||
description = "A secure Wayland lockscreen with GTK4, PAM and fingerprint support"
|
||||
license = "MIT"
|
||||
|
||||
@ -13,6 +13,7 @@ const FPRINTD_DEVICE_IFACE: &str = "net.reactivated.Fprint.Device";
|
||||
|
||||
const MAX_FP_ATTEMPTS: u32 = 10;
|
||||
const DBUS_TIMEOUT_MS: i32 = 3000;
|
||||
const FPRINTD_DEVICE_PREFIX: &str = "/net/reactivated/Fprint/Device/";
|
||||
|
||||
/// Retry-able statuses — finger not read properly, try again.
|
||||
const RETRY_STATUSES: &[&str] = &[
|
||||
@ -99,6 +100,10 @@ impl FingerprintListener {
|
||||
if device_path.is_empty() {
|
||||
return;
|
||||
}
|
||||
if !device_path.starts_with(FPRINTD_DEVICE_PREFIX) {
|
||||
log::warn!("Unexpected fprintd device path: {device_path}");
|
||||
return;
|
||||
}
|
||||
|
||||
match gio::DBusProxy::for_bus_future(
|
||||
gio::BusType::System,
|
||||
|
||||
24
src/i18n.rs
24
src/i18n.rs
@ -100,11 +100,13 @@ pub fn load_strings(locale: Option<&str>) -> &'static Strings {
|
||||
match locale { "de" => &STRINGS_DE, _ => &STRINGS_EN }
|
||||
}
|
||||
|
||||
/// Returns a warning when the user is one attempt away from lockout.
|
||||
/// Returns a warning when the user is close to lockout (2 or fewer attempts remaining).
|
||||
/// Caller is responsible for handling the locked state (count >= max_attempts).
|
||||
pub fn faillock_warning(attempt_count: u32, max_attempts: u32, strings: &Strings) -> Option<String> {
|
||||
let remaining = max_attempts.saturating_sub(attempt_count);
|
||||
if remaining == 1 { return Some(strings.faillock_attempts_remaining.replace("{n}", &remaining.to_string())); }
|
||||
if remaining > 0 && remaining <= 2 {
|
||||
return Some(strings.faillock_attempts_remaining.replace("{n}", &remaining.to_string()));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
@ -138,7 +140,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test] fn faillock_zero() { assert!(faillock_warning(0, 3, load_strings(Some("en"))).is_none()); }
|
||||
#[test] fn faillock_one() { assert!(faillock_warning(1, 3, load_strings(Some("en"))).is_none()); }
|
||||
#[test] fn faillock_one() { assert!(faillock_warning(1, 3, load_strings(Some("en"))).is_some()); }
|
||||
#[test] fn faillock_two() { assert!(faillock_warning(2, 3, load_strings(Some("en"))).is_some()); }
|
||||
#[test] fn faillock_three() { assert!(faillock_warning(3, 3, load_strings(Some("en"))).is_none()); }
|
||||
|
||||
@ -150,11 +152,23 @@ mod tests {
|
||||
let strings = load_strings(Some("en"));
|
||||
for count in 0..max {
|
||||
let result = faillock_warning(count, max, strings);
|
||||
if max - count == 1 {
|
||||
assert!(result.is_some(), "should warn at count={count}");
|
||||
let remaining = max - count;
|
||||
if remaining <= 2 {
|
||||
assert!(result.is_some(), "should warn at count={count} (remaining={remaining})");
|
||||
} else {
|
||||
assert!(result.is_none(), "should not warn at count={count}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn faillock_warns_progressively_with_higher_max() {
|
||||
let strings = load_strings(Some("en"));
|
||||
// With max=5: warn at count 3 (rem=2) and count 4 (rem=1), not at 0-2
|
||||
assert!(faillock_warning(0, 5, strings).is_none());
|
||||
assert!(faillock_warning(2, 5, strings).is_none());
|
||||
assert!(faillock_warning(3, 5, strings).is_some());
|
||||
assert!(faillock_warning(4, 5, strings).is_some());
|
||||
assert!(faillock_warning(5, 5, strings).is_none()); // at max, caller handles lockout
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user