From Bugzilla Helper: User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.7.6) Gecko/20050321 Firefox/1.0.2 Description of problem: During tracking down of strange IPv6 PTR requests found in tcpdump session on an RHEL3U4 system with IPv6 enabled OpenLDAP and IPv6 enabled postfix-2.2.1 the result is that the openldap client causes such strange requests, because getpeername was called with a strange IPv6 address. Version-Release number of selected component (if applicable): openldap-2.0.27-17 How reproducible: Always Steps to Reproduce: 0. enable IPv6 on system 1. fresh install of openldap (base, server, client) 2. enable IPv6 by # cat /etc/sysconfig/ldap SLAPD_OPTIONS="-h 'ldap://127.0.0.1/ ldap://[::1]/'" 3. start openlap # service ldap start 4. run ldapsearch, e.g. # strace ldapsearch -x -h ::1 Actual Results: The very interesting part is shown here: connect(3, {sa_family=AF_INET6, sin6_port=htons(389), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINPROGRESS (Operation now in progress) select(1024, NULL, [3], NULL, NULL) = 1 (out [3]) getpeername(3, {sa_family=AF_INET6, sin6_port=htons(389), inet_pton(AF_INET6, "::890:ffbf:53:c000", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=3221196648}, [28]) = 0 fcntl64(3, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK) fcntl64(3, F_SETFL, O_RDWR) = 0 getpeername(3, {sa_family=AF_INET6, sin6_port=htons(389), inet_pton(AF_INET6, "::3891:ffbf:53:c000", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=9177489}, [28]) = 0 The big question is, what is generating the illegal IPv6 addresses: ::890:ffbf:53:c000 ::3891:ffbf:53:c000 Note that some nibbles are always equal while other bits are uniq (if tracked over time). Expected Results: Proper result like happen on RHEL4 (using openldap-2.2): Note that on RHEL4 you have to use "strace ldapsearch -x -h [::1]" to force LDAP query over IPv6. connect(3, {sa_family=AF_INET6, sin6_port=htons(389), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINPROGRESS (Operation now in progress) select(1024, NULL, [3], NULL, NULL) = 1 (out [3]) getpeername(3, {sa_family=AF_INET6, sin6_port=htons(389), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0 fcntl64(3, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK) Additional info: Thread on postfix-devel: http://archive.netbsd.se/?ml=postfix-devel&a=2005-03&m=790534 I've straced the slapd, here such strange address doesn't occur (ltracing slapd didn't work on my system). I believe it's a bug in the LDAP client code. Digging further and further I find the code where the problem must be located: High debugging of ldapsearch in combination with strace shows me connect(3, {sa_family=AF_INET6, sin6_port=htons(389), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINPROGRESS (Operation now in progress) select(1024, NULL, [3], NULL, NULL) = 1 (out [3]) write(2, "ldap_is_sock_ready: 3\n", 22ldap_is_sock_ready: 3 ) = 22 getpeername(3, {sa_family=AF_INET6, sin6_port=htons(389), inet_pton(AF_INET6, "::68a1:ffbf:93:d800", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=3221201096}, [28]) = 0 write(2, "ldap_ndelay_off: 3\n", 19ldap_ndelay_off: 3 ) = 19 Bingo, 2 getpeername calls found in: libraries/libldap/os-ip.c static int ldap_pvt_is_socket_ready(LDAP *ld, int s) ... if ( getpeername( s, (struct sockaddr *) &sin, &dummy ) == AC_SOCKET_ERROR ) { ... char * ldap_host_connected_to( Sockbuf *sb ) ... if ( getpeername( sd, &sa, &len ) == -1 ) { return( NULL ); } ... Can one check whether one of these calls aren't proper coded?
Created attachment 112643 [details] strace of IPv6 ldapsearch on RHEL3U4
Created attachment 112644 [details] strace of IPv6 ldapsearch on RHEL4
I guess (without looking at the code) that maybe the sockaddr structures aren't properly zeroed out when initialized.
Yes, this one: static int ldap_pvt_is_socket_ready(LDAP *ld, int s) ... /* error slippery */ struct sockaddr_in sin; char ch; int dummy = sizeof(sin); if ( getpeername( s, (struct sockaddr *) &sin, &dummy ) == AC_SOCKET_ERROR ) { /* XXX: needs to be replace with ber_stream_read() */ read(s, &ch, 1); TRACE; return -1; } return 0; No wonder, "sin" is undefined...strange lookups are triggered...strange function at all...
It isn't because sin is "undefined" (ie, not zeroed), but because it is of improper type: it should be sockaddr_storage or sockaddr_in6, but not sockaddr_in - the latter can not be used with IPv6.
BTW: IPv6 enabled postfix (postmap) is segfaulting if system is IPv6 enabled and openldap is listening on :: or 127.0.0.1 short after the second getpeername call: cat ldap-test.conf # LDAP server #server_host = 127.0.0.1 #server_host = ::ffff:127.0.0.1 server_host = [::1] # LDAP search base search_base = dc=domain,dc=example # LDAP query filter query_filter = (&(mail=%s)(objectClass=CourierMailAccount)) # LDAP result attribute result_attribute = uid # LDAP result filter result_filter = OK # Need no bind for upper query bind = no # strace postmap -q peter ldap:ldap-test.conf ... connect(4, {sa_family=AF_INET, sin_port=htons(389), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress) select(1024, NULL, [4], NULL, {10, 0}) = 1 (out [4], left {10, 0}) getpeername(4, {sa_family=AF_INET, sin_port=htons(389), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0 fcntl64(4, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK) fcntl64(4, F_SETFL, O_RDWR) = 0 getpeername(4, {sa_family=AF_INET, sin_port=htons(389), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0 --- SIGSEGV (Segmentation fault) @ 0 (0) --- +++ killed by SIGSEGV +++ Note that postfix on my test system is IPv6 enabled but not turned on, therefore the IPv4 fallback. But on my real-life system postfix is IPv6 turned on, here postfix segfaults if server_host = 127.0.0.1 I can only use server_host = [::1] -> Note here that from remote I can sucessfully connect from an RHEL4 system (with openldap 2.2) So I believe if a RHEL3 system is IPv6 enabled and installed LDAP server is turned on, it can happen that IPv4 connects to LDAP server will cause a segfault.
Note that the strange getpeername occurs 2 times, the first one I am able to fix with following patch: --- openldap-2.0.27/libraries/libldap/os-ip.c.orig 2005-04-04 10:18:46.000000000 -0400 +++ openldap-2.0.27/libraries/libldap/os-ip.c 2005-04-04 10:19:05.000000000 -0400 @@ -168,7 +168,7 @@ #else { /* error slippery */ - struct sockaddr_in sin; + struct sockaddr_storage sin; char ch; int dummy = sizeof(sin); if ( getpeername( s, (struct sockaddr *) &sin, &dummy ) The second one is in function: ldap_host_connected_to ... struct sockaddr sa; if ( getpeername( sd, &sa, &len ) == -1 ) { return( NULL ); } How to fix this proper for IPv4 and IPv6? I can't replace it by sockaddr_storage because of a missig member in structure: libraries/libldap/os-ip.c: In function `ldap_host_connected_to': libraries/libldap/os-ip.c:464: warning: passing arg 2 of `getpeername' from incompatible pointer type libraries/libldap/os-ip.c:475: structure has no member named `sa_family' libraries/libldap/os-ip.c:521: structure has no member named `sa_family' Can I use sockaddr_in6, is this IPv4 safe?
Created attachment 112648 [details] Patch to fix buggy sockaddr usage Solved 2nd issue by looking into source code of 2.1.30, where fixes already made. Tststs, looks like 2.0.27 never hit IPv6-ready status, but nobody warns... BTW: after installing the fixed library, upper shown postmap execution no longer segfaults, too.
Created attachment 112657 [details] Fixed patch Fixed patch, forgot one minor but important ptr/addr switch
I would only note that I have now installed this on my productive system... before: # postmap -q peter ldap:/etc/postfix/ldap-test.cf Segmentation fault after: # postmap -q peter ldap:/etc/postfix/ldap-test.cf peter That's ok. Pls. push this fix forward.
Unfortunately, this patch was not included in https://rhn.redhat.com/errata/RHSA-2005-751.html and therefore openldap-2.0.27-20.src.rpm has at least the same segfault bug.
This bug is filed against RHEL 3, which is in maintenance phase. During the maintenance phase, only security errata and select mission critical bug fixes will be released for enterprise products. Since this bug does not meet that criteria, it is now being closed. For more information of the RHEL errata support policy, please visit: http://www.redhat.com/security/updates/errata/ If you feel this bug is indeed mission critical, please contact your support representative. You may be asked to provide detailed information on how this bug is affecting you.