PAM accepting any password for valid users
Solution 1:
Let's analyze the authentication section of your PAM configuration in detail.
auth sufficient pam_unix.so nullok try_first_pass
The first line says: "If this test is successful, stop checking any further and accept the login; if it fails, keep checking. Check for users/passwords configured in /etc/passwd
and /etc/shadow
.If the user exists and the password field is blank, user is allowed in." This is the authentication check for local user accounts.
auth requisite pam_succeed_if.so uid >= 500 quiet
The second line says: "If this test fails, stop checking any further and reject the login; if successful, keep checking. The user's UID value must be 500 or greater." This prevents logins to system accounts using passwords in AD or other shared user database.
auth sufficient pam_sss.so use_first_pass
The third line says: "If this test is successful, stop checking any further and accept the login; if it fails, keep checking. Check with SSSD." This is the check for AD accounts.
auth required pam_env.so
The fourth line says: "If this line fails, reject the login; but keep checking to the end of this section in any case. Set any environment variables described in /etc/security/pam_env.conf
and/or /etc/environment
."
Now think of what will happen if the user exists (either in AD or in local /etc/passwd
) but the password checks fail. First, pam_unix.so
fails; but that cannot cause a rejection because that would stop you from using any AD-based user accounts.
So the process goes on to the second line. If the user has a valid UID mapping and the UID number is 500 or greater, this will pe successful too. The only ways this would fail would be if the UID was less than 500.
The third line makes the AD check; this fails too. But again, "sufficient" is used to allow configuring any other authentication methods after this one, so the process continues, just as with pam_unix.so
.
At this point, the fourth line must be executed successfully to allow the user in. But this is just setting environment variables. man pam_env
tells me the pam_env.so
module will return a PAM_SUCCESS value if the environment variables were successfully set. But because this is the last PAM module in this stack, and none of the other modules will have put in an absolute rejection so far, the result of this module will become the overall result of the authentication phase.
To fix this, the authentication phase needs a pam_deny.so
at the very end, to stop any login attempts whenever all the actual authentication mechanisms have failed to accept the user.
Also, the pam_env.so
should probably happen earlier in the process, so that the environment variable initialization would happen the same way for all valid users. If this does not work at the beginning of the auth
phase, then the pam_env.so
should probably go to the session
phase instead; man pam_env
says it will work in either auth
or session
phases.
So, my initial suggestion would be to change the auth
section of your PAM configuration to this:
auth required pam_env.so
auth sufficient pam_unix.so nullok try_first_pass
auth requisite pam_succeed_if.so uid >= 500 quiet
auth sufficient pam_sss.so use_first_pass
auth requisite pam_deny.so
So, the functionality would be:
- Set environment variables for the user. If this fails, something is seriously wrong anyway.
- Check for local password; if successful, accept the login and end this phase.
- Reject any users with UID less than 500 at this point (= no root or system account login with an AD account!)
- Check for password in AD; if successful, accept the login and end this phase.
- If we get to this point, none of the real authentication mechanisms accepted the password, so reject the login attempt unconditionally.
If it turns out that pam_env.so
causes problems when placed at the beginning of the auth
phase, you may try just commenting it out; it seems that previously it was skipped on any valid logins.
As always when changing PAM configurations, first open a session to the system and make sure it's sudo
'd to root or otherwise has full root privileges available: then backup the current configuration. Make the change but don't log out to test it: instead, test it by opening another session. If it fails, you still have the original session logged in, so you can easily restore the old configuration if necessary. If this is a production system or otherwise critical one, open two root sessions before making the change, just to protect against fingers-being-faster-than-brain errors.