Bug 153263 - IPv6 enabled OpenLDAP causes strange IPv6 lookups during getpeername call
IPv6 enabled OpenLDAP causes strange IPv6 lookups during getpeername call
Status: CLOSED WONTFIX
Product: Red Hat Enterprise Linux 3
Classification: Red Hat
Component: openldap (Show other bugs)
3.0
All Linux
medium Severity medium
: ---
: ---
Assigned To: Jan Safranek
Jay Turner
:
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2005-04-04 05:03 EDT by Peter Bieringer
Modified: 2015-01-07 19:09 EST (History)
2 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2007-10-19 15:05:27 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)
strace of IPv6 ldapsearch on RHEL3U4 (19.69 KB, text/plain)
2005-04-04 05:08 EDT, Peter Bieringer
no flags Details
strace of IPv6 ldapsearch on RHEL4 (14.06 KB, text/plain)
2005-04-04 05:09 EDT, Peter Bieringer
no flags Details
Patch to fix buggy sockaddr usage (1.49 KB, patch)
2005-04-04 08:58 EDT, Peter Bieringer
no flags Details | Diff
Fixed patch (1.49 KB, patch)
2005-04-04 12:01 EDT, Peter Bieringer
no flags Details | Diff

  None (edit)
Description Peter Bieringer 2005-04-04 05:03:57 EDT
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?
Comment 1 Peter Bieringer 2005-04-04 05:08:19 EDT
Created attachment 112643 [details]
strace of IPv6 ldapsearch on RHEL3U4
Comment 2 Peter Bieringer 2005-04-04 05:09:02 EDT
Created attachment 112644 [details]
strace of IPv6 ldapsearch on RHEL4
Comment 3 Pekka Savola 2005-04-04 05:14:33 EDT
I guess (without looking at the code) that maybe the sockaddr structures aren't
properly zeroed out when initialized.
Comment 4 Peter Bieringer 2005-04-04 05:16:52 EDT
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...
Comment 5 Michael Tokarev 2005-04-04 05:27:15 EDT
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.
Comment 6 Peter Bieringer 2005-04-04 05:57:50 EDT
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@bieringer.de 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.
Comment 7 Peter Bieringer 2005-04-04 08:40:10 EDT
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?

Comment 8 Peter Bieringer 2005-04-04 08:58:33 EDT
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.
Comment 9 Peter Bieringer 2005-04-04 12:01:03 EDT
Created attachment 112657 [details]
Fixed patch

Fixed patch, forgot one minor but important ptr/addr switch
Comment 11 Peter Bieringer 2005-04-05 10:02:53 EDT
I would only note that I have now installed this on my productive system...

before:
# postmap -q peter@bieringer.de ldap:/etc/postfix/ldap-test.cf
Segmentation fault

after:
# postmap -q peter@bieringer.de ldap:/etc/postfix/ldap-test.cf
peter

That's ok. Pls. push this fix forward.
Comment 12 Peter Bieringer 2005-10-17 11:11:10 EDT
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.
Comment 13 RHEL Product and Program Management 2007-10-19 15:05:27 EDT
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.

Note You need to log in before you can comment on or make changes to this bug.