I'm trying to set up Chef-managed accounts for a group of machines with the following characteristics:
- If there is no local account, login is blocked.
- If there is a local account with SSH keys, use those for authentication is possible.
- If there is a local account that has a local password, that password is used for authentication.
- If there is a local account with no local password, Kerberos is used.
I've got that much working.
But the last thing I want to be able to do is to disable login on the account by locally locking the password (e.g. using usermod -L
). The problem is that when the local password is locked, PAM is falling back to Kerberos ... and allowing access.
Is there a way to configure PAM so that if a local password exists but it is locked that it won't try Kerberos?
The best I can think of so far is to lock the account by clobbering the local password with something unguessable. But that is a bit crude, and doesn't play well if someone does not "follow the procedure" ...
I agree with Michael Hampton's comments - you can and should use Kerberos to do this. But if you do want to do it by changing things on the local machine, here's a solution that should work.
In your
sshd_config
, add the lineCreate a group named "blocked". When locking a user's local password, also add them to the group "blocked".
WARNING! This is a horribly ugly kludge that shouldn't exist in a sane world. It may, however, be useful in the one we live in.
This problem is mostly a consequence of the fact that
pam_unix.so
checks for account lockouts in theauth
stack instead ofaccount
, which is a little counter-intuitive for PAM newbies. Accounting decisions should be made inaccount
, notauth
, but shadow based account locks are performed based on the password field. This makes it a necessary compromise.Before continuing from there and deciding how to implement your fix, let's review the management groups defined by PAM:
auth
-- Authentication concerns. Limit your tweaks to decisions based on credentials the user is submitting to authenticate, particularly since programs may choose to bypass this module entirely if they implement their own authentication scheme. (the example everyone forgets:sshd
skipsauth
if SSH key authentication is enabled and succeeds)account
-- The one that most people new to PAM overlook. If authentication succeeded but the user should be denied access anyway, that decision should be made here. (sshd
will not skip this module if SSH key authentication succeeds, unlikeauth
)passwd
-- Changing passwords related to services you defined inauth
.session
-- Miscellaneous tasks that generally have little to do with whether or not authentication succeeds. Logging, mounting stuff, etc.Based on your problem description:
auth
stack that prioritizes local credentials over krb5 credentials, but one of the two must succeed. Sounds like you've got that covered.account
stack that denies access if no local user is defined. As stated earlier,pam_unix.so
fails us in this regard.passwd
defaults are probably fine for changing local passwords.session
.Based on your proposed self-answer, it looks like you have an idea of where to take it from here.
I need to check this at work, but I think I could add a "pam_exec" entry to the stack after "pam_krb5" entry. This could run a script that uses "passwd -S" to check that the password entry for the user has not been locked.
Or I could do it by placing the user a "blocked" group and using pam_succeed_if like this:
For general use, I don't recommend mixing local and kerberos accounts. However, this auth pam stack should work for our purposes. (You may have other piece e.g.
pam_env.so
that you'll include.)If the user's local password is incorrect, or locked, authentication will fail. If the user has no local password, authentication uses kerberos (not GSSAPI), if that fails authentication will fail.