Bug 153263 - IPv6 enabled OpenLDAP causes strange IPv6 lookups during getpeername call
Summary: IPv6 enabled OpenLDAP causes strange IPv6 lookups during getpeername call
Keywords:
Status: CLOSED WONTFIX
Alias: None
Product: Red Hat Enterprise Linux 3
Classification: Red Hat
Component: openldap
Version: 3.0
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Jan Safranek
QA Contact: Jay Turner
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2005-04-04 09:03 UTC by Peter Bieringer
Modified: 2015-01-08 00:09 UTC (History)
2 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2007-10-19 19:05:27 UTC
Target Upstream Version:
Embargoed:


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

Description Peter Bieringer 2005-04-04 09:03:57 UTC
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 09:08:19 UTC
Created attachment 112643 [details]
strace of IPv6 ldapsearch on RHEL3U4

Comment 2 Peter Bieringer 2005-04-04 09:09:02 UTC
Created attachment 112644 [details]
strace of IPv6 ldapsearch on RHEL4

Comment 3 Pekka Savola 2005-04-04 09:14:33 UTC
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 09:16:52 UTC
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 09:27:15 UTC
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 09:57:50 UTC
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.

Comment 7 Peter Bieringer 2005-04-04 12:40:10 UTC
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 12:58:33 UTC
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 16:01:03 UTC
Created attachment 112657 [details]
Fixed patch

Fixed patch, forgot one minor but important ptr/addr switch

Comment 11 Peter Bieringer 2005-04-05 14:02:53 UTC
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.


Comment 12 Peter Bieringer 2005-10-17 15:11:10 UTC
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 Program Management 2007-10-19 19:05:27 UTC
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.