After upgrading my Sarge workstation to Etch today, I decided to start messing aroud with sudo-ldap. I was a bit disappointed to find that it did not work with ldaps:// schemes. I did some digging and here is what I have found. I think that there are a combination of factors, which is I why I have CC'd the pkg-openldap list. There must be something going here that I am just not seeing.
The scenario: miami.connexer.com - the workstation santiago.connexer.com - the LDAP server localadmin - is a local account on miami roberto - is an account served from LDAP on santiago I followed the directions in /usr/share/doc/sudo-ldap/README.LDAP.gz. I have the following lines in /etc/ldap/ldap.conf: BASE dc=connexer,dc=com URI ldaps://santiago.connexer.com TLS_CACERT /etc/ldap/cacert.pem sudoers_base ou=Sudoers,dc=connexer,dc=com sudoers_debug 2 Now, santiago's slapd is only accessible via SSL over port 636. This is done both by not allowing slapd to bind to the cleartext port and also by shorewall rules. I loaded the sudoers info slapd on santiago. From miami, I can see the data: [EMAIL PROTECTED]:~$ ldapsearch -x -LLL objectclass=sudoRole dn: cn=defaults,ou=Sudoers,dc=connexer,dc=com objectClass: top objectClass: sudoRole cn: defaults description: Default sudoOption's go here dn: cn=root,ou=Sudoers,dc=connexer,dc=com objectClass: top objectClass: sudoRole cn: root sudoUser: root sudoHost: ALL sudoCommand: (ALL) ALL dn: cn=roberto,ou=Sudoers,dc=connexer,dc=com objectClass: top objectClass: sudoRole cn: roberto sudoUser: roberto sudoHost: ALL sudoCommand: (ALL) ALL Now, the sudoers file on miami has the following: root ALL=(ALL) ALL localadmin ALL=(ALL) ALL The first step was to try invoke sudo from roberto's account: [EMAIL PROTECTED]:~$ sudo ls -a LDAP Config Summary =================== uri ldaps://santiago.connexer.com ldap_version 3 sudoers_base ou=Sudoers,dc=connexer,dc=com binddn (anonymous) bindpw (anonymous) ssl (no) =================== ldap_initialize(ld,ldaps://santiago.connexer.com) ldap_set_option(LDAP_OPT_PROTOCOL_VERSION,0x03) ldap_simple_bind_s()=81 : Can't contact LDAP server Password: Sorry, try again. Password: sudo: 1 incorrect password attempt No joy. Next, we try from localadmin's account: [EMAIL PROTECTED]:~$ su - localadmin Password: [EMAIL PROTECTED]:~$ sudo ls -a LDAP Config Summary =================== uri ldaps://santiago.connexer.com ldap_version 3 sudoers_base ou=Sudoers,dc=connexer,dc=com binddn (anonymous) bindpw (anonymous) ssl (no) =================== ldap_initialize(ld,ldaps://santiago.connexer.com) ldap_set_option(LDAP_OPT_PROTOCOL_VERSION,0x03) ldap_simple_bind_s()=81 : Can't contact LDAP server . .alias .bash_logout .bashrc .lesshst .Xauthority .. .bash_history .bash_profile .cshrc .ssh [EMAIL PROTECTED]:~$ logout It works, but the ldap_bind is still causing trouble. Now, I have an ldaps URI, but it still claims that ssl is not on. I explicitly force it on by adding the line "ssl on" to /etc/ldap/ldap.conf. This is what we see now for both accounts: [EMAIL PROTECTED]:~$ sudo ls -a LDAP Config Summary =================== uri ldaps://santiago.connexer.com ldap_version 3 sudoers_base ou=Sudoers,dc=connexer,dc=com binddn (anonymous) bindpw (anonymous) ssl on =================== ldap_initialize(ld,ldaps://santiago.connexer.com) ldap_set_option(LDAP_OPT_PROTOCOL_VERSION,0x03) ldap_simple_bind_s()=81 : Can't contact LDAP server Password: Sorry, try again. Password: sudo: 1 incorrect password attempt [EMAIL PROTECTED]:~$ su - localadmin Password: [EMAIL PROTECTED]:~$ sudo -k LDAP Config Summary =================== uri ldaps://santiago.connexer.com ldap_version 3 sudoers_base ou=Sudoers,dc=connexer,dc=com binddn (anonymous) bindpw (anonymous) ssl on =================== ldap_initialize(ld,ldaps://santiago.connexer.com) ldap_set_option(LDAP_OPT_PROTOCOL_VERSION,0x03) ldap_simple_bind_s()=81 : Can't contact LDAP server [EMAIL PROTECTED]:~$ sudo ls -a LDAP Config Summary =================== uri ldaps://santiago.connexer.com ldap_version 3 sudoers_base ou=Sudoers,dc=connexer,dc=com binddn (anonymous) bindpw (anonymous) ssl on =================== ldap_initialize(ld,ldaps://santiago.connexer.com) ldap_set_option(LDAP_OPT_PROTOCOL_VERSION,0x03) ldap_simple_bind_s()=81 : Can't contact LDAP server Password: . .alias .bash_logout .bashrc .lesshst .Xauthority .. .bash_history .bash_profile .cshrc .ssh [EMAIL PROTECTED]:~$ So, it appears that nothing is really different here. It turns out that sudo's handling of TLS and SSL is somewhat broken (or brain dead). I applied the following patch to the sudo source package, rebuilt and installed the new package: ----------8<---------->8---------- --- sudo-1.6.8p12.orig/ldap.c +++ sudo-1.6.8p12/ldap.c @@ -565,6 +565,9 @@ if (!ldap_conf.port) ldap_conf.port=389; if (!ldap_conf.host) ldap_conf.host=estrdup("localhost"); + if (ldap_conf.ssl && !strcasecmp(ldap_conf.ssl, "on")) { + ldap_conf.tls_checkpeer = LDAP_OPT_X_TLS_NEVER; + } if (ldap_conf.debug>1) { printf("LDAP Config Summary\n"); @@ -821,6 +824,8 @@ /* Actually connect */ + if (ldap_conf.debug>1) fprintf(stderr, + "ldap_simple_bind(ld,%s,%d)\n",ldap_conf.binddn,ldap_conf.bindpw); rc=ldap_simple_bind_s(ld,ldap_conf.binddn,ldap_conf.bindpw); if(rc){ fprintf(stderr,"ldap_simple_bind_s()=%d : %s\n", ----------8<---------->8---------- Now, the check really needs to be smarter, so that the mere presence of a directive to use port 636 or a URI starting with ldaps:// will make it realize to use SSL instead of TLS. But this is a quick and dirty hack. Now, I have again removed the "ssl on" line from /etc/ldap/ldap.conf. Here is what it looks like now for the two accounts: [EMAIL PROTECTED]:~$ sudo ls -a LDAP Config Summary =================== uri ldaps://santiago.connexer.com ldap_version 3 sudoers_base ou=Sudoers,dc=connexer,dc=com binddn (anonymous) bindpw (anonymous) ssl (no) =================== ldap_initialize(ld,ldaps://santiago.connexer.com) ldap_set_option(LDAP_OPT_PROTOCOL_VERSION,0x03) ldap_simple_bind(ld,(null),0) ldap_simple_bind_s()=81 : Can't contact LDAP server Password: Sorry, try again. Password: sudo: 1 incorrect password attempt [EMAIL PROTECTED]:~$ su - localadmin Password: [EMAIL PROTECTED]:~$ sudo -k LDAP Config Summary =================== uri ldaps://santiago.connexer.com ldap_version 3 sudoers_base ou=Sudoers,dc=connexer,dc=com binddn (anonymous) bindpw (anonymous) ssl (no) =================== ldap_initialize(ld,ldaps://santiago.connexer.com) ldap_set_option(LDAP_OPT_PROTOCOL_VERSION,0x03) ldap_simple_bind(ld,(null),0) ldap_simple_bind_s()=81 : Can't contact LDAP server [EMAIL PROTECTED]:~$ sudo ls -a LDAP Config Summary =================== uri ldaps://santiago.connexer.com ldap_version 3 sudoers_base ou=Sudoers,dc=connexer,dc=com binddn (anonymous) bindpw (anonymous) ssl (no) =================== ldap_initialize(ld,ldaps://santiago.connexer.com) ldap_set_option(LDAP_OPT_PROTOCOL_VERSION,0x03) ldap_simple_bind(ld,(null),0) ldap_simple_bind_s()=81 : Can't contact LDAP server Password: . .alias .bash_logout .bashrc .lesshst .Xauthority .. .bash_history .bash_profile .cshrc .ssh [EMAIL PROTECTED]:~$ Looks exactly the same as before. roberto can't do anything and localadmin succeeds, but gets an ldap_bind() warning. Now, we add the "ssl on" line back into /etc/ldap/ldap.conf: [EMAIL PROTECTED]:~$ sudo ls -a LDAP Config Summary =================== uri ldaps://santiago.connexer.com ldap_version 3 sudoers_base ou=Sudoers,dc=connexer,dc=com binddn (anonymous) bindpw (anonymous) ssl on =================== ldap_set_option(LDAP_OPT_X_TLS_REQUIRE_CERT,0x00) ldap_initialize(ld,ldaps://santiago.connexer.com) ldap_set_option(LDAP_OPT_PROTOCOL_VERSION,0x03) ldap_simple_bind(ld,(null),0) ldap_simple_bind_s()=81 : Can't contact LDAP server Password: Sorry, try again. Password: sudo: 1 incorrect password attempt [EMAIL PROTECTED]:~$ su - localadmin Password: [EMAIL PROTECTED]:~$ sudo -k LDAP Config Summary =================== uri ldaps://santiago.connexer.com ldap_version 3 sudoers_base ou=Sudoers,dc=connexer,dc=com binddn (anonymous) bindpw (anonymous) ssl on =================== ldap_set_option(LDAP_OPT_X_TLS_REQUIRE_CERT,0x00) ldap_initialize(ld,ldaps://santiago.connexer.com) ldap_set_option(LDAP_OPT_PROTOCOL_VERSION,0x03) ldap_simple_bind(ld,(null),0) ldap_bind() ok found:cn=defaults,ou=Sudoers,dc=connexer,dc=com ldap search '(|(sudoUser=localadmin)(sudoUser=%localadmin)(sudoUser=%localadmin)(sudoUser=ALL))' ldap search 'sudoUser=+*' user_matches=0 host_matches=0 sudo_ldap_check(-1)=0x44 [EMAIL PROTECTED]:~$ sudo ls -a LDAP Config Summary =================== uri ldaps://santiago.connexer.com ldap_version 3 sudoers_base ou=Sudoers,dc=connexer,dc=com binddn (anonymous) bindpw (anonymous) ssl on =================== ldap_set_option(LDAP_OPT_X_TLS_REQUIRE_CERT,0x00) ldap_initialize(ld,ldaps://santiago.connexer.com) ldap_set_option(LDAP_OPT_PROTOCOL_VERSION,0x03) ldap_simple_bind(ld,(null),0) ldap_bind() ok found:cn=defaults,ou=Sudoers,dc=connexer,dc=com ldap search '(|(sudoUser=localadmin)(sudoUser=%localadmin)(sudoUser=%localadmin)(sudoUser=ALL))' ldap search 'sudoUser=+*' user_matches=0 host_matches=0 sudo_ldap_check(0)=0x44 Password: . .alias .bash_logout .bashrc .lesshst .Xauthority .. .bash_history .bash_profile .cshrc .ssh [EMAIL PROTECTED]:~$ Now things get interesting. roberto still can't get anything, but when localadmin tries to use sudo, his bind succeeds and sudo is able to query the LDAP server. Now, the strange thing is that if I add a local account for roberto to /etc/passwd and /etc/shadow (with the same uid and gid as is present in LDAP), then it works the same way for him. Now, according to the LDAP documentation for sudo, it doesn't use nsswitch at all. But I am wondering if there might be some hidden interaction there. Either way, there is something about having a local account that makes it able to bind to the LDAP server that otherwise causes it fail. Naturally, this makes things less desirable, since the point of LDAP is to not have to create local accounts. Of course, if I add the ignore_local_sudoers option in LDAP, then nobody can do anything. I have carefully looked through the source code to see if I can figure out what is going on. But as far as I can tell, everything important to this is happening in sudo_ldap_check() in ldap.c, which is called only one time from within sudo.c. I can't find anything that implies that there is some sort of additional check or another call being made that might cause it to pull in a local account without an LDAP account. There are a couple of calls to getuid() and while I am not a C library guru, my understanding is to the calling application that function transperently queries all the sources of account data available to the system. Hopefully someone can make a bit more sense of this. Regards, -Roberto -- Roberto C. Sánchez http://people.connexer.com/~roberto http://www.connexer.com
signature.asc
Description: Digital signature