I’ve been working on a PR to make the PAM helper binary unix_chkpwd not be setuid root. (At most it needs CAP_DAC_READ_SEARCH.) In the process I have tripped over some issues, both with unix_chkpwd itself, and with with how we create /etc/shadow, that I think should be brought up to a wider audience.
It’s not actually clear to me that unix_chkpwd needs to be an intrinsically privileged binary at all. If /run/wrappers/bin/unix_chkpwddoesn’t exist, all logins fail, but if it is an ordinary executable (mode 0755, no file capabilities) everything seems to work fine.
The PAM documentation says that the purpose of unix_chkpwd is to allow pam_unix.so to “verify the password of the current user” even when invoked from a completely unprivileged context. Since verifying passwords involves reading from /etc/shadow, and that file is not readable by unprivileged users, it makes sense that this would require an intrinsically privileged binary. The catch, though, is that I can’t find any programs that actually do invoke pam_unix.so from a context that doesn’t already have enough ambient privilege to read /etc/shadow; in particular, both console gettys and sshd run PAM authentication checks with full root privileges, and I think so do passwd, su, sudo, etc. (I originally started down this rathole because I thought sshd sandboxed PAM, but I was mistaken; my original experiment completely removed /run/wrappers/bin/unix_chkpwd instead of just stripping its privileges. Presumably all existing users could be patched to invoke /nix/store/<hash>-linux-pam-<ver>/bin/unix_chkpwd directly, or that file could be added to the PATH used by system daemons that need it.)
Does anyone know of a program that really does invoke pam_unix.so, in a mode where it needs unix_chkpwd, without enough ambient privilege to read /etc/shadow?
[EDIT: as discussed below, unix_chkpwd does indeed need to be intrinsically privileged so that it can be used by, for example, programs that lock the user’s session; these normally should not themselves be set-id.]
Assuming unix_chkpwd does need to be an intrinsically privileged binary, it would be nice to not have to give it CAP_DAC_READ_SEARCH (which is a very powerful capability) since the only file it needs special privilege to access is /etc/shadow. The PAM documentation says that a least-privilege configuration is for /etc/shadow to be installed with ownership and permissions -rw-r----- root shadow, and then unix_chkpwd can be be just setgidshadow.
This is how the traditional make-users-groups.pl sets up /etc/shadow, so I presume that all the other software in NixOS can handle that setup; howewer userborn makes it ---------- root root instead. Was that an intentional change in userborn? If so, what was the rationale?
Speaking of userborn, it seems to silently ignore users.users.<name>.expires and possibly also other users.users.<name> settings that translate to shadow file fields. Is this a known bug?
Upstream FreeRADIUS has the PAM module disabled at build time, apparently because
And the nixpkgs package doesn’t offer any option to turn it on, so that’s no good for the automated NixOS test I’m trying to write (and I’d rather not rebuild something as big as freeradius just for an automated test, anyway).
This is a better example of a case where it matters in practice, but I don’t see how to write an automated NixOS test that interacts with a GUI screen lock. Do you (or anyone) have any suggestions for that? (Is there a console screen lock somewhere in nixpkgs?)
Nominally, vlock and physlock are probably fitting the request for «VT-based locker». I think they have some extra functionality/integrations, though, making unprivileged installation a non-default mode.
For XScreenSaver one could imitate any GUI NixOS test (but I think we don’t have many, because they are a bit of a grind to debug); it helps that with a locker you can normally lock from command line, then any keypresses sent go to the locker by definition and usually go to the password field (maybe after the first key).
But yeah, I agree that «just test the password check» approach sounds like a better answer to the specific need discussed. Session lockers are small and thus somewhat replaceable, so churn risk is high, and this is probably not the highest-payoff thing to test well.
Set-GID shadow with the group only having some read-only access to a few files does sound reasonable to me as general analysis; I am using neither NixOS mainline nor userborn, though, so I am not sure about the implementation reasons; I think using the setgid solution in more cases should not be too hard to get through on the NixOS side (assuming there are tests and they pass for the knowningly-affected cases)