Problem
atrium's current authentication flow is static: the greeter collects a username and password upfront and sends them to the daemon as a single blob. The daemon's PAM conversation function responds to every prompt with the pre-collected password.
This breaks for any authentication scheme beyond a single secret:
- Multi-factor authentication (TOTP, FIDO2, hardware tokens): PAM issues a second (or third) prompt that the static conversation function cannot satisfy.
- Challenge-response modules: the challenge arrives as a
PAM_TEXT_INFO message (currently discarded by the daemon) before the response prompt is issued.
PAM_PROMPT_ECHO_ON prompts: e.g. pam_duo's "Passcode or option" prompt. The current conversation function returns an empty string for these.
This is also a blocker for greetd greeter compatibility: greetd's IPC protocol is inherently dialog-driven, and a greetd-compatible translation layer needs a dialog-capable auth backend to sit behind it.
Proposed Change
Replace the single-shot credential bundle with a multi-turn dialog protocol over the existing pipe pair.
New flow:
- When the user selects an account, the greeter sends
start:<username>\n to the daemon immediately.
- The daemon spawns a PAM auth thread for that seat. The PAM conversation function sends each prompt to the greeter (
prompt:off:<text>\n or prompt:on:<text>\n) and waits for the greeter's resp:<text>\n reply.
- PAM informational and error messages are forwarded to the greeter as
info: / error: lines and displayed as banners.
- When PAM completes, the thread signals the main event loop via an
eventfd. The main thread sends ok\n or fail:<reason>\n to the greeter as before.
- The greeter's Back button sends
cancel\n; the auth thread detects the broken pipe and aborts cleanly.
Affected components:
daemon/auth/auth.c: conversation function becomes I/O-driven; auth_begin() loses the password argument and gains pipe fds; a thread-based async entry point is added.
daemon/core/greeter.c, main.c: replace the single credentials read with the new protocol; add eventfd handling for auth completion.
greeter/ui-gtk4.c, main.c: replace the upfront password page with a dynamic prompt page driven by messages from the daemon.
tools/greeter-test.c: updated to speak the new protocol.
The passwordless path (ATRIUM_PASSWORDLESS_USERS) bypasses the dialog: the daemon sends ok\n immediately after the start: message with no prompts.
Problem
atrium's current authentication flow is static: the greeter collects a username and password upfront and sends them to the daemon as a single blob. The daemon's PAM conversation function responds to every prompt with the pre-collected password.
This breaks for any authentication scheme beyond a single secret:
PAM_TEXT_INFOmessage (currently discarded by the daemon) before the response prompt is issued.PAM_PROMPT_ECHO_ONprompts: e.g. pam_duo's "Passcode or option" prompt. The current conversation function returns an empty string for these.This is also a blocker for greetd greeter compatibility: greetd's IPC protocol is inherently dialog-driven, and a greetd-compatible translation layer needs a dialog-capable auth backend to sit behind it.
Proposed Change
Replace the single-shot credential bundle with a multi-turn dialog protocol over the existing pipe pair.
New flow:
start:<username>\nto the daemon immediately.prompt:off:<text>\norprompt:on:<text>\n) and waits for the greeter'sresp:<text>\nreply.info:/error:lines and displayed as banners.eventfd. The main thread sendsok\norfail:<reason>\nto the greeter as before.cancel\n; the auth thread detects the broken pipe and aborts cleanly.Affected components:
daemon/auth/auth.c: conversation function becomes I/O-driven;auth_begin()loses thepasswordargument and gains pipe fds; a thread-based async entry point is added.daemon/core/greeter.c,main.c: replace the single credentials read with the new protocol; add eventfd handling for auth completion.greeter/ui-gtk4.c,main.c: replace the upfront password page with a dynamic prompt page driven by messages from the daemon.tools/greeter-test.c: updated to speak the new protocol.The passwordless path (
ATRIUM_PASSWORDLESS_USERS) bypasses the dialog: the daemon sendsok\nimmediately after thestart:message with no prompts.