Commit Graph
54 Commits
Author SHA1 Message Date
nevaforget 0c9773123b fix: audit LOW fixes — docs, rustdoc, scope, debug gate, lto fat (v0.6.12)
- Update CLAUDE.md and README.md to reflect the blur range [0,200] that
  the code has clamped to since v0.6.8.
- Move the // SYNC: comment above the /// doc on MAX_BLUR_DIMENSION so
  rustdoc renders one coherent paragraph instead of a truncated sentence.
- Narrow check_account visibility to pub(crate) and document the caller
  precondition (username must come from users::get_current_user()).
- Gate MOONLOCK_DEBUG behind #[cfg(debug_assertions)]. Release builds
  always run at LevelFilter::Info so a session script cannot escalate
  journal verbosity to leak fprintd / D-Bus internals.
- Document why pam_setcred is deliberately not called in authenticate().
- Release profile: lto = "fat" instead of "thin" — doubles release build
  time for better cross-crate inlining on the auth + i18n hot paths.
v0.6.12
2026-04-24 14:05:17 +02:00
nevaforget d0df3392da fix: audit MEDIUM fixes — D-Bus race, TOCTOU, FP reset, entry clear (v0.6.11)
- fingerprint: split cleanup_dbus into a sync take_cleanup_proxy() + async
  perform_dbus_cleanup(). resume_async now awaits VerifyStop+Release before
  re-claiming, so fprintd cannot reject the Claim on a slow bus. stop()
  still spawns the cleanup fire-and-forget.
- fingerprint: remove failed_attempts = 0 from resume_async. An attacker
  with sensor control could otherwise cycle verify-match → account-fail →
  resume and never trip the 10-attempt cap.
- lockscreen: open the wallpaper with O_NOFOLLOW and build the texture
  from bytes, closing the TOCTOU between the symlink check and Texture::
  from_file.
- lockscreen: clear password_entry immediately after extracting the
  Zeroizing<String>, shortening the window the GLib GString copy stays in
  libc-malloc'd memory.
v0.6.11
2026-04-24 13:21:19 +02:00
nevaforget da7c713c6b fix: audit fixes — RefCell across await, async avatar decode (v0.6.10)
- init_fingerprint_async: hoist username before the await so a concurrent
  connect_monitor signal (hotplug / suspend-resume) cannot cause a RefCell
  panic. Re-borrow after the await for signal wiring.
- set_avatar_from_file: decode via gio::File::read_future +
  Pixbuf::from_stream_at_scale_future so the GTK main thread stays
  responsive during monitor hotplug. Default icon shown while loading.
v0.6.10
2026-04-24 12:34:00 +02:00
nevaforget f2dde0550e docs: drop Nyx persona, unify attribution on ClaudeCode
Remove the Nyx persona block from CLAUDE.md and rewrite prior
DECISIONS entries from Nyx and leftover Ragnar to ClaudeCode for
consistency with the rest of the ecosystem.
2026-04-21 09:03:23 +02:00
nevaforget 8a0033a1ef style: replace hardcoded colors with GTK theme variables
Use @theme_bg_color, @theme_fg_color, @error_color and @success_color
instead of hardcoded hex values and 'white'. Makes moonlock respect the
active GTK theme instead of assuming Catppuccin Mocha colors.

Note: moongreet and moonset still use hardcoded colors and should be
updated to match.
2026-04-09 14:51:29 +02:00
nevaforget 3dd2995074 fix: handle monitor hotplug to survive suspend/resume (v0.6.9)
moonlock crashed with segfault in libgtk-4.so after suspend/resume when
HDMI monitors disconnected and reconnected, invalidating GDK monitor
objects that statically created windows still referenced.

Replace manual monitor iteration with connect_monitor signal (v1_2) that
fires both at lock time and on hotplug. Windows are now created on demand
per monitor event and auto-unmap when their monitor disappears.
v0.6.9
2026-04-09 14:48:06 +02:00
nevaforget 46a29f64fc Remove unnecessary pacman git install from CI workflow
Git is already available in the runner image.
2026-04-02 08:28:08 +02:00
nevaforget 7bc0f77872 Revert CI workaround: remove pacman install step
The act_runner now uses a custom Arch-based image with git
pre-installed, so per-workflow installs are no longer needed.
2026-04-01 16:17:45 +02:00
nevaforget 4b3dbecd5c fix: audit fixes — peek icon, blur limit, GResource compression, sync markers (v0.6.8)
- Enable peek icon on password entry (consistent with moongreet)
- Raise blur limit from 100 to 200 (consistent with moongreet/moonset)
- Add compressed="true" to GResource CSS/SVG entries
- Add SYNC comments to duplicated blur/background functions
v0.6.8
2026-03-31 11:08:36 +02:00
nevaforget 76e61616eb docs: update README features and fix build.rs comment
README was missing features added since v0.6.1 (GPU blur, journal
logging, lock-first architecture, PAM timeout, fprintd sender
validation, progressive faillock). build.rs comment still referenced
removed wallpaper.jpg.
2026-03-31 09:34:06 +02:00
nevaforget 974579e41b fix: audit fixes — fprintd path validation, progressive faillock warning (v0.6.7)
- 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
v0.6.7
2026-03-30 16:08:59 +02:00
nevaforget 250fc0461d ci: also update .SRCINFO in pkgver workflow
paru reads .SRCINFO (not PKGBUILD) for version comparison during
sysupgrade. Without updating .SRCINFO, paru never detects upgrades
for PKGBUILD repository packages.
2026-03-30 13:49:03 +02:00
nevaforget 4d803f8469 fix: audit fixes — blur offset, lock-before-IO, FP signal lifecycle, TOCTOU (v0.6.6)
Third triple audit (quality, performance, security). Key fixes:
- Blur padding offset: texture at (-pad,-pad) prevents edge darkening on all sides
- Wallpaper loads after lock.lock() — disk I/O no longer delays lock acquisition
- begin_verification disconnects old signal handler before registering new one
- resume_async resets failed_attempts to prevent premature exhaustion
- Unknown VerifyStatus with done=true triggers restart instead of hanging
- symlink_metadata() replaces separate is_file()+is_symlink() (TOCTOU)
- faillock_warning dead code removed, blur sigma clamped to [0,100]
- Redundant Zeroizing<Vec<u8>> removed, on_verify_status restricted to pub(crate)
- Warn logging for non-UTF-8 GECOS and avatar path errors
- Default impl for FingerprintListener, 3 new tests (47 total)
2026-03-30 13:09:02 +02:00
nevaforget e83b5149bb fix: audit fixes — CString zeroize, FP account check, PAM timeout, blur downscale (v0.6.5)
Address findings from second triple audit (quality, performance, security):

- Wrap PAM CString password in Zeroizing<CString> to wipe on drop (S-H1)
- Add check_account() for pam_acct_mgmt after fingerprint unlock,
  with resume_async() to restart FP on transient failure (S-M1)
- 30s PAM timeout with generation counter to prevent stale result
  interference from parallel auth attempts (S-M3)
- Downscale wallpaper to max 1920px before GPU blur, reducing work
  by ~4x on 4K wallpapers (P-M1)
- exit(1) instead of return on no-monitor after lock.lock() (Q-2.1)
2026-03-30 00:24:43 +02:00
nevaforget ac96b899be ci: add workflow to auto-update pkgver in moonarch-pkgbuilds 2026-03-29 23:05:09 +02:00
nevaforget b23e4c1fc8 fix: elevate CSS priority to override GTK4 user theme (v0.6.4)
Colloid-Catppuccin theme loaded via ~/.config/gtk-4.0/gtk.css at
PRIORITY_USER (800) was overriding moonlock's PRIORITY_APPLICATION (600),
causing avatar to lose its circular border-radius.

- Use STYLE_PROVIDER_PRIORITY_USER for app CSS provider
- Replace border-radius: 50% with 9999px (GTK4 CSS percentage quirk)
v0.6.4
2026-03-29 14:24:26 +02:00
nevaforget 11e7cc438b fix: prevent edge darkening on GPU-blurred wallpaper (v0.6.3)
GskBlurNode samples pixels outside texture bounds as transparent,
causing visible darkening at wallpaper edges. Fix renders the texture
with 3x-sigma padding before blur, then clips back to original size.
Symmetric fix with moonset v0.7.1.
2026-03-28 23:28:40 +01:00
nevaforget c286a9e77e refactor: remove embedded wallpaper from binary (v0.6.2)
Wallpaper is installed by moonarch to /usr/share/moonarch/wallpaper.jpg.
Embedding a 374K JPEG in the binary was redundant. Without a wallpaper
file, GTK background color (Catppuccin Mocha base) shows through.
2026-03-28 23:23:02 +01:00
nevaforget 18df41a345 feat: add MOONLOCK_DEBUG env var for debug-level logging (v0.6.1)
Align with moongreet/moonset logging pattern — set MOONLOCK_DEBUG to
enable debug-level journal output for troubleshooting.
v0.6.1
2026-03-28 22:57:02 +01:00
nevaforget ce6739d174 fix: audit fixes — D-Bus sender validation, fp lifecycle, multi-monitor caching (v0.6.0)
Close the only exploitable auth bypass: validate VerifyStatus signal sender
against fprintd's unique bus name. Fix fingerprint D-Bus lifecycle so devices
are properly released on verify-match and async restarts check the running
flag between awaits.

Security: num_msg guard in PAM callback, symlink rejection for background_path,
peek icon disabled, TOML parse errors logged, panic hook before logging.

Performance: blur and avatar textures cached across monitors, release profile
with LTO/strip.
2026-03-28 22:47:09 +01:00
nevaforget 44f0e0cec0 fix: audit fixes — double-unlock guard, PAM OOM code, GPU blur, async fp stop (v0.5.1)
Security: prevent double unlock() when PAM and fingerprint succeed
simultaneously (ext-session-lock protocol error). Fix PAM callback
returning PAM_AUTH_ERR instead of PAM_BUF_ERR on calloc OOM.

Performance: replace CPU-side Gaussian blur (image crate) with GPU blur
via GskBlurNode + GskRenderer::render_texture(). Eliminates 500ms-2s
main-thread blocking on cold cache for 4K wallpapers. Remove image and
dirs dependencies (~15 transitive crates). Make fingerprint stop()
fire-and-forget async to avoid 6s UI block after successful auth.
2026-03-28 22:06:38 +01:00
nevaforget 89a6a5c371 perf: cache blurred wallpaper to disk to avoid re-blur on startup
First launch with blur blurs and saves to ~/.cache/moonlock/.
Subsequent starts load the cached PNG directly. Cache invalidates
when wallpaper path, size, mtime, or sigma changes.
Adds dirs crate for cache directory resolution.
2026-03-28 21:23:43 +01:00
nevaforget 15ac79260d feat: add optional background blur, align to shared texture pattern
Gaussian blur applied at texture load time when `background_blur` is
set in moonlock.toml. Refactored wallpaper loading from per-window
Picture::for_filename() to shared gdk::Texture pattern (matching
moonset/moongreet), avoiding redundant JPEG decoding on multi-monitor.
v0.5.0
2026-03-28 14:53:27 +01:00
nevaforget d59a1de076 fix: audit fixes — async restart_verify, locale caching, panic safety (v0.5.0)
- restart_verify() now async via spawn_future_local (was blocking main thread)
- stop() uses 3s timeout instead of unbounded
- load_strings() caches locale detection in OnceLock (was reading /etc/locale.conf on every call)
- child_get() replaced with child_value().get() for graceful D-Bus type mismatch handling
- Eliminate redundant password clone in auth path (direct move into spawn_blocking)
- Add on_exhausted callback: hides fp_label after MAX_FP_ATTEMPTS
- Set running=false before on_success callback (prevent double-unlock)
- Add 4 unit tests for on_verify_status state machine
- Document GLib-GString/CString zeroize limitation in CLAUDE.md
2026-03-28 10:16:06 +01:00
nevaforget bb48d38efb perf: async fprintd initialization for instant window display
Move all fprintd D-Bus calls (init, availability check, claim, verify)
from synchronous to async using gio futures. Windows now appear
immediately without waiting for D-Bus — fingerprint label fades in
once fprintd is ready. Single shared FingerprintListener across all
monitors instead of one per monitor.
2026-03-28 09:57:56 +01:00
nevaforget 3e3b1e531a feat: switch logging to systemd journal (v0.4.2)
Replace env_logger + /var/cache/moonlock file logging with
systemd-journal-logger. Logs are now reliably accessible via
journalctl --user -u moonlock, fixing invisible errors in the
systemd user service context.

- Cargo.toml: env_logger → systemd-journal-logger 2.2
- main.rs: setup_logging() uses JournalLog
- PKGBUILD: add systemd-libs dependency
- power.rs: include unstaged systemctl fixes (ABOUTME, --no-ask-password, output())
2026-03-28 01:11:48 +01:00
nevaforget 136414a711 fix: use systemctl instead of loginctl for reboot/poweroff
loginctl has no reboot/poweroff subcommands — these are systemctl
commands. The error was silently swallowed because stderr wasn't
captured and logs went to a non-existent directory.
2026-03-28 00:53:14 +01:00
nevaforget d2710ad0c5 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.
v0.4.1
2026-03-28 00:06:27 +01:00
nevaforget e499428fde fix: PKGBUILD depends on gtk-session-lock (not gtk4-session-lock) 2026-03-27 23:28:11 +01:00
nevaforget f5028336ba Merge rust-rewrite: moonlock v0.4.0 Rust rewrite 2026-03-27 23:18:03 +01:00
nevaforget 9aa516f873 Fix Rust 2024 unsafe block warnings in PAM callback
Wrap raw pointer operations in explicit unsafe blocks inside
the unsafe extern "C" conv callback, as required by Rust 2024
edition. Remove unused mut binding.
2026-03-27 23:13:23 +01:00
nevaforget 09382b3bd2 Rewrite moonlock from Python to Rust (v0.4.0)
Complete rewrite of the Wayland lockscreen from Python/PyGObject to
Rust/gtk4-rs for memory safety in security-critical PAM code and
consistency with the moonset/moongreet Rust ecosystem.

Modules: main, lockscreen, auth (PAM FFI), fingerprint (fprintd D-Bus),
config, i18n, users, power. 37 unit tests.

Security: PAM conversation callback with Zeroizing password, panic hook
that never unlocks, root check, ext-session-lock-v1 compositor policy,
absolute loginctl path, avatar symlink rejection.
2026-03-27 23:09:54 +01:00
nevaforget a81ed64dcc Revert "feat: fade-in animation for panel and wallpaper windows"
This reverts commit cf31cb057e.
2026-03-27 15:12:26 +01:00
nevaforget cf31cb057e feat: fade-in animation for panel and wallpaper windows
CSS opacity transition (350ms ease-in) triggered via adding
a 'visible' class after the window is mapped.
2026-03-27 14:45:10 +01:00
nevaforget 27301bd8b4 Move power confirmation below fingerprint label with own text
Confirmation prompt is now a self-contained box (label + buttons)
appended at the bottom of the login box instead of reusing the
error label above the fingerprint text.
2026-03-26 22:18:58 +01:00
nevaforget acfd712919 Security hardening based on triple audit (security, quality, performance)
- Remove SIGUSR1 unlock handler (unauthenticated unlock vector)
- Sanitize LD_PRELOAD (discard inherited environment)
- Refuse to run as root
- Validate D-Bus signal sender against fprintd proxy owner
- Pass bytearray (not str) to PAM conversation callback for wipeable password
- Resolve libc before returning CFUNCTYPE callback
- Bundle fingerprint success idle_add into single atomic callback
- Add running/device_proxy guards to VerifyStart retries with error handling
- Add fingerprint attempt counter (max 10 before disabling)
- Add power button confirmation dialog (inline yes/cancel)
- Move fingerprint D-Bus init before session lock to avoid mainloop blocking
- Resolve wallpaper path once, share across all monitor windows
- Document faillock as UI-only (pam_faillock handles real brute-force protection)
- Fix type hints (Callable), remove dead import (c_char), fix import order
v0.3.0
2026-03-26 22:11:00 +01:00
nevaforget 977f7c6b38 Replace crash guard with SIGUSR1 unlock and crash logging
Remove sys.excepthook that unlocked on crash — this violated
ext-session-lock-v1 security model where the compositor must keep
the screen locked if the client dies (per protocol spec and hyprlock
reference). Now: crashes are logged but session stays locked.
SIGUSR1 handler added for external recovery (e.g. wrapper script).
v0.2.2
2026-03-26 21:11:42 +01:00
nevaforget 4f4a53470c Add crash guard, logging, and defensive error handling to prevent lockout
Global sys.excepthook unlocks the session on unhandled exceptions.
Structured logging to stderr and optional file at /var/cache/moonlock/.
Window creation, CSS loading, and fingerprint start wrapped in
try/except with automatic session unlock when all windows fail.
v0.2.1
2026-03-26 17:56:45 +01:00
nevaforget ccd55eea2f Bump version to 0.2.0 v0.2.0 2026-03-26 16:31:20 +01:00
nevaforget 2b4eb731b1 Make login box background transparent v0.1.1 2026-03-26 16:31:01 +01:00
nevaforget a62489aa73 Clean dist/ before wheel build to prevent stale artifacts
Version bumps leave old wheels in dist/, causing the glob to
expand to multiple files and python-installer to fail.
2026-03-26 15:49:37 +01:00
nevaforget 62ab71b3ae Bump version to 0.1.1 2026-03-26 15:44:37 +01:00
nevaforget ab4c50fff6 Fix fprintd AlreadyInUse error by respecting done flag
VerifyStart was called unconditionally on retry/no-match statuses,
ignoring the done parameter from fprintd's VerifyStatus signal.
When done=False the verify session is still active, causing
AlreadyInUse errors. Now only restarts verification when done=True.
2026-03-26 15:43:27 +01:00
nevaforget f6696bb65f Simplify pkgver() to require tags v0.1.0 2026-03-26 14:02:06 +01:00
nevaforget 577a404e14 Fix pkgver() stdout leak in PKGBUILD 2026-03-26 14:00:16 +01:00
nevaforget 7c49269539 Show login UI on all monitors for compositor-agnostic focus
Wayland does not expose absolute pointer coordinates to clients,
so we cannot reliably detect which monitor has focus. Instead,
show the full lockscreen UI on every monitor — the compositor
assigns keyboard focus to the surface under the pointer via
ext-session-lock-v1.

Share a single FingerprintListener across all windows to avoid
multiple device claims. Also add makepkg build artifacts to
gitignore.
2026-03-26 13:58:45 +01:00
nevaforget b060c02010 Add PKGBUILD and remove stale moongreet icon
Add Arch Linux PKGBUILD for makepkg installation. Installs the
Python package, PAM config, and example config file. Fix pkgver()
to handle repos without tags (sed always exits 0 on empty input).

Remove leftover moongreet icon that was accidentally included in
the data directory.
2026-03-26 13:48:07 +01:00
nevaforget ea1f1bb5de Harden auth, user detection, faillock, and LD_PRELOAD handling
- Replace os.getlogin() with pwd.getpwuid(os.getuid()) to prevent
  crashes in systemd/display-manager sessions without a controlling tty
- Cache libpam and libc at module level instead of calling find_library()
  on every auth attempt (spawned ldconfig subprocess each time)
- Disable password entry permanently after FAILLOCK_MAX_ATTEMPTS instead
  of just showing a warning while allowing unlimited retries
- Fix LD_PRELOAD logic to append gtk4-layer-shell instead of skipping
  when LD_PRELOAD is already set (caused silent session lock fallback)
- Ensure password entry keeps focus after errors and escape
2026-03-26 13:35:26 +01:00
nevaforget 52c855bfbf Add wallpaper and default avatar support
Wallpaper with fallback hierarchy: config path > Moonarch system
default (/usr/share/moonarch/wallpaper.jpg) > package fallback.
Applied to both primary and secondary monitors.

Default avatar from Moongreet ecosystem with theme-colored SVG
rendering via PixbufLoader and proper clipping frame (Gtk.Box
with overflow hidden), matching the Moongreet avatar pattern.
2026-03-26 13:01:25 +01:00
nevaforget c9279b85a5 Fix PAM conversation segfault causing unrecoverable red lockscreen
ctypes auto-converts c_char_p return values to Python bytes, losing
the original malloc'd pointer from strdup(). When PAM called free()
on the response, it hit a ctypes-internal buffer instead — segfault.
Use c_void_p for PamResponse.resp and strdup restype to preserve raw
pointers. Also use calloc/strdup for proper malloc'd memory that PAM
can safely free().

Add try/except in auth thread so UI stays interactive on PAM errors.
2026-03-26 12:43:53 +01:00