Bug 1274244

Summary: pam_unix does not return PAM_USER_UNKNOWN if user does not exist
Product: Red Hat Enterprise Linux 7 Reporter: Michael Fischer <mfischer>
Component: pamAssignee: Tomas Mraz <tmraz>
Status: CLOSED WONTFIX QA Contact: BaseOS QE Security Team <qe-baseos-security>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 7.1CC: pkis
Target Milestone: rc   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2015-10-22 12:04:15 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Michael Fischer 2015-10-22 10:58:14 UTC
pam_unix(8) does not return PAM_USER_UNKNOWN if the user does not exist in the local passwd(5)/shadow(5) files.  Therefore it's impossible to compose predicates in the pam.conf(5) file that involve them.

For example, suppose I want to compose a set of auth rules that look like the following, to enable 2-factor authentication (using pam_duo), whether the user is in the local authentication database or in LDAP:

auth        required      pam_env.so
auth        [user_unknown=ignore default=die] pam_unix.so nullok try_first_pass
auth        requisite     pam_ldap.so use_first_pass ignore_unknown_user
auth        requisite     pam_succeed_if.so uid >= 1000 quiet_success
auth        sufficient    pam_duo.so
auth        required      pam_deny.so

The Debian team enables this behavior already; see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=204506

Comment 2 Tomas Mraz 2015-10-22 12:04:15 UTC
I do not think changing this behaviour of pam_unix in a released RHEL version is appropriate. Users might have already configurations that depend on this current behaviour.
Also there is pam_localuser which purpose is exactly that.

Comment 3 Michael Fischer 2015-10-22 12:13:45 UTC
Thanks for pointing me to pam_localuser.  Here's a solution that appears to work:

auth        required      pam_env.so
# Don't consult local password db (skip next statement) if user is unknown
auth        [user_unknown=1] pam_localuser.so
# If user is known in local password db, and validation fails, fail completely.
# If validation succeeds, skip LDAP validation.
auth        [success=1 new_authtok_reqd=ok ignore=ignore default=die]    pam_unix.so nullok try_first_pass
auth        requisite     pam_ldap.so use_first_pass
auth        requisite     pam_succeed_if.so uid >= 1000 quiet_success
auth        sufficient    pam_duo.so
auth        required      pam_deny.so