[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
Re: libldap: too little space allocated for IPv6 address *patch* (ITS#2018)
Thanks, fixed in HEAD, please test.
Kurt
At 12:55 PM 2002-08-09, thorild@Update.UU.SE wrote:
>Full_Name: Thorild Selén
>Version: 2.0.23 and HEAD
>OS: Linux 2.4.19 (Debian)
>URL:
>Submission from: (NULL) (130.238.19.17)
>
>
>(In brief: IPv6 address allocation problem; patch at end)
>
>I was using strace to examine a program that kept hanging, and saw:
>
>> connect(10, {sin_family=AF_INET6, sin6_port=htons(389),
>> inet_pton(AF_INET6, "3ffe:200:66:8000::11", &sin6_addr),
>> sin6_flowinfo=0 , sin6_scope_id=0}, 28) = -1 EINPROGRESS (Operation
>> now in progress)
>> select(1024, NULL, [10], NULL, {16, 0}) = 1 (out [10], left {16, 0})
>
>(We connect to the LDAP server. All is well so far. From the data that follows,
>this looks like libnss_ldap checking which groups exist on the system.)
>And then:
>
>> getpeername(10, {sin_family=AF_INET6, sin6_port=htons(389),
>> inet_pton(AF_INET6, "3ffe:200:66:8000:1cd3:ffbf:ac7c:5940",
>> &sin6_addr), sin6_flowinfo=0, sin6_scope_id=137790328}, [28]) = 0
>> fcntl64(10, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK)
>> fcntl64(10, F_SETFL, O_RDWR) = 0
>> getpeername(10, {sin_family=AF_INET6, sin6_port=htons(389),
>> inet_pton(AF_INET6, "3ffe:200:66:8000:2cd4:ffbf:af7a:5840",
>> &sin6_addr), sin6_flowinfo=0, sin6_scope_id=139343664}, [28]) = 0
>
>The second parts of these addresses are mangled; something isn't allocating
>enough space to store an IPv6 address. That made me look in the libldap
>source for a bug of this kind, and saw that in libraries/libldap/os-ip.c,
>in ldap_host_connected_to, an auto struct sockaddr is used to store an
>address; possibly an IPv6 address, which won't fit; a struct
>sockaddr_storage should be used instead (see RFC 2553). This bug is present
>in this version as well as in the present working version (HEAD).
>
>Below is a patch for HEAD.
>
>/Thorild
>
>
>Patch copyright 2002 Thorild Selén, all rights reserved.
>Contains code copyright 1999-2001 the OpenLDAP Foundation,
> Redwood City, California, USA.
>This is free software; you can redistribute and use it
>under the same terms as OpenLDAP itself.
>
>=========================================================
>
>
>diff -Naur ldap/libraries/libldap/os-ip.c ldap-new/libraries/libldap/os-ip.c
>--- ldap/libraries/libldap/os-ip.c Sun Jul 28 03:30:39 2002
>+++ ldap-new/libraries/libldap/os-ip.c Fri Aug 9 17:50:51 2002
>@@ -1,4 +1,4 @@
>-/* $OpenLDAP: pkg/ldap/libraries/libldap/os-ip.c,v 1.79 2002/07/28 03:30:39
>kurt Exp $ */
>+/* $OpenLDAP: /libraries/libldap/os-ip.c,v 1.72.2.4 2002/07/28 19:10:46 kurt
>Exp $ */
> /*
> * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
> * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
>@@ -482,7 +482,13 @@
> {
> struct hostent *hp;
> socklen_t len;
>- struct sockaddr sa;
>+#ifdef LDAP_PF_INET6
>+ struct sockaddr_storage sa_storage;
>+#else
>+ struct sockaddr sa_storage;
>+#endif
>+ struct sockaddr *sa = (struct sockaddr *) &sa_storage;
>+
> char *addr;
> char *host;
>
>@@ -492,11 +498,11 @@
> char *ha_buf=NULL;
> ber_socket_t sd;
>
>- (void)memset( (char *)&sa, '\0', sizeof( struct sockaddr ));
>- len = sizeof( sa );
>+ (void)memset( (char *)&sa_storage, '\0', sizeof( sa_storage ));
>+ len = sizeof( sa_storage );
>
> ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd );
>- if ( getpeername( sd, &sa, &len ) == -1 ) {
>+ if ( getpeername( sd, sa, &len ) == -1 ) {
> return( NULL );
> }
>
>@@ -506,19 +512,19 @@
> * hostname is used as the kerberos instance.
> */
>
>- switch (sa.sa_family) {
>+ switch (sa->sa_family) {
> #ifdef LDAP_PF_LOCAL
> case AF_LOCAL:
> return LDAP_STRDUP( ldap_int_hostname );
> #endif
> #ifdef LDAP_PF_INET6
> case AF_INET6:
>- addr = (char *) &((struct sockaddr_in6 *)&sa)->sin6_addr;
>+ addr = (char *) &((struct sockaddr_in6 *)sa)->sin6_addr;
> len = sizeof( struct in6_addr );
> break;
> #endif
> case AF_INET:
>- addr = (char *) &((struct sockaddr_in *)&sa)->sin_addr;
>+ addr = (char *) &((struct sockaddr_in *)sa)->sin_addr;
> len = sizeof( struct in_addr );
>
> {
>@@ -526,7 +532,7 @@
> localhost.sin_addr.s_addr = htonl( INADDR_ANY );
>
> if( memcmp ( &localhost.sin_addr,
>- &((struct sockaddr_in *)&sa)->sin_addr,
>+ &((struct sockaddr_in *)sa)->sin_addr,
> sizeof(localhost.sin_addr) ) == 0 )
> {
> return LDAP_STRDUP( ldap_int_hostname );
>@@ -536,7 +542,7 @@
> localhost.sin_addr.s_addr = htonl( INADDR_LOOPBACK );
>
> if( memcmp ( &localhost.sin_addr,
>- &((struct sockaddr_in *)&sa)->sin_addr,
>+ &((struct sockaddr_in *)sa)->sin_addr,
> sizeof(localhost.sin_addr) ) == 0 )
> {
> return LDAP_STRDUP( ldap_int_hostname );
>@@ -552,7 +558,7 @@
>
> host = NULL;
> if ((ldap_pvt_gethostbyaddr_a( addr, len,
>- sa.sa_family, &he_buf, &ha_buf,
>+ sa->sa_family, &he_buf, &ha_buf,
> &hp,&local_h_errno ) == 0 ) &&
> (hp != NULL) && ( hp->h_name != NULL ) )
> {