Persistent sudo Touch ID Authentication on macOS
It’s been five years since the first launch of a Touch ID capable Macbook. In case you’re out of the loop, Touch ID is also available as a built-in PAM module. Unfortunately it’s not enabled for sudo by default, so people need to add a
pam_tid.so entry in the
Sounds perfectly no problem, unless you hit a system upgrade. Since modern macOS performs image-based updates, the system volume is overwritten every time it’s updated. Including
/etc/pam.d/sudo. As a result, I had to manually manipulate the file for every update.
I was officially tired of that, and looked into if there’s any existing solutions. Someone at Hacker News suggested to add a shell alias to automatically add the entry, or more straightforward, wrap the sudo function, check every time if
pam_tid.so is enabled, and add the entry to
/etc/pam.d/sudo if not. Good enough, but I think we don’t have to mess with the shell configurations just for this.
I created persistent_pam_tid. It’s a macOS LaunchDaemon that calls a script to check
/etc/pam.d/sudo at every system startup, and adds
pam_tid.so if it’s not present in the file:
#!/bin/bash if ! grep 'pam_tid.so' /etc/pam.d/sudo --silent; then sed -i -e '1s;^;auth sufficient pam_tid.so\n;' /etc/pam.d/sudo fi
While studying launchd.plist, this documentation has made exceptional use, and it was simple enough to construct this launchd configuration:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>me.birkhoff.pam_tid</string> <key>KeepAlive</key> <false/> <key>LaunchOnlyOnce</key> <true/> <key>RunAtLoad</key> <true/> <key>ProgramArguments</key> <array> <string>/usr/local/bin/pam_tid_installer</string> </array> <key>StandardOutPath</key> <string>/tmp/pam_tid_installer.stdout.log</string> <key>StandardErrorPath</key> <string>/tmp/pam_tid_installer.stderr.log</string> </dict> </plist>
To install a launch daemon, move the definition file to
/Library/LaunchDaemons/ and run:
sudo launchctl load -w <path>
sudo is required for launch daemons, since they are either run as root or any other arbitrary user specified in the definitions file. The flag
-w enables the service if it’s disabled.
Now the daemon is loaded, yet since
RunAtLoad is set to
pam_tid_installer is called (as root).
Every time the system boots, launchd scans the launch daemons directories and loads those daemons which are not disabled. So our daemon will be run every time system starts.