Description of problem: The subject nearly says it all: if you use shadow passwords and the exim plaintext authenticator (over TLS) configured to use PAM to authenticate credentials, thus PLAIN: driver = plaintext server_set_id = $auth2 server_prompts = : server_condition = ${if pam{$2:$3}{1}{0}} server_advertise_condition = ${if def:tls_cipher } then it doesn't work, although if you copy the password from /etc/shadow to /etc/passwd it works fine. I did a good deal of debugging, and I think I can explain the root cause of the problem. The exim MTA runs as an unprivileged user "exim" (uid 93 on my system). When the exim daemon does a callout to PAM to validate user credentials. The pam_unix module determines that the password is shadowed, and that the user is unprivileged, and executes a SUID helper binary /sbin/unix_chkpwd as /sbin/unix_chkpwd username nonull with the PAM library that forked this command sending the password to the child process through a pipe. The problem is that /sbin/unix_chkpwd program contains the following: if (SELINUX_ENABLED && getuid() == 0) { user=argv[1]; } else { user = getuidname(getuid()); /* if the caller specifies the username, verify that user matches it */ if (strcmp(user, argv[1])) { return PAM_AUTH_ERR; } } So, even if SELinux is enabled, because our UID 93 is nonzero, we execute the else clause. This tests to see if the process UID matches the username provided on the command line. Since the username provided on the command line is the name of the user wanting SMTP authentication and the UID of the process matches the user "exim", this always fails. Thus, SMTP authentication with exim cannot use PAM and shadow passwords. Version-Release number of selected component (if applicable): pam-0.99.6.2-3.27.el5 How reproducible: Easily. Steps to Reproduce: 1. Configure exim to use the PLAIN authenticator with PAM (uncomment the stanza in the default /etc/exim/exim.conf) 2. Configure PAM to use shadow passwords. 3. Attempt an SMTP authentication. It might be easier to use a simple PAM test program; I wrote one and can supply it. Just run the program as one unprivileged user trying to authenticate another. Actual results: SMTP Authentication always fails. Expected results: SMTP Authentication should succeed for valid credentials. Additional info: I have verified that patching /sbin/unix_chkpwd to remove the if/else statement above fixes the problem. I am attaching the patch FYI.
Created attachment 307298 [details] patch that fixes the issue (but might not be desirable for other reasons)
The check is there for a purpose and cannot be removed. The unix_chkpwd must not allow a regular user to check another user's password hash. The current PAM in Fedora 9 does not do the check explicitely though. It will just do setuid(getuid()) call and so if /etc/shadow would be readable to the exim process - it will allow to proceed and verify the password hash. I am not sure whether the pam_unix module in RHEL-5 would allow this, you can verify that by adding ACL on /etc/shadow or making /etc/shadow group readable and owned by the exim user's group.
(In reply to comment #2) > The check is there for a purpose and cannot be removed. The unix_chkpwd must not > allow a regular user to check another user's password hash. That requirement is a bit too heavy handed. I agree that if any user can read the hashes in /etc/shadow then there's no point in storing the hashes in /etc/shadow instead of /etc/passwd; however, I think the Fedora approach: > The current PAM in > Fedora 9 does not do the check explicitely though. It will just do > setuid(getuid()) call and so if /etc/shadow would be readable to the exim > process - it will allow to proceed and verify the password hash. makes a lot more sense. Then, for example, you could have a "shadow" group, and make /etc/shadow readable to members of that group, then add the exim user to it. > I am not sure > whether the pam_unix module in RHEL-5 would allow this, you can verify that by > adding ACL on /etc/shadow or making /etc/shadow group readable and owned by the > exim user's group. It won't; you don't have to do any experiments to see that from the source code for /sbin/unix_chkpwd. In particular, the test I quoted above if (SELINUX_ENABLED && getuid() == 0) { user=argv[1]; } else { user = getuidname(getuid()); /* if the caller specifies the username, verify that user matches it */ if (strcmp(user, argv[1])) { return PAM_AUTH_ERR; } } shows that it will only allow a user to check his own password hash, irregardless of whether or not he can read /etc/shadow.
The pam_unix module code is different in RHEL-5 from the F-9 version so it might work if SELinux doesn't prevent it.
The checks are slightly relaxed in current Fedora releases which means that RHEL-6 should be OK in this regard.