Yubikey for sudo and login(s)
PAM is amazingly flexible and playing around with it can render your system inoperable. So if you love the thrill of editing a file without testing you are going to love adding a yubikey as a login option to your system.
All jokes aside, having a root login terminal, and a backup of the files you are editing is enough to not lock you out of a system. On to the fun part!
We are going to modify 2 files under /etc/pam.d/
. u2f
and system-auth
.
The goal here is to completely skip typing our amazingly long and secure password and tap our yubikey whenever we want to login or perform administrative access using sudo or other access elevation programs.
If you accidentally break PAM and realise you cannot login after rebooting.
You will need to start up in “single-user-mode”, which can be achieved by adding init=/bin/bash
to your boot manager, such as grub. Or you can just use that trusty live iso you have laying around so you can mount your system and edit PAM back to its original system.
Required Reading
- https://wiki.gentoo.org/wiki/YubiKey
- https://support.yubico.com/hc/en-us/articles/360016649099-Ubuntu-Linux-Login-Guide-U2F
Optional Reading
Learn more about what we are actually doing by reading up on how PAM works
- https://wiki.gentoo.org/wiki/PAM
There is a wealth of knowledge in the above links and they cover how to correctly perform a setup and mapping of your yubikey so that you can login with/without a yubikey.
Once you have added your yubikeys to your ~/.config/Yubico/u2f_keys
you can see what a successful PAM setup looks like for touch login and touch sudo.
Touch Login & Touch Sudo
We create a single PAM config file with our settings that we can use include on any subsequent file changes.
Changing sufficient
to required
here would make everything require 2FA, instead of everything accepting just your yubikey (or just your password).
- /etc/pam.d/u2f
auth sufficient pam_u2f.so cue
We then add the first 3 auth lines to our system-auth
which allow us to login with u2f, and if it is successful, skip passed the next auth line, (which is the failure). We then modify pam_env.so
to also be sufficient
instead of required
as before.
- /etc/pam.d/system-auth
auth include u2f auth [success=1 default=ignore] pam_unix.so nullok try_first_pass auth [default=die] pam_faillock.so authfail auth sufficient pam_env.so auth requisite pam_faillock.so preauth ... snip ...
Note: I’ve only included the
auth
lines in all the files, as they were the only changes needed. Do note delete any of the otheraccount
,password
,session
lines etc.
Note 2: The last two lines may not appear in your config, if so leave them out!
Testing!
At this point if you never took a backup, I assume you left a root terminal open so if you broke your authentication by mistyping the above, or not realising pam_u2f.so
is not the library that came with your distribution you can quickly revert your changes…
The options to test to confirm everything works as you expect:
- sudo with yubikey in
- Result: Touch only ✓
- sudo without yubikey
- Result: Password only ✓
- login with yubikey in
- Result: Touch only ✓
- login without yubikey
- Result: Password only ✓
These 4 options can be tested by using the login
command, which opens up a new login terminal so you will be able to test the new login functionality, without having to actually logout of your working system.
Please touch your device
Congratulations! We now no longer have to type our password when logging in, or when we type sudo.
You may be wondering why if we never modified the sudo
file under /etc/pam.d
how does it still allows us to use our key as a sufficient authentication mechanism.
If you take a peek into the sudo file, the first line (should be) auth substack system-auth
. Sudo utilises system-auth for authentication.
If you don’t like that, and for example, only wanted to login with the yubikey you would revert your system-auth
file, and would modify your login-managers-password file accordingly.
For example, you would modify gdm-password
for gdm.
Thoughts…?
You read this far? I like you!
One of the interesting edge cases (for me) and the reason I wrote this post was I never changed the pam_env.so
line to sufficient
and I could not find any references about it either. If I left it as required
it resulted in password authentication failing, but yubikey auth being successful. These are the edge cases I like finding out about, and investigating.
I think PAM needs a better fail safe feature so you don’t have to worry about locking yourself out. It would probably be very difficult to implement as PAM has so many use cases. Maybe something as simple as a critical path flowchart in ascii (or png) that you can view would be better than nothing. Visualising each step of success and failure may highlight an insecurity. (IE: what is my pam_env file doing here. I’m sure it is from a previous change I made but for the life of me I’m not sure why :D)