Skip to content

Feature: replace static auth with PAM conversation callback-driven authentication #93

@kavau

Description

@kavau

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:

  1. When the user selects an account, the greeter sends start:<username>\n to the daemon immediately.
  2. 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.
  3. PAM informational and error messages are forwarded to the greeter as info: / error: lines and displayed as banners.
  4. 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.
  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:daemonDaemon core: event loop, signal handling, main.c wiringfeatureNew functionality - non-trivial but straightforward

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions