Backport of the FIDO2 authfile fix (PR #7904 by @mdisec, merged to quattro as
23dab9ec) onto the v4-0-1 release branch.
pamu2fcfg wrote to /tmp/fido2 and the registration was then moved into place
with sudo mv. Any other local user can pre-create /tmp/fido2, and rename(2) does
not dereference the final component, so the privileged move installed the
attacker's symlink itself as pam_u2f's global authfile -- a file consulted by
sufficient lines in /etc/pam.d/sudo and /etc/pam.d/polkit-1.
The same move also carried the staged file's ownership into /etc, so on every
install to date /etc/fido2/fido2 is owned by the invoking user at mode 0644.
That needs no attacker, no race and no second account: anything running as that
uid can append its own credential and satisfy the machine's sudo prompt without
knowing the password.
The setup now creates a unique staging file as root beside the final authfile
and pipes pamu2fcfg into it, so root never reopens a caller-owned pathname,
rejects failed or empty enrollment output, publishes with an atomic mv -Tf,
cleans the exact staging file after every failure, refuses non-regular authfile
states, and installs root:root 0644. A migration repairs machines set up by
earlier versions by replacing the inode rather than chowning in place: a process
that already holds a writable descriptor on the legacy user-owned mapping keeps
it, so the repair has to leave that inode behind where PAM no longer reads it.
Clean cherry-pick: all six files are byte-identical to quattro, so merging
v4-0-1 into quattro resolves without a conflict. The migration's timestamp
(1787494718) is older than others already on this branch, which is harmless:
omarchy-migrate marks each migration by filename rather than tracking a
watermark, so this one runs on every machine that has not run this exact file.
test/shell passes: 195 files, including the three this adds -- the setup's
staging and failure paths, the migration's repair and unrepairable states, and
the removal's symlink handling. test/cli passes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DEMYa9UWtroz93DhMTtcV
41 lines
1.1 KiB
Bash
Executable File
41 lines
1.1 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# omarchy:summary=Remove FIDO2 authentication from sudo and polkit
|
|
# omarchy:requires-sudo=true
|
|
|
|
set -e
|
|
|
|
|
|
remove_pam_config() {
|
|
# Remove from sudo
|
|
if grep -q pam_u2f.so /etc/pam.d/sudo; then
|
|
echo "Removing FIDO2 authentication from sudo..."
|
|
sudo sed -i '/pam_u2f\.so/d' /etc/pam.d/sudo
|
|
fi
|
|
|
|
# Remove from polkit
|
|
if [[ -f /etc/pam.d/polkit-1 ]] && grep -Fq 'pam_u2f.so' /etc/pam.d/polkit-1; then
|
|
echo "Removing FIDO2 authentication from polkit..."
|
|
sudo sed -i '/pam_u2f\.so/d' /etc/pam.d/polkit-1
|
|
fi
|
|
}
|
|
|
|
echo -e "\e[32mRemoving FIDO2 device from authentication.\n\e[0m"
|
|
|
|
remove_pam_config
|
|
|
|
authdir=/etc/fido2
|
|
|
|
# -d follows symlinks, so a dangling link at /etc/fido2 would survive this and
|
|
# a later setup would install the authfile through it. rm -rf on a symlink
|
|
# removes the link itself, never the directory it points at.
|
|
if [[ -e $authdir || -L $authdir ]]; then
|
|
echo "Removing FIDO2 configuration..."
|
|
sudo rm -rf "$authdir"
|
|
fi
|
|
|
|
echo "Removing FIDO2 packages..."
|
|
omarchy-pkg-drop libfido2 pam-u2f
|
|
|
|
echo -e "\e[32mFIDO2 authentication has been completely removed.\e[0m"
|