# Debug symbols are already stripped by Cargo's release profile (strip = true). # Generating the debuginfo RPM would add ~5 min and ~128 MB with no benefit. %global debug_package %{nil} Name: linux-hello Version: 0.1.0~alpha4 Release: 1%{?dist} Summary: Windows Hello equivalent for Linux — biometric PAM authentication License: GPL-3.0-only URL: https://github.com/giacomofurlan/linux-hello Source0: %{name}-%{version}.tar.gz BuildRequires: rust >= 1.97 BuildRequires: cargo >= 1.97 BuildRequires: cmake BuildRequires: ninja-build BuildRequires: clang BuildRequires: pkgconfig BuildRequires: pkgconfig(fontconfig) BuildRequires: pkgconfig(libudev) BuildRequires: pkgconfig(xkbcommon) BuildRequires: pkgconfig(wayland-client) BuildRequires: pkgconfig(x11) BuildRequires: pkgconfig(xext) BuildRequires: pkgconfig(Qt6Core) BuildRequires: pkgconfig(Qt6Qml) BuildRequires: pkgconfig(Qt6Quick) BuildRequires: pkgconfig(Qt6Svg) BuildRequires: pkgconfig(tss2-esys) BuildRequires: pkgconfig(opencv4) BuildRequires: pkgconfig(pam) BuildRequires: pkgconfig(dbus-1) BuildRequires: pkgconfig(sqlite3) BuildRequires: checkpolicy BuildRequires: policycoreutils Requires: qt6-qtbase Requires: qt6-qtdeclarative Requires: tpm2-tss Requires: pam Requires: dbus Requires(pre): shadow-utils # Declare that this package creates the linux-hello user/group (done in %pre). # RPM's scriptlet auto-detection does not reliably pick up the getent||useradd # pattern, so we declare the virtual provides explicitly. Provides: user(linux-hello) Provides: group(linux-hello) Requires(post): systemd Requires(post): curl Requires(preun): systemd Requires(postun): systemd Recommends: tpm2-abrmd Recommends: fprintd Suggests: pamtester %description linux-hello provides PAM-integrated biometric and hardware-token authentication for Linux, analogous to Windows Hello. It supports face recognition (IR and RGB), fingerprint (via fprintd), FIDO2/WebAuthn hardware keys, PIN, and TOTP. The trust policy is TPM-sealed and configurable per PAM service. %prep %autosetup %build cargo build --release --workspace --exclude linux-hello-pam cargo build --release -p linux-hello-pam %install install -Dm755 target/release/linux-hello-daemon %{buildroot}%{_bindir}/linux-hello-daemon install -Dm755 target/release/linux-hello-notify %{buildroot}%{_bindir}/linux-hello-notify install -Dm755 target/release/linux-hello-enroll %{buildroot}%{_bindir}/linux-hello-enroll install -Dm755 target/release/linux-hello-admin %{buildroot}%{_bindir}/linux-hello-admin install -Dm755 target/release/linux-hello-overlay %{buildroot}%{_bindir}/linux-hello-overlay install -Dm755 target/release/linux-hello-greetd %{buildroot}%{_bindir}/linux-hello-greetd install -Dm755 target/release/linux-hello-sddm-helper %{buildroot}%{_libdir}/linux-hello/linux-hello-sddm-helper install -Dm644 target/release/libpam_linux_hello.so %{buildroot}%{_libdir}/security/pam_linux_hello.so install -Dm644 config/pam/linux-hello \ %{buildroot}%{_sysconfdir}/pam.d/linux-hello install -Dm644 config/systemd/linux-hello.service \ %{buildroot}%{_unitdir}/linux-hello.service install -Dm644 config/systemd/90-linux-hello.preset \ %{buildroot}%{_presetdir}/90-linux-hello.preset install -Dm644 config/systemd/linux-hello-sddm-helper.service \ %{buildroot}%{_unitdir}/linux-hello-sddm-helper.service install -Dm644 config/systemd/linux-hello-reseal.service \ %{buildroot}%{_unitdir}/linux-hello-reseal.service install -Dm644 config/systemd/linux-hello-overlay.service \ %{buildroot}%{_userunitdir}/linux-hello-overlay.service install -Dm644 config/systemd/linux-hello-notify.service \ %{buildroot}%{_userunitdir}/linux-hello-notify.service install -Dm644 config/dbus/linux-hello.conf \ %{buildroot}%{_datadir}/dbus-1/system.d/linux-hello.conf install -Dm644 polkit/name.giacomofurlan.linux_hello.policy \ %{buildroot}%{_datadir}/polkit-1/actions/name.giacomofurlan.linux_hello.policy install -Dm755 config/kernel-install/90-linux-hello-reseal.install \ %{buildroot}%{_prefix}/lib/kernel/install.d/90-linux-hello-reseal.install install -Dm644 config/applications/linux-hello-enroll.desktop \ %{buildroot}%{_datadir}/applications/linux-hello-enroll.desktop install -Dm644 config/applications/linux-hello-admin.desktop \ %{buildroot}%{_datadir}/applications/linux-hello-admin.desktop install -Dm644 assets/icons/linux-hello.svg \ %{buildroot}%{_datadir}/icons/hicolor/scalable/apps/linux-hello.svg install -Dm644 assets/icons/linux-hello-256.png \ %{buildroot}%{_datadir}/icons/hicolor/256x256/apps/linux-hello.png install -Dm644 assets/icons/linux-hello-48.png \ %{buildroot}%{_datadir}/icons/hicolor/48x48/apps/linux-hello.png install -dm755 %{buildroot}%{_sysconfdir}/linux-hello install -dm755 %{buildroot}%{_sharedstatedir}/linux-hello install -Dm755 packaging/download-models.sh %{buildroot}%{_datadir}/linux-hello/download-models.sh install -Dm644 packaging/models/checksums.sha256 %{buildroot}%{_datadir}/linux-hello/models/checksums.sha256 install -dm755 %{buildroot}%{_datadir}/linux-hello/models install -Dm644 config/udev/70-linux-hello.rules \ %{buildroot}%{_udevrulesdir}/70-linux-hello.rules # SELinux policy module — subshell keeps the cd from affecting subsequent paths. (cd config/selinux && \ checkmodule -M -m -o linux_hello.mod linux_hello.te && \ semodule_package -o linux_hello.pp -m linux_hello.mod -f linux_hello.fc) install -Dm644 config/selinux/linux_hello.pp \ %{buildroot}%{_datadir}/linux-hello/selinux/linux_hello.pp install -Dm644 config/selinux/linux_hello.te \ %{buildroot}%{_datadir}/linux-hello/selinux/linux_hello.te install -Dm644 config/selinux/linux_hello.fc \ %{buildroot}%{_datadir}/linux-hello/selinux/linux_hello.fc install -dm755 %{buildroot}%{_datadir}/sddm/themes cp -r config/sddm/theme/linux-hello \ %{buildroot}%{_datadir}/sddm/themes/linux-hello cp -r config/sddm/theme/linux-hello-xmb \ %{buildroot}%{_datadir}/sddm/themes/linux-hello-xmb install -dm755 %{buildroot}%{_datadir}/plasma/look-and-feel cp -r config/kscreenlocker/theme/linux-hello \ %{buildroot}%{_datadir}/plasma/look-and-feel/linux-hello cp -r config/kscreenlocker/theme/linux-hello-xmb \ %{buildroot}%{_datadir}/plasma/look-and-feel/linux-hello-xmb %pre # Stop the daemon before upgrade so the binary can be replaced. if [ $1 -ge 2 ] && [ -d /run/systemd/system ]; then systemctl is-active --quiet linux-hello.service && \ systemctl stop linux-hello.service || : fi getent group linux-hello >/dev/null || groupadd --system linux-hello getent passwd linux-hello >/dev/null || \ useradd --system --gid linux-hello \ --home-dir %{_sharedstatedir}/linux-hello \ --shell /sbin/nologin \ --comment "Linux Hello daemon" \ linux-hello # Add to tss group for TPM access and video group for face recognition. getent group tss >/dev/null && usermod -aG tss linux-hello || : getent group video >/dev/null && usermod -aG video linux-hello || : %post %systemd_post linux-hello.service linux-hello-sddm-helper.service linux-hello-reseal.service install -dm700 -o linux-hello -g linux-hello %{_sharedstatedir}/linux-hello # On upgrade from v1: remove the old SCRFD-500M model (replaced by det_10g.onnx). if [ $1 -ge 2 ]; then rm -f %{_datadir}/linux-hello/models/scrfd_500m.onnx fi /usr/share/linux-hello/download-models.sh || \ echo "WARNING: model download failed; run sudo /usr/share/linux-hello/download-models.sh manually" # Install SELinux policy so SDDM's PAM helper can connect to the PAM socket. if [ -x /usr/sbin/semodule ]; then semodule -i %{_datadir}/linux-hello/selinux/linux_hello.pp 2>/dev/null || : restorecon -Rv /run/linux-hello 2>/dev/null || : fi %preun %systemd_preun linux-hello.service linux-hello-sddm-helper.service linux-hello-reseal.service if [ $1 -eq 0 ]; then rm -f %{_datadir}/linux-hello/models/det_10g.onnx \ %{_datadir}/linux-hello/models/scrfd_500m.onnx \ %{_datadir}/linux-hello/models/arcface_r50.onnx \ %{_datadir}/linux-hello/models/minifasnet_v2.onnx fi %postun %systemd_postun_with_restart linux-hello.service linux-hello-sddm-helper.service linux-hello-reseal.service # Remove SELinux policy on uninstall. if [ $1 -eq 0 ] && [ -x /usr/sbin/semodule ]; then semodule -r linux_hello 2>/dev/null || : fi %files %license LICENSE %doc README.md %{_bindir}/linux-hello-daemon %{_bindir}/linux-hello-notify %{_bindir}/linux-hello-enroll %{_bindir}/linux-hello-admin %{_bindir}/linux-hello-overlay %{_bindir}/linux-hello-greetd %{_libdir}/linux-hello/linux-hello-sddm-helper %{_libdir}/security/pam_linux_hello.so %config(noreplace) %{_sysconfdir}/pam.d/linux-hello %{_unitdir}/linux-hello.service %{_presetdir}/90-linux-hello.preset %{_unitdir}/linux-hello-sddm-helper.service %{_unitdir}/linux-hello-reseal.service %{_userunitdir}/linux-hello-overlay.service %{_userunitdir}/linux-hello-notify.service %{_datadir}/dbus-1/system.d/linux-hello.conf %{_datadir}/polkit-1/actions/name.giacomofurlan.linux_hello.policy %{_prefix}/lib/kernel/install.d/90-linux-hello-reseal.install %{_datadir}/applications/linux-hello-enroll.desktop %{_datadir}/applications/linux-hello-admin.desktop %{_datadir}/icons/hicolor/scalable/apps/linux-hello.svg %{_datadir}/icons/hicolor/256x256/apps/linux-hello.png %{_datadir}/icons/hicolor/48x48/apps/linux-hello.png %dir %{_sysconfdir}/linux-hello %attr(700,linux-hello,linux-hello) %dir %{_sharedstatedir}/linux-hello %{_datadir}/sddm/themes/linux-hello %{_datadir}/sddm/themes/linux-hello-xmb %{_datadir}/plasma/look-and-feel/linux-hello %{_datadir}/plasma/look-and-feel/linux-hello-xmb %{_datadir}/linux-hello/download-models.sh %dir %{_datadir}/linux-hello/models %{_datadir}/linux-hello/models/checksums.sha256 %dir %{_datadir}/linux-hello/selinux %{_datadir}/linux-hello/selinux/linux_hello.pp %{_datadir}/linux-hello/selinux/linux_hello.te %{_datadir}/linux-hello/selinux/linux_hello.fc %{_udevrulesdir}/70-linux-hello.rules %ghost %{_datadir}/linux-hello/models/det_10g.onnx %ghost %{_datadir}/linux-hello/models/arcface_r50.onnx %ghost %{_datadir}/linux-hello/models/minifasnet_v2.onnx %changelog * Sat Oct 10 2026 Giacomo "Mr. Wolf" Furlan - 0.1.0~alpha4-1 - Overlay dismiss button ("✕", top right): closes the overlay early and acts like Cancel on a pending consent request. - Overlay hint "Enter your PIN / authenticator code / recovery token in the prompt" when biometrics do not match and a typed credential is requested, instead of a misleading "Authentication failed — use your password". - New D-Bus signal `AuthCancelled(session_id)`, emitted when that credential prompt is cancelled. The daemon detects it through a *watch* connection the PAM module keeps open on the PAM socket while the prompt is shown, because polkit kills the PAM helper when its dialog is dismissed. - TPM tier status and migration in the daemon and D-Bus API, and in the admin GUI and TUI. - Admin Services tab (GUI and TUI) to manage the base and optional systemd services. - COPR publish pipeline for stable and testing channels; RPM changelog generated from this file. - Quick start guide with screenshots, linked from the README. - The overlay is no longer shown for callers that already give feedback themselves (terminal, SSH, display-manager and lock-screen themes). It stays for polkit, `swaylock` and unknown services. The PAM module reports this with the new `has_own_feedback` flag on every request. - The consent gate (Allow / Cancel) is raised only when the user has an enrolled and available passive factor (face IR / RGB). Fingerprint, FIDO2 touch and typed credentials need no gate, since the gesture is the consent. Mixed setups (e.g. fingerprint + face) keep it. - D-Bus: `AuthStarted` has a fourth argument `has_own_feedback: b`; denied `AuthResult`s that request a typed credential carry `factor_used = "needs:"`. The PAM socket protocol gains optional fields (`has_own_feedback`, `watch_session`, `session_id`); older modules and daemons keep working. - Terminal PIN prompt is now a plain `PIN: ` confirmed with Enter, without auto-submit. Graphical lockers keep `PIN (N digits)` for their auto-submit field. - Admin lock screen reapply re-copies the theme when the source changed, and `make install` runs it. - kscreenlocker themes use a neutral auth status text and parse the PIN prompt independently of the locale. - Secrets integration targets GNOME Keyring only; KWallet references removed. - RPM: debuginfo package dropped, `CARGO_PROFILE_RELEASE_CODEGEN_UNITS` override removed to speed up packaging. - The overlay appeared after logins from the lock screen or SDDM and during `sudo` / `login`, where the information is already on screen. - A stale "ready" timer could hide a newer scan result or a consent prompt; resets now apply only if nothing else was shown meanwhile. - Admin could not enable `polkit-1` (or other integrations) on distributions that ship PAM defaults in `/usr/lib/pam.d` (e.g. Fedora); it now starts from the vendor file, and disabling removes an `/etc/pam.d` copy that equals it. - PAM detects enrollment when called as an unprivileged user and skips the pre-prompt when no biometric factor is enrolled. - `PAM_SECDIR` detection uses `dpkg-architecture` only on Debian-based systems. - `linux-hello-notify.service` `ExecStart` path. - RPM: missing `BuildRequires` (fontconfig, udev, xkbcommon, wayland, x11) for COPR builds. - Clippy 1.98 lints (`as_chunks`, `unused_async_trait_impl`). * Mon Jul 27 2026 Giacomo Furlan - 0.1.0-1 - Initial RPM packaging.