Package: libpam0g Version: 0.79-4
Package: libnss-ldap Version: 251-7.5 On Debian Sarge in LDAP authentication enviroment it is possible to allow login only for users listed in group identified by "pam_groupdn". In case the user does not exist in the group, access is debied by LDAP. Usually the pam_ldap precede pam_unix. In case the user "root" is not in LDAP but only local user (in case of all LDAP servers failure), the user "root" can still login even if not in "pam_groupdn" listed - pam_unix checks if user "root" exists in system and in shadows. On Debian Etch this does not work and PAM allows login users which are not local on the machine and were authenticated against LDAP. Pam_ldap in this case deny access but pam_ldap is only "sufficient" and then pam_unix is processed and in this case pam_unix allows login to users which has not record for shadow password. For pam_unix there is a option "broken_shadow", which should ignore errors when reading shadown info for user. This should be the case, but pam_unix ignores errors even without this option and allow login. I am not sure, in which package is the error, but IMO pam_unix should not allow login users without correct shadow info if option "broken_shadow" not used. I wanted to send an email into pam-list mailing list, but my email has been never distributed in the mailing list (I am subscribed and I have sent email from correct email address). Please, see my email to pam-list mailing list below, it contains detailed info. Regards, Wolf. ########################################################################### Dear PAM dev team, I would like to ask you for your opinion to the following situation: I have Linux setup for LDAP authention. On Debian system, I've installed libnss-ldap and libpam-ldap packages and configured /etc/pam_ldap.conf and /etc/libnss-ldap.conf ================================================== uri ldaps://LDAP-HOST base BASE-DN ldap_version 3 scope sub idle_timelimit 3600 nss_connect_policy persist bind_policy hard timelimit 30 pam_filter objectclass=posixAccount pam_login_attribute uid pam_lookup_policy yes pam_groupdn LOGIN-ALLOWED-GROUP-DN pam_min_uid 10000 pam_password clear ssl on tls_checkpeer yes tls_cacert /etc/ldap/cacerts.pem tls_cacertfile /etc/ldap/cacerts.pem pam_member_attribute uniqueMember ================================================== /etc/pam.d/ssh (default by debian package) ================================================== auth required pam_env.so auth required pam_env.so envfile=/etc/default/locale @include common-auth account required pam_nologin.so @include common-account @include common-session session optional pam_motd.so session optional pam_mail.so standard noenv session required pam_limits.so @include common-password ================================================== /etc/pam.d/common-account (inserted line with pam_ldap.so) ================================================== account sufficient /lib/security/pam_ldap.so account required pam_unix.so ================================================== Everything works fine, but I would like to limit access only for users included in group referenced by LDAP DN LOGIN-ALLOWED-GROUP-DN and I have a user's DN in this group. I would like to keep access for root user in case of LDAP server failure. User root has which has records in /etc/passwd and /etc/shadow files. I have DN of user TESTER-A in the group LOGIN-ALLOWED-GROUP-DN. User TESTER-B is not in this group listed. When I try to login on Debian 3.1 Sarge using SSH on account TESTER-A, everything goes correct, and user can login. When I try to login with user TESTER-B, system asks for password and then, because the TESTER-B is not in LOGIN-ALLOWED-GROUP-DN group, it writes "You must be a uniqueMember of LOGIN-ALLOWED-GROUP-DN to login. Connection closed by IP". This is what I expect. Because "account sufficient pam_ldap" did not pass, pam_unix is tested, but the account has no record in /etc/shadow and login is disabled. But the same configuration on Debian 4.0 Etch and Gentoo gives the different results. For the user TESTER-A everything goes same way, that's correct. But for TESTER-B the system asks password and then writes "You must be a uniqueMember of LOGIN-ALLOWED-GROUP-DN to login." but allow user to login. In this case pam_unix does not block to login and allow to login for user which does not exist on the system (TESTER-B exists only in LDAP). I have found following problem in the source code: Until version 246, libnss-ldap uses character "x" if userPassword LDAP attribute is not present (or contains unknown type). Since version 246 it uses character "*" (see. libnss-ldap/ChangeLog, version 246, BUG#240). ================================================== libnss-ldap:ChangeLog --------------------- 246 Luke Howard <[EMAIL PROTECTED]> * fix for BUG#240: return "*" rather than "x" for userPassword if not present ================================================== In the source code of pam_unix module, there is function pam_sm_acct_mgmt. This function tries to find if user has an account. At first, it finds user using getpwnam() function, which return line in "/etc/passwd" format. For user from LDAP, it returns in my case line "TESTER-A:x:10000:10000:/home/TESTER-A:/bin/bash" on Debian 3.1 Sarge with libnss-ldap-238. But on Debian 4.0 Etch with libnss-ldap-251 it returns "TESTER-A:*:10000:10000:/home/TESTER-A:/bin/bash". ================================================== Linux-PAM/modules/pam_unix/pam_sm_acct_mgmt.c --------------------------------------------- PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags, int argc, const char **argv) { ... pwent = pam_modutil_getpwnam(pamh, uname); if (!pwent) { pam_syslog(pamh, LOG_ALERT, "could not identify user (from getpwnam(%s))", uname); return PAM_USER_UNKNOWN; } if (!strcmp( pwent->pw_passwd, "*NP*" )) { /* NIS+ */ uid_t save_euid, save_uid; save_euid = geteuid(); save_uid = getuid(); if (save_uid == pwent->pw_uid) setreuid( save_euid, save_uid ); else { setreuid( 0, -1 ); if (setreuid( -1, pwent->pw_uid ) == -1) { setreuid( -1, 0 ); setreuid( 0, -1 ); if(setreuid( -1, pwent->pw_uid ) == -1) return PAM_CRED_INSUFFICIENT; } } spent = pam_modutil_getspnam (pamh, uname); if (save_uid == pwent->pw_uid) setreuid( save_uid, save_euid ); else { if (setreuid( -1, 0 ) == -1) setreuid( save_uid, -1 ); setreuid( -1, save_euid ); } } else if (_unix_shadowed (pwent)) spent = pam_modutil_getspnam (pamh, uname); else return PAM_SUCCESS; #ifdef WITH_SELINUX if (!spent && SELINUX_ENABLED ) spent = _unix_run_verify_binary(pamh, ctrl, uname); #endif if (!spent) if (on(UNIX_BROKEN_SHADOW,ctrl)) return PAM_SUCCESS; if (!spent) return PAM_AUTHINFO_UNAVAIL; /* Couldn't get username from shadow */ ================================================== When function pam_sm_acct_mgmt finds any user (using getpwnam() function), it continues and tries to find record in "shadow" file using function _unix_shadowed(). And when it could not find password as "x" character, then if returns PAM_SUCCESS. In fact this means when user has no record in "shadow" file, it has granted access to machine. IMO this is not correct because there is a option for pam_unix called "broken_shadow" with description "Ignore errors reading shadow inforation for users in the account management module." should be for such a case when shadow info is unreadable. ================================================== Linux-PAM/modules/pam_unix/support.c ------------------------------------ int _unix_shadowed(const struct passwd *pwd) { if (pwd != NULL) { if (strcmp(pwd->pw_passwd, "x") == 0) { return 1; } if ((pwd->pw_passwd[0] == '#') && (pwd->pw_passwd[1] == '#') && (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0)) { return 1; } } return 0; } ================================================== This is the problem I found. I don't know in which package is the error. But I have a few questions: 1) I think, the "x" character in /etc/passwd password field means, that the password is in shadow file - right? What exactly the "*" character means in password field of /etc/passwd? 2) Do you think function _unix_shadowed of Linux-PAM/pam_unix/support.c should check "*" too? 3) A user has LDAP record with userPassword attribute set. libnss-ldap, pam-ldap and the other connects anonymously to read user attributes. And when the libnss-ldap connects as LDAP administrator (which is not secure in production env), it can read userPassword, but it is {SSHA} encrypted. libnss-ldap expects attribute userPassword either in RFC2307 ({CRYPT}) or in RFC3112 (CRYPT$) format. Question: What do you think, what kind of password (character) should function _nss_ldap_locate_userpassword() of libnss-ldap/ldap-nss.c returns for unreadable userPassword attribute? Character "x" (as shadowed password) or character "*" (in what meaning)? What character would be better for NSS compatibility and for PAM (pam_unix)? Thank you for your answer. Regards, Wolf. -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]