Fingerprint as PAM second factor

Given that Framework has rather convenient and reliable enough fingerprint scanner, I’d like to give it a try. For security reasons I’d like to use fingerprint scanner as a second mandatory factor along with a password.

The thing is, most guides & howtos I found on the internets are trying to configure fingerprint as an alternative to a password, i.e. only one of them is required for a successful login.

In contrast, I need to have a setup where both are required for login.

Also, I’d like to tweak sudo authorization behavior so that after a successful authorization it would still ask for a fingerprint for subsequent invocations (instead of silently accepting the command).

So it should look like this:

  1. User login: fingerprint + password
  2. First sudo authorization: fingerprint + password
  3. Subsequent sudo authorization within an active session: fingerprint only
  4. Screen unlock within, say, 5 minutes after it was locked: fingerprint only
  5. Screen unlock after more than 5 minutes or after sleep: fingerprint + password

I tried looking at PAM configs but kinda failed to figure it out. Would really appreciate any help and/or clues.

P.S.: In the past years KDE has finally shown some activity towards proper fingerprint support in SDDM and in Plasma which hopefully would make it easier and more configurable.

4 Likes

So, requiring both is doable, for both sudo and login (assuming you’re using gdm, not sure how to do it with others). The others, not quite. I’m using Arch, so you may need to adjust for your distro.

For user login, assuming you’re using GDM, replace the contents of both /etc/pam.d/gdm-fingerprint and /etc/pam.d/gdm-password with this:

#%PAM-1.0

auth       requisite                   pam_fprintd.so
auth       include                     system-local-login
auth       optional                    pam_gnome_keyring.so

account    include                     system-local-login

password   include                     system-local-login
password   optional                    pam_gnome_keyring.so use_authtok

session    include                     system-local-login
session    optional                    pam_gnome_keyring.so auto_start

To be clear, this is the original contents of gdm-password with this line added as the first auth line:

auth       requisite                   pam_fprintd.so

With that change, GDM will ask for a fingerprint then let you enter a password.

Then, for sudo, you can make it require both by editing /etc/pam.d/sudo and replacing the sufficient on the auth line for pam_fprintd.so to required. My config looks like this:

#%PAM-1.0
auth        required    pam_fprintd.so
auth		include		system-auth
account		include		system-auth
session		include		system-auth

Now, 3-5 are trickier. PAM does have a timestamp plugin that mirrors sudo’s in some ways, but it doesn’t quite fit exactly what you’re looking for – for case 3, it doesn’t cache correctly with sudo (as it seems to be more intended for caching logins than for sudo). When authenticating, sudo requests that you authenticate as yourself, so the target user for the PAM timestamp is yourself. However, when generating timestamps, the PAM plugin uses the target user for the session – which in this case, is root (or whatever other user you’re running as).

This is the verbose log when attempting to authenticate for sudo using the cached timestamp (reverse order):

Jan 17 14:49:48 Xenon sudo[513117]: pam_timestamp(sudo:auth): cannot open timestamp `/var/run/pam_timestamp/animus/tty3': No such file or directory
Jan 17 14:49:48 Xenon sudo[513117]: pam_timestamp(sudo:auth): using timestamp file `/var/run/pam_timestamp/animus/tty3'
Jan 17 14:49:48 Xenon sudo[513117]: pam_timestamp(sudo:auth): tty is `/dev/tty3'
Jan 17 14:49:48 Xenon sudo[513117]: pam_timestamp(sudo:auth): currently user `animus'
Jan 17 14:49:48 Xenon sudo[513117]: pam_timestamp(sudo:auth): becoming user `animus'

Then, after it authenticates, as part of the session management, it creates a timestamp, but this time the target user is whatever user you’re running as:


Jan 17 14:49:52 Xenon sudo[513117]: pam_timestamp(sudo:session): updated timestamp file `/var/run/pam_timestamp/animus/tty3:root'
Jan 17 14:49:52 Xenon sudo[513117]: pam_timestamp(sudo:session): using timestamp file `/var/run/pam_timestamp/animus/tty3:root'
Jan 17 14:49:52 Xenon sudo[513117]: pam_timestamp(sudo:session): tty is `/dev/tty3'
Jan 17 14:49:52 Xenon sudo[513117]: pam_timestamp(sudo:session): currently user `animus'
Jan 17 14:49:52 Xenon sudo[513117]: pam_timestamp(sudo:session): becoming user `root'

So, not sure it’s easily doable. If you’re determined, I’d make a custom PAM module based off the timestamp module. You could modify it not to make a different timestamp for different target users, then point your sudo configuration at that one. After letting PAM handle the caching, you can disable sudo’s built in password caching by setting the default timestamp_timeout in /etc/sudoers to 0.

Scenario 4 also is similar to the timestamp plugin’s functionality, but the timestamp plugin is based on last authentication (aka when you logged in/unlocked), not when you went idle. I’m not sure PAM is notified when you lock the screen/session, so I’m not sure how doable it is as you specify it. My workaround would be to use the timestamp plugin to allow you to unlock using only a fingerprint if you’ve authenticated fairly recently. You could do this by making the fingerprint required first, then have the timestamp be sufficient after (in gdm-password and gdm-fingerprint).

Scenario 5 is technically doable (the sleep part at least), by creating a systemd unit that runs on sleep that wipes the timestamps used by PAM. It would look something like this (note: I just wrote that off the cuff, haven’t tested it. It’s roughly based off a script I used for power management so it may need tweaking, particularly the remain/stop bits).

9 Likes

Awesome! Thank you very much for the detailed reply! Will definitely try it out.

So, am I right saying that sudo does this time based trick on its own and not via PAM? That probably explains why locking a session does not reset the sudo state :thinking:

1 Like

To all the fellow Linux newbies out there: don’t repeat my mistakes and edit PAM files without being certain you have sufficient backups.

I made a backup of my home directory beforehand so I could restore my data if I messed up. Because I used authselect before and had made a backup of my PAM configuration from before using it in there, I thought I was all set.

Little did I know that the latter only preserved what PAM files were in use and not their state. Because I foolishly thought that the existence of gdm-fingerprint and gdm-password meant that they were in use, I followed the (excellent) guide by @reanimus one by one and didn’t make a copy of the files in their before-state. Turns out: Budgie seems not to use them, so I think I got away with it, but if there’s some weird auth error down the line, I’ll know who to blame.

If you’re like me and use Budgie and want to use the fingerprint for sudo and screensaver logins only (which isn’t easily doable with authselect or the Ubuntu equivalent from my understanding), add
auth sufficient pam_fprintd.so to the top of both budgie-screensaver and sudo in the /etc/pam.d directory.

5 Likes