Skip to content

[feat] Add opt-in Touch ID authentication for guest sudo - #143

Open
Fail-Safe wants to merge 5 commits into
omacom:mainfrom
Fail-Safe:experiment/touch-id-auth
Open

[feat] Add opt-in Touch ID authentication for guest sudo#143
Fail-Safe wants to merge 5 commits into
omacom:mainfrom
Fail-Safe:experiment/touch-id-auth

Conversation

@Fail-Safe

@Fail-Safe Fail-Safe commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add an opt-in Touch ID authentication bridge for guest sudo
  • add a stateful Setup → Security → Touch ID for sudo control with enable, test, re-pair, and disable actions
  • keep the integration dormant until the user authenticates with the guest sudo password and approves enrollment with Touch ID
  • preserve normal guest-password authentication as fallback and display the reason before requesting the password
  • enable guest time synchronization at boot so clock drift does not invalidate otherwise valid signed approvals

This implements the sudo-scoped portion of #133. It does not attempt to expose Apple Passwords/Keychain data or replace guest login and screen-unlock authentication.

Security model

  • the guest authentication device and enrollment state are root-only
  • each approval uses a fresh request ID and 256-bit challenge
  • the Secure Enclave P-256 signature binds the operation, guest identity, PAM user, requesting user, service, TTY, key identity, and 15-second validity window
  • the guest pins the enrolled public key and verifies every signature with OpenSSL
  • macOS prompts with deviceOwnerAuthenticationWithBiometrics, biometric-set binding, no password fallback, and zero reuse duration
  • the host prompts only while the matching QEMU process is alive and focused
  • enabling writes the PAM rule only after enrollment succeeds; disabling removes the PAM rule before deleting enrollment state
  • existing recognized PAM rules migrate to enable user-visible fallback explanations without re-enrollment; approval validity checks remain unchanged

Validation

  • DEVELOPER_DIR=/Applications/Xcode-beta.app/Contents/Developer make test passed, including guest unit and contract tests, 210 Swift tests in 47 suites, macOS compatibility/runtime relocation, and QEMU forwarding, power, SSH, and persistent-storage tests
  • the release host helper builds successfully; new regression coverage checks compact menu insertion, command failure propagation, refusal of password fallback, host prompt cancellation, late callbacks, and late-response recovery
  • regression coverage verifies that a real signed approval is rejected with a clock explanation when guest time is outside the allowed window, while successful authentication stays quiet
  • checked message delivery through the running guest's actual PAM library: the explanation reaches the conversation and failed authentication remains rejected
  • live guest validation: time synchronization corrected approximately 16 seconds of drift; Mac and guest clocks then matched, and the user confirmed Touch ID sudo authentication without a guest password
  • verified enable, disable, re-enable, and persistence across shutdown/power-on during the original implementation
  • the original security review covered commit c523029; it is not presented as a security review of the subsequent time-sync and diagnostic changes
  • clean factory-image rebuild attempted: guest package resolution stopped with could not satisfy dependencies before reaching the changed configuration scripts. For live testing, cached guest artifacts were refreshed and the app rebuilt; signature and macOS compatibility checks passed. This does not establish a successful clean factory build.

Deliberate manual failure-path testing

Tests were performed interactively with real Mac Touch ID and the persistent guest. Each authentication test cleared sudo's cached credentials.

  • Normal approval: with guest time synchronized, fingerprint approval completed sudo true with exit status 0 and no guest password.
  • Explicit cancellation: canceling Touch ID displayed the fallback explanation; entering the correct guest password then completed ordinary sudo with exit status 0.
  • Focus loss: switching to another Mac application while the prompt was open, then successfully scanning a finger, resulted in rejected approval and a guest-password prompt. The dialog remained visible and repeatedly returned to the foreground; automatic cancellation on focus loss is not claimed.
  • Timeout on dc06bcf: two unanswered attempts both closed the Touch ID dialog and reported failed authentication without accepting password fallback. The first was timed at exactly 55 seconds; the second was not timed. No numeric exit status was captured for these timeout attempts.
  • Recovery after timeout on dc06bcf: two subsequent interactive test runs completed without a guest password, each reporting exit status 0, with no mismatched-request errors.

Normal approval, explicit cancellation, and focus-loss checks were performed before the final timeout/test-command update. Timeout and recovery were repeated after installing the dc06bcf Mac helper and guest scripts in the enrolled VM. Earlier runs against the old installation reproduced the stale-response failure and are not counted as validation of the fix.

Remaining UX limitation: host timeout still appears as “Touch ID was not approved”; the shared broker message mentions password fallback even though the dedicated test deliberately refuses it.

Operational boundaries

  • supported scope is guest sudo only
  • moving or resetting the VM, changing Macs or macOS accounts, or changing the enrolled biometric set may require re-pairing
  • the Try Omarchy window must be focused when Touch ID is requested
  • new factory images enable systemd-timesyncd; existing guests with drift can enable it with sudo systemctl enable --now systemd-timesyncd.service and verify synchronization with timedatectl
  • unanswered Mac prompts are canceled after 55 seconds; the guest discards late responses without extending its 65-second deadline
  • the test and enable/re-pair checks refuse password fallback and propagate failure; passwordless sudo policies are explicitly distinguished from evidence of Touch ID use

@Fail-Safe
Fail-Safe marked this pull request as ready for review September 6, 2026 01:57
@Fail-Safe
Fail-Safe marked this pull request as draft September 6, 2026 01:58
@Fail-Safe
Fail-Safe marked this pull request as ready for review September 6, 2026 17:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant