Summary: | sudo fails to find LDAP users, despite NSS (seemingly?) working correctly | ||
---|---|---|---|
Product: | Gentoo Linux | Reporter: | Brian Vargas <ardvaark-gentoobugs> |
Component: | Current packages | Assignee: | Andrea Barisani (RETIRED) <lcars> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | adam.carheden, evert.gentoo, gentoobugs, kevin, taviso, trask768, zhcnmccmzhdvfevooo |
Priority: | High | ||
Version: | unspecified | ||
Hardware: | x86 | ||
OS: | Linux | ||
Whiteboard: | |||
Package list: | Runtime testing required: | --- | |
Attachments: |
Example sudo pam stack
Example system-auth pam stack Patch to remove setting of LDAPNOINIT Updated ebuild integrating the patch from Kevin. patch to unset LDAPNOINIT at the right moment |
Description
Brian Vargas
2005-09-29 12:13:06 UTC
I don't think this is a sudo problem but rather an issue with your ldap setup (and that could be 1000 things). a) Does getent passwd as the user invoking sudo works? b) could you show me /etc/pam.d/sudo and /etc/pam.d/system-auth did you recompile sudo after the last openldap upgrade? I have recompiled both sudo and openldap since this problem appeared. I don't have access to the problem machines at the moment - I'll get you the requested information tomorrow morning, EDT. Running getent passwd as the user for whom sudo fails correctly returns the entries from LDAP. I am creating attachments for my sudo and system-auth pam stacks. Created attachment 69564 [details]
Example sudo pam stack
Created attachment 69565 [details]
Example system-auth pam stack
Then nss doesn't work correctly and the problem is not related to pam or sudo at all. I need /etc/ldap.conf, /etc/openldap/ldap.conf and your .ldaprc for root and the user (if any) along with any fancy conf in slapd.conf If you prefer mail me directly, close this bug as INVALID and we could sort the issue privately since it's not strictly a bug with gentoo. Marking as INVALID and continuing the conversation privately. I will post any final resolution to the forum thread above. *** Bug 107951 has been marked as a duplicate of this bug. *** While I still think this is a LDAP setup problem it appears that we can't pinpoint the issue to the ldap setup easily (as it's common when dealing with ldap stuff), so I'm reopening the bug in order to get further feedback from other folks that might experience the same (yes 107951 I'm looking at you! ;) ). I have a perfectly working setup though and I can't replicate the issue. Works if you emerge app-admin/sudo without the "ldap" useflag. Still counts as a bug IMO. More info on the original forum thread http://forums.gentoo.org/viewtopic-p-2775819.html I posted this on bug #107951, but I wanted to add these comments here so that everything would be in one place. After running into problems with the sudo package, I downloaded the source code for sudo and compiled it on my system instead of fiddling with the sudo USE flags. The following configure flags worked perfectly: ./configure --prefix=/usr --with-pam --without-passwd The following configure flags causes the uid not found error: ./configure --prefix=/usr --with-pam From what I can tell, the problem is that sudo, by default tries to validate a user from the passwd file rather than by pam. So, to fix the package, I think you just have to make sure that the --without- passwd configure option is set when the +pam USE flag is set. Since you configure PAM to take care of the LDAP details, sudo just needs to forget about reading the passwd file - it should get its information from pam instead. I ran into a similar problem and found that the app-admin/sudo ebuild file forced the config file to /etc/ldap.conf.sudo instead of the standard /etc/ldap.conf. A quick symlink from ldap.conf to ldap.conf.sudo fixed my problem. Actually, the configuration file is intentionally set to ldap.conf.sudo so that the sudoers information can be read-only, in the same way that /etc/sudoers is usually read-only. Simply symlinking and changing the permissions leaves yourself less secure. We are having the same problem with a ssh installation, this is related to libldap and not to sudo and/or nss apparently. Can you please trying rebuilding openldap (and possibly glibc + sudo after that) and see if something changes? I rebuilt openldap, glibc, and sudo. No change. I've also had this problem, just using the USE=-ldap workaround for now to get things operational I also experience this problem and have had to use the -ldap option on sudo to overcome it for the time being however this affects the ability to use ldap instead of the sudoers file, but at least the users can now sudo! So we have 3 users with the same problem apparently but I can't reproduce it on any box. Can yo all mail me /etc/pam.d/sudo, /etc/pam.d/system-auth, /etc/nsswitch.conf, /etc/ldap.conf and /etc/ldap.conf.sudo please so that I can get a clue and spot the misconfiguration (because that's really likely to be the case). Reviewing the sudo code, I found that enabling its LDAP features causes it to set LDAPNOINIT in the environment. This is described in the code as a security measure to prevent users' .ldaprc from being read along with its own ldap.conf.sudo, but it also clobbers nss_ldap's configuration when sudo calls it. Deleting the LDAPNOINIT code from sudo solves my problem, which seems to have been the same as everyone else's here. My sudo (1.6.8_p9-r2, USE=ldap) now properly handles its config from LDAP along with users defined only in LDAP. This theoretically leaves the security problem with user .ldaprc, but I wasn't able to redirect sudo to another LDAP server by creating a "hostile" .ldaprc of my own. If this is actually a problem, it will probably fix itself in upstream's planned config rehaul. In any case, I'm attaching a patch to remove the offending LDAPNOINIT code, with the caveat that this may leave a vague, obscure security hole. Created attachment 74913 [details, diff]
Patch to remove setting of LDAPNOINIT
Confirmed that this fixes the problem. Awesome! I'll attach the ebuild I used in my overlay momentarily. Created attachment 74948 [details]
Updated ebuild integrating the patch from Kevin.
The only change from r2 is an additinal epatch targeting sudo-remove-LDAPNOINIT-scrubbing.diff.
I don't get this .ldaprc "security" issue, sudo is run as root so /home/$user/.ldaprc is never meant to be used. Besides sudo works just fine here with or without .ldaprc settings. Were some of you using ldap nss settings in your own .ldaprc instead of /etc/ldap.conf? (because that's the only think I didn't try, I only have certs specifications in .ldaprc) Btw I want upstream opinion on this before committing the patch since I'd like to understand the logic behind that code. I'm not sure what was meant in the code either. (Direct quote from code comment: "Prevent OpenLDAP from reading any user dotfiles or files in the current directory.") A setuid program will still carry the real user's $HOME through to glibc and nss, and sudo might not clear its environment before it checks on the calling user. I definitely see the problem with a current-directory .ldaprc. No, I never had any .ldaprc files at all. LDAPNOINIT is supposed to suppress all configuration files, including /etc/ldap.conf, so that being set should be enough to clobber nss_ldap. I'm actually not sure how nss_ldap could work for anyone with sudo doing this, so there must still be some difference between our setups. I tend to think that solution to your problem could be related to the recompiling itself and not to the supposed "fix", I really can't see how that would solve the problem and it's logic anyway. I'm bugging sudo-workers about this right now. Could you recompile without the patch and see if the behaviour changes somehow? I, too, have never had any user-specific .ldaprc files. Additionally, I've re-compiled sudo backwards and forwards since this problem cropped up. (This is Gentoo, after all. ;-) I just re-compiled again on a problem machine without the patch and with +ldap, to no avail. Sudo is unable to find the LDAP user via NSS, and fails with the message "sudo: uid 1000 does not exist in the passwd file!" I would also like to find out why it works on some systems and not others - that is really strange. Looking at openldap-2.2.28/libraries/libldap/init.c, it does seem true that no configuration files will be read by libldap if the LDAPNOINIT environment variable is set. If it's set, the ldap_int_initialize() method returns, and never reaches the call to openldap_ldap_init_w_sysconf(). Same for me: I recompiled with multiple combinations of useflags and even tried some EXTRA_ECONF settings on sudo, but nothing worked but the patch before or after I used it. For the sake of completeness, here's my entire chain of involved package versions: app-admin/sudo-1.6.8_p9-r2 (with the LDAPNOINIT patch) net-nds/openldap-2.2.28-r3 sys-auth/nss_ldap-239-r1 sys-libs/glibc-2.3.5-r2 sys-libs/pam-0.78-r3 (though the error in question occurs before sudo even queries pam) sudo is obviously capable of reading sudoers from LDAP even after it has set LDAPNOINIT (else this would be a much more prominent bug), so this is all a difference between the behaviour of sudo->libldap and of sudo->glibc->nss_ldap->libldap. It seems that a more stable solution would be either to wait on setting LDAPNOINIT until sudo has done all its authorisation, or to have nss_ldap do whatever the sudoers parser does to read its LDAP config anyway. Or, for that matter, to have some differentiation in OpenLDAP between suppressing global config files in /etc and suppressing user config in $HOME or $PWD. ok same here at my site. with the LDAPNOINIT patch it works good, as describe by the others here. But is it now a real security hole to use this patch? Or any update here? (In reply to comment #29) Thanks for reminding everyone about this; I had almost completely forgotten it. I went back through sudo's execution order. LDAPNOINIT is set early on when sudo resets its environment for security purposes. After parsing arguments, it then checks sudoers, either from LDAP or [/etc/sudoers]. These LDAP transactions succeed despite LDAPNOINIT=1 because sudo manually reads and parses its LDAP configuration file (in Gentoo's case, [ldap.conf.sudo] instead of [ldap.conf]). So while in the default setup, with one unified [ldap.conf], LDAPNOINIT only serves to keep out user [.ldaprc]s, a setup like Gentoo's with a separate --with-ldap-conf-file needs it to maintain that separation as well. All that only applies in theory. LDAPNOINIT is obviously not useful for nss_ldap, since it clobbers it, so that can be ignored entirely. As for guarding sudo's own LDAP config, sudo's ldap.c seems to do a pretty good job of that itself. AFAICT, every applicable option is set or handled in override of whatever OpenLDAP brings to the table. Practically speaking, I haven't been able to get a test case with [.ldaprc] or [/etc/ldap.conf] injecting anything, despite multiple tries to redirect to another server, turn TLS on/off, switch bases and bind DNs, etc. I looked over the sudo-workers archive and discovered that the LDAPNOINIT code in sudo was born from the sudo bug [http://www.courtesan.com/bugzilla/show_bug.cgi?id=145]. It wasn't the solution to the bug itself, but was intended to address setups with separation of [ldap.conf] files. So, to be cautious, I created a new patch that leaves LDAPNOINIT in place during sudo's LDAP activity, but then immediately [unsetenv]s it. This new patch compiles cleanly and continues to solve the problem for me. There is definitely not a security issue with this one. Created attachment 83418 [details, diff]
patch to unset LDAPNOINIT at the right moment
(In reply to comment #31) > Created an attachment (id=83418) [edit] > patch to unset LDAPNOINIT at the right moment > Did everyone else have success with this patch? I've put this in my overlay along with the above new ebuild with no success. I've also tried adding --without-passwd to the ebuild, also with no success. The only thing that fixes it for me is removing the ldap use flag. One more though. I believe this bug is either in OpenLDAP or related to OpenLDAP. The problem started occuring for me after replacing my CentOS OpenLDAP server with a Gentoo OpenLDAP server (due to a hard drive crash). Sudo worked fine on all of my Gentoo servers when they authenticated against the CentOS ldap server even though they all had stock sudo-1.6.8_p9-r2, indlucing the ldap use flag. The major difference I notcied from the admin side is that the client's /etc/ldap.conf used only the host, base, 'pam_password md5', and tsl_cacertdir directives with the CentOS server. My Gentoo server uses uri, suffix, 'pam_password exop', etc. as specified in the howto (http://www.gentoo.org/doc/en/ldap-howto.xml). Can anyone shed some light on if the pam_* attirbutes recommended in that howto may be related? I did not even bother trying the patch, I just added the next line in /etc/portage/package.use and remerged sudo which works find for me. app-admin/sudo -ldap Simply adding -ldap only solves the problem if you are not itending on defining sudoers information in a directory. Without the ldap USE flag, sudo gets built sans LDAP support, making it impossible to do what we want. (In reply to comment #31) > Created an attachment (id=83418) [edit] > patch to unset LDAPNOINIT at the right moment > Is it possible to have this in portage as an unstable package so we can easily merge this into our system for testing??? or does someone already have all the modifications needed to a ebuild?? and can they please attach it here thanks. (In reply to comment #36) The already-attached ebuild from Brian is almost identical to what I'm using. The name he gave the first patch isn't exactly right now--LDAPNOINIT is still present for sudo's own config parsing--but that's neither here nor there. That ebuild should work for you. Have you guys looked at your slapd logs? or how about your logs from pam? Does PAM do this for you: [sudo] nss_ldap: reconnecting to LDAP server (sleeping 1 seconds)... Does slapd show this? Mar 5 16:37:30 [slapd] connection_get(13): got connid=2_ Mar 5 16:37:30 [slapd] connection_read(13): checking for input on id=2_ Mar 5 16:37:30 [slapd] connection_read(13): TLS accept failure error=-1 id=2, closing_ Mar 5 16:37:30 [slapd] connection_closing: readying conn=2 sd=13 for close_ Mar 5 16:37:30 [slapd] connection_close: conn=2 sd=-1_ with sudoers_debug set to 2 I get the following as root and every real user that exists in /etc/passwd. # sudo --help sudo: please use single character options LDAP Config Summary =================== uri ldap://gravel.internal.company.com ldap://marble.internal.company.com ldap_version 3 sudoers_base ou=SUDOers,dc=company,dc=com binddn (anonymous) bindpw (anonymous) bind_timelimit 30 timelimit 30 ssl start_tls =================== ldap_set_option(LDAP_OPT_X_TLS_CACERTDIR,"/etc/ssl/certs/") ldap_set_option(LDAP_OPT_X_TLS_REQUIRE_CERT,0x01) ldap_set_option(LDAP_OPT_TIMELIMIT,0x1e) setting bind_timelimit to 30 ldap_initialize(ld, ldap://gravel.internal.company.com ldap://marble.internal.company.com) ldap_set_option(LDAP_OPT_PROTOCOL_VERSION,0x03) ldap_start_tls_s() ok ldap_bind() ok found:cn=defaults,ou=SUDOers,dc=company,dc=com ldap search '(|(sudoUser=root)(sudoUser=%root)(sudoUser=%root)(sudoUser=%bin)(sudoUser=%daemon)(sudoUser=%sys)(sudoUser=%adm)(sudoUser=%disk)(sudoUser=%wheel)(sudoUser=%floppy)(sudoUser=%dialout)(sudoUser=%tape)(sudoUser=%video)(sudoUser=ALL))' ldap search 'sudoUser=+*' user_matches=0 host_matches=0 sudo_ldap_check(0)=0x44 usage: sudo -K | -L | -V | -h | -k | -l | -v usage: sudo [-HPSb] [-p prompt] [-u username|#uid] { -e file [...] | -i | -s | <command> } Any user that only exists in LDAP but is visible via getent passwd I get the following: $ sudo --help sudo: please use single character options LDAP Config Summary =================== uri ldap://gravel.internal.company.com ldap://marble.internal.company.com ldap_version 3 sudoers_base ou=SUDOers,dc=company,dc=com binddn (anonymous) bindpw (anonymous) bind_timelimit 30 timelimit 30 ssl start_tls =================== ldap_set_option(LDAP_OPT_X_TLS_CACERTDIR,"/etc/ssl/certs/") ldap_set_option(LDAP_OPT_X_TLS_REQUIRE_CERT,0x01) ldap_set_option(LDAP_OPT_TIMELIMIT,0x1e) setting bind_timelimit to 30 ldap_initialize(ld,ldap://gravel.internal.company.com ldap://marble.internal.company.com) ldap_set_option(LDAP_OPT_PROTOCOL_VERSION,0x03) ldap_start_tls_s(): -11: Connect error usage: sudo -K | -L | -V | -h | -k | -l | -v usage: sudo [-HPSb] [-p prompt] [-u username|#uid] { -e file [...] | -i | -s | <command> } This is from the same machine.... I've managed to track this down to TLS connections failing for nss_ldap when sudo is compiled with USE=ldap. However, when sudo is compiled USE="-ldap", then nss_ldap is able to perform TLS connections. I believe the problem lies in a OpenLDAP sharing OpenSSL contexts when it's not safe to share them or one that's already been freed. My assumption was correct. I discussed this with OpenLDAP upstream and they are working to fix this for the OpenLDAP 2.4 release. I however have managed a work around with configs. People can contact me on IRC for some assistant if they'd like me to help them with their config. lcars: You might want to close this as upstream. (In reply to comment #41) > My assumption was correct. I discussed this with OpenLDAP upstream and they are > working to fix this for the OpenLDAP 2.4 release. I however have managed a work > around with configs. People can contact me on IRC for some assistant if they'd > like me to help them with their config. > > lcars: You might want to close this as upstream. > I was about to reply to this saying that the bug you've found and fixed is completely unrelated. Our nss_ldap configurations weren't being read in the first place (literally no stat of /etc/ldap.conf in trace), and it didn't even have the chance to attempt and fail a TLS negotiation. Before doing so, however, I recompiled sudo without the patch we've been using, and our problem seems to no longer exist (still using OpenLDAP 2.3 as before). I'm guessing it was resolved in one of the newer nss_ldap versions, which mentioned changing the way configuration and reconnection are handled. If anything, our bug was masking the one you found, so it's good to know that both have been/are being worked out. Closing since one way or another it looks fixed ;) |