diff --git a/CHANGES b/CHANGES index 7b198525f9f699681cebe23d9542320a9c9b3ff2..0ce6e70359ed51f90f3e8a5b42a449ab0da9c0f8 100644 --- a/CHANGES +++ b/CHANGES @@ -1,12 +1,15 @@ OpenLDAP 2.1 Change Log -OpenLDAP 2.1.9 Engineering +OpenLDAP 2.1.9 Release Fixed back-bdb moddn newSuperior bug Fixed back-ldap/meta modify bug (ITS#2158) Fixed back-glue segv bug (ITS#2214) + Fixed back-monitor subordinate database bug Fixed libldap try_read1msg drain bug (ITS#2153) Fixed libldap SASL bugs (ITS#2184) Fixed libldap referral bug (ITS#2187) + Fixed libldap getaddrinfo threading bug (ITS#2221) + Fixed libldif empty value bugs (ITS#2218) Added slapd allow update_anon feature (ITS#2155) Added slapd authz stats logging feature (ITS#2165) Fixed slapd unix socket unlink bug (ITS#2157) @@ -16,6 +19,8 @@ OpenLDAP 2.1.9 Engineering Fixed slapd multimaster passwd bug (ITS#2176) Fixed slapd bad acl DN bug (ITS#2196) Fixed slapd SASL bugs (ITS#2200) (ITS#2202) + Fixed slapd language range option bug + Fixed slapd new logging bugs Removed lint Build Environment Add subordinate referral test diff --git a/build/version.sh b/build/version.sh index a0d7a02b1a59fa3f6e75fc7281ac1f9755bf752e..11ef7736a142829102b5ba661de7b4187e27c9d4 100755 --- a/build/version.sh +++ b/build/version.sh @@ -7,9 +7,9 @@ ol_package=OpenLDAP ol_major=2 ol_minor=1 -ol_patch=X -ol_api_inc=20108 -ol_api_lib=2:108:0 +ol_patch=9 +ol_api_inc=20109 +ol_api_lib=2:109:0 if test $ol_patch != X ; then ol_version=${ol_major}.${ol_minor}.${ol_patch} diff --git a/doc/devel/todo b/doc/devel/todo index 3454f063052293ba3438d6e4c2cc85d73a5a74a6..8aacd8abf3a0ad538b18100bcaffe66d5a9cd6a0 100644 --- a/doc/devel/todo +++ b/doc/devel/todo @@ -41,7 +41,6 @@ Implement authPassword (RFC 3112) Implement DIT Structure Rules and Name Forms Implement LDAP Cancel extension Implement LDAP Transactions extension -Implement Proxy Authorization Control extension Redesign slapd memory allocation fault handling Localize tools diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h index b0c2bd93614cfe0bdbe4c161d74212f5a16be2c6..897569b59980b3453a286cde634f0cf9015dc579 100644 --- a/libraries/libldap/ldap-int.h +++ b/libraries/libldap/ldap-int.h @@ -315,9 +315,7 @@ struct ldap { #define LDAP_VALID(ld) ( (ld)->ld_valid == LDAP_VALID_SESSION ) #ifdef LDAP_R_COMPILE -#ifdef HAVE_RES_QUERY LDAP_V ( ldap_pvt_thread_mutex_t ) ldap_int_resolv_mutex; -#endif #ifdef HAVE_CYRUS_SASL LDAP_V( ldap_pvt_thread_mutex_t ) ldap_int_sasl_mutex; diff --git a/libraries/libldap/os-ip.c b/libraries/libldap/os-ip.c index 5e4391178a735f74eecbd35d969ee034c4fe966d..4854e5c75e640c4ea7ef530d8514165cb91e702e 100644 --- a/libraries/libldap/os-ip.c +++ b/libraries/libldap/os-ip.c @@ -357,7 +357,19 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, hints.ai_socktype = socktype; snprintf(serv, sizeof serv, "%d", port ); - if ( ( err = getaddrinfo(host, serv, &hints, &res) ) ) { + +#ifdef LDAP_R_COMPILE + /* most getaddrinfo(3) use non-threadsafe resolver libraries */ + ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex); +#endif + + err = getaddrinfo( host, serv, &hints, &res ); + +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex); +#endif + + if ( err != 0 ) { osip_debug(ld, "ldap_connect_to_host: getaddrinfo failed: %s\n", AC_GAI_STRERROR(err), 0, 0); return -1; diff --git a/libraries/libldap/util-int.c b/libraries/libldap/util-int.c new file mode 100644 index 0000000000000000000000000000000000000000..649394741eb53ce14cfb7c729062ff4894793596 --- /dev/null +++ b/libraries/libldap/util-int.c @@ -0,0 +1,444 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* + * util-int.c Various functions to replace missing threadsafe ones. + * Without the real *_r funcs, things will + * work, but might not be threadsafe. + * + * Written by Bart Hartgers. + * + * Copyright 1998, A. Hartgers, All rights reserved. + * This software is not subject to any license of Eindhoven University of + * Technology, since it was written in my spare time. + * + * Redistribution and use in source and binary forms are permitted only + * as authorized by the OpenLDAP Public License. A copy of this + * license is available at http://www.OpenLDAP.org/license.html or + * in file LICENSE in the top-level directory of the distribution. + */ + + +#include "portable.h" + +#include <ac/stdlib.h> + +#include <ac/errno.h> +#include <ac/socket.h> +#include <ac/string.h> +#include <ac/time.h> +#include <ac/unistd.h> + +#include "ldap-int.h" + +#if defined( LDAP_R_COMPILE ) +# include <ldap_pvt_thread.h> +#else +# undef HAVE_REENTRANT_FUNCTIONS +#endif + +#if (defined( HAVE_CTIME_R ) || defined( HAVE_REENTRANT_FUNCTIONS)) \ + && defined( CTIME_R_NARGS ) +# define USE_CTIME_R +#endif + +#if defined(HAVE_GETHOSTBYNAME_R) && \ + (GETHOSTBYNAME_R_NARGS > 6 || GETHOSTBYNAME_R_NARGS < 5) + /* Don't know how to handle this version, pretend it's not there */ +# undef HAVE_GETHOSTBYNAME_R +#endif +#if defined(HAVE_GETHOSTBYADDR_R) && \ + (GETHOSTBYADDR_R_NARGS > 8 || GETHOSTBYADDR_R_NARGS < 7) + /* Don't know how to handle this version, pretend it's not there */ +# undef HAVE_GETHOSTBYADDR_R +#endif + +#ifdef LDAP_R_COMPILE +# ifndef USE_CTIME_R + static ldap_pvt_thread_mutex_t ldap_int_ctime_mutex; +# endif +# ifdef HAVE_RES_QUERY + ldap_pvt_thread_mutex_t ldap_int_resolv_mutex; +# endif +#endif /* LDAP_R_COMPILE */ + +char *ldap_pvt_ctime( const time_t *tp, char *buf ) +{ +#ifdef USE_CTIME_R +# if (CTIME_R_NARGS > 3) || (CTIME_R_NARGS < 2) +# error "CTIME_R_NARGS should be 2 or 3" +# elif CTIME_R_NARGS > 2 && defined(CTIME_R_RETURNS_INT) + return( ctime_r(tp,buf,26) < 0 ? 0 : buf ); +# elif CTIME_R_NARGS > 2 + return ctime_r(tp,buf,26); +# else + return ctime_r(tp,buf); +# endif + +#else +# ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_lock( &ldap_int_ctime_mutex ); +# endif + AC_MEMCPY( buf, ctime(tp), 26 ); +# ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_unlock( &ldap_int_ctime_mutex ); +# endif + return buf; +#endif +} + +#define BUFSTART (1024-32) +#define BUFMAX (32*1024-32) + +static char *safe_realloc( char **buf, int len ); + +#if !defined(HAVE_GETHOSTBYNAME_R) && defined(LDAP_R_COMPILE) +static int copy_hostent( struct hostent *res, char **buf, struct hostent * src ); +#endif + +int ldap_pvt_gethostbyname_a( + const char *name, + struct hostent *resbuf, + char **buf, + struct hostent **result, + int *herrno_ptr ) +{ +#if defined( HAVE_GETHOSTBYNAME_R ) + +# define NEED_SAFE_REALLOC 1 + int r=-1; + int buflen=BUFSTART; + *buf = NULL; + for(;buflen<BUFMAX;) { + if (safe_realloc( buf, buflen )==NULL) + return r; + +#if (GETHOSTBYNAME_R_NARGS < 6) + r = ((*result=gethostbyname_r( name, resbuf, *buf, + buflen, herrno_ptr ))== NULL) ? + -1 : 0; +#else + r = gethostbyname_r( name, resbuf, *buf, + buflen, result, herrno_ptr ); +#endif + + Debug( LDAP_DEBUG_TRACE, "ldap_pvt_gethostbyname_a: host=%s, r=%d\n", + name, r, 0 ); + +#ifdef NETDB_INTERNAL + if ((r<0) && + (*herrno_ptr==NETDB_INTERNAL) && + (errno==ERANGE)) + { + buflen*=2; + continue; + } +#endif + return r; + } + return -1; +#elif defined( LDAP_R_COMPILE ) +# define NEED_COPY_HOSTENT + struct hostent *he; + int retval; + *buf = NULL; + + ldap_pvt_thread_mutex_lock( &ldap_int_resolv_mutex ); + + he = gethostbyname( name ); + + if (he==NULL) { + *herrno_ptr = h_errno; + retval = -1; + } else if (copy_hostent( resbuf, buf, he )<0) { + *herrno_ptr = -1; + retval = -1; + } else { + *result = resbuf; + retval = 0; + } + + ldap_pvt_thread_mutex_unlock( &ldap_int_resolv_mutex ); + + return retval; +#else + *buf = NULL; + *result = gethostbyname( name ); + + if (*result!=NULL) { + return 0; + } + + *herrno_ptr = h_errno; + + return -1; +#endif +} + +int ldap_pvt_gethostbyaddr_a( + const char *addr, + int len, + int type, + struct hostent *resbuf, + char **buf, + struct hostent **result, + int *herrno_ptr ) +{ +#if defined( HAVE_GETHOSTBYADDR_R ) + +# undef NEED_SAFE_REALLOC +# define NEED_SAFE_REALLOC + int r=-1; + int buflen=BUFSTART; + *buf = NULL; + for(;buflen<BUFMAX;) { + if (safe_realloc( buf, buflen )==NULL) + return r; +#if (GETHOSTBYADDR_R_NARGS < 8) + r = ((*result=gethostbyaddr_r( addr, len, type, + resbuf, *buf, buflen, + herrno_ptr )) == NULL) ? + -1 : 0; +#else + r = gethostbyaddr_r( addr, len, type, + resbuf, *buf, buflen, + result, herrno_ptr ); +#endif + +#ifdef NETDB_INTERNAL + if ((r<0) && + (*herrno_ptr==NETDB_INTERNAL) && + (errno==ERANGE)) + { + buflen*=2; + continue; + } +#endif + return r; + } + return -1; +#elif defined( LDAP_R_COMPILE ) +# undef NEED_COPY_HOSTENT +# define NEED_COPY_HOSTENT + struct hostent *he; + int retval; + *buf = NULL; + + ldap_pvt_thread_mutex_lock( &ldap_int_resolv_mutex ); + + he = gethostbyaddr( addr, len, type ); + + if (he==NULL) { + *herrno_ptr = h_errno; + retval = -1; + } else if (copy_hostent( resbuf, buf, he )<0) { + *herrno_ptr = -1; + retval = -1; + } else { + *result = resbuf; + retval = 0; + } + + ldap_pvt_thread_mutex_unlock( &ldap_int_resolv_mutex ); + + return retval; +#else /* gethostbyaddr() */ + *buf = NULL; + *result = gethostbyaddr( addr, len, type ); + + if (*result!=NULL) { + return 0; + } + return -1; +#endif +} +/* + * ldap_int_utils_init() should be called before any other function. + */ + +void ldap_int_utils_init( void ) +{ + static int done=0; + if (done) + return; + done=1; + +#ifdef LDAP_R_COMPILE + +#if !defined( USE_CTIME_R ) && !defined( HAVE_REENTRANT_FUNCTIONS ) + ldap_pvt_thread_mutex_init( &ldap_int_ctime_mutex ); +#endif + +#ifdef HAVE_RES_QUERY + ldap_pvt_thread_mutex_init( &ldap_int_resolv_mutex ); +#endif + + /* call other module init functions here... */ +#endif +} + +#if defined( NEED_COPY_HOSTENT ) +# undef NEED_SAFE_REALLOC +#define NEED_SAFE_REALLOC + +static char *cpy_aliases( char ***tgtio, char *buf, char **src ) +{ + int len; + char **tgt=*tgtio; + for( ; (*src) ; src++ ) { + len = strlen( *src ) + 1; + AC_MEMCPY( buf, *src, len ); + *tgt++=buf; + buf+=len; + } + *tgtio=tgt; + return buf; +} + +static char *cpy_addresses( char ***tgtio, char *buf, char **src, int len ) +{ + char **tgt=*tgtio; + for( ; (*src) ; src++ ) { + AC_MEMCPY( buf, *src, len ); + *tgt++=buf; + buf+=len; + } + *tgtio=tgt; + return buf; +} + +static int copy_hostent( struct hostent *res, char **buf, struct hostent * src ) +{ + char **p; + char **tp; + char *tbuf; + int name_len; + int n_alias=0; + int total_alias_len=0; + int n_addr=0; + int total_addr_len; + int total_len; + + /* calculate the size needed for the buffer */ + name_len = strlen( src->h_name ) + 1; + + if( src->h_aliases != NULL ) { + for( p = src->h_aliases; (*p) != NULL; p++ ) { + total_alias_len += strlen( *p ) + 1; + n_alias++; + } + } + + if( src->h_addr_list != NULL ) { + for( p = src->h_addr_list; (*p) != NULL; p++ ) { + n_addr++; + } + total_addr_len = n_addr * src->h_length; + } + + total_len = (n_alias + n_addr + 2) * sizeof( char * ) + + total_addr_len + total_alias_len + name_len; + + if (safe_realloc( buf, total_len )) { + tp = (char **) *buf; + tbuf = *buf + (n_alias + n_addr + 2) * sizeof( char * ); + AC_MEMCPY( res, src, sizeof( struct hostent ) ); + /* first the name... */ + AC_MEMCPY( tbuf, src->h_name, name_len ); + res->h_name = tbuf; tbuf+=name_len; + /* now the aliases */ + res->h_aliases = tp; + if ( src->h_aliases != NULL ) { + tbuf = cpy_aliases( &tp, tbuf, src->h_aliases ); + } + *tp++=NULL; + /* finally the addresses */ + res->h_addr_list = tp; + if ( src->h_addr_list != NULL ) { + tbuf = cpy_addresses( &tp, tbuf, src->h_addr_list, src->h_length ); + } + *tp++=NULL; + return 0; + } + return -1; +} +#endif + +#if defined( NEED_SAFE_REALLOC ) +static char *safe_realloc( char **buf, int len ) +{ + char *tmpbuf; + tmpbuf = LDAP_REALLOC( *buf, len ); + if (tmpbuf) { + *buf=tmpbuf; + } + return tmpbuf; +} +#endif + +char * ldap_pvt_get_fqdn( char *name ) +{ + char *fqdn, *ha_buf; + char hostbuf[MAXHOSTNAMELEN+1]; + struct hostent *hp, he_buf; + int rc, local_h_errno; + + if( name == NULL ) { + if( gethostname( hostbuf, MAXHOSTNAMELEN ) == 0 ) { + hostbuf[MAXHOSTNAMELEN] = '\0'; + name = hostbuf; + } else { + name = "localhost"; + } + } + + rc = ldap_pvt_gethostbyname_a( name, + &he_buf, &ha_buf, &hp, &local_h_errno ); + + if( rc < 0 || hp == NULL || hp->h_name == NULL ) { + fqdn = LDAP_STRDUP( name ); + } else { + fqdn = LDAP_STRDUP( hp->h_name ); + } + + LDAP_FREE( ha_buf ); + return fqdn; +} + +#if defined( HAVE_GETADDRINFO ) && !defined( HAVE_GAI_STRERROR ) +char *ldap_pvt_gai_strerror (int code) { + static struct { + int code; + const char *msg; + } values[] = { +#ifdef EAI_ADDRFAMILY + { EAI_ADDRFAMILY, "Address family for hostname not supported" }, +#endif + { EAI_AGAIN, "Temporary failure in name resolution" }, + { EAI_BADFLAGS, "Bad value for ai_flags" }, + { EAI_FAIL, "Non-recoverable failure in name resolution" }, + { EAI_FAMILY, "ai_family not supported" }, + { EAI_MEMORY, "Memory allocation failure" }, +#ifdef EAI_NODATA + { EAI_NODATA, "No address associated with hostname" }, +#endif + { EAI_NONAME, "Name or service not known" }, + { EAI_SERVICE, "Servname not supported for ai_socktype" }, + { EAI_SOCKTYPE, "ai_socktype not supported" }, + { EAI_SYSTEM, "System error" }, + { 0, NULL } + }; + + int i; + + for ( i = 0; values[i].msg != NULL; i++ ) { + if ( values[i].code == code ) { + return (char *) values[i].msg; + } + } + + return "Unknown error"; +} +#endif diff --git a/libraries/libldif/fetch.c b/libraries/libldif/fetch.c new file mode 100644 index 0000000000000000000000000000000000000000..36baf734c2fa3ee9f92219998ba157d896be4c62 --- /dev/null +++ b/libraries/libldif/fetch.c @@ -0,0 +1,104 @@ +/* line64.c - routines for dealing with the slapd line format */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include <stdio.h> + +#include <ac/stdlib.h> + +#include <ac/string.h> +#include <ac/socket.h> +#include <ac/time.h> + +#ifdef HAVE_FETCH +#include <fetch.h> +#endif + +#include "ldap_log.h" +#include "lber_pvt.h" +#include "ldap_pvt.h" +#include "ldap_config.h" +#include "ldif.h" + +int +ldif_fetch_url( + LDAP_CONST char *urlstr, + char **valuep, + ber_len_t *vlenp +) +{ + FILE *url; + char buffer[1024]; + char *p = NULL; + size_t total; + size_t bytes; + + *valuep = NULL; + *vlenp = 0; + +#ifdef HAVE_FETCH + url = fetchGetURL( (char*) urlstr, "" ); + +#else + if( strncasecmp( "file://", urlstr, sizeof("file://")-1 ) == 0 ) { + p = strchr( &urlstr[sizeof("file://")-1], '/' ); + if( p == NULL ) { + return -1; + } + + /* we don't check for LDAP_DIRSEP since URLs should contain '/' */ + if( *p != '/' ) { + /* skip over false root */ + p++; + } + + p = ber_strdup( p ); + ldap_pvt_hex_unescape( p ); + + url = fopen( p, "rb" ); + + } else { + return -1; + } +#endif + + if( url == NULL ) { + return -1; + } + + total = 0; + + while( (bytes = fread( buffer, 1, sizeof(buffer), url )) != 0 ) { + char *newp = ber_memrealloc( p, total + bytes + 1 ); + if( newp == NULL ) { + ber_memfree( p ); + fclose( url ); + return -1; + } + p = newp; + AC_MEMCPY( &p[total], buffer, bytes ); + total += bytes; + } + + fclose( url ); + + if( total == 0 ) { + char *newp = ber_memrealloc( p, 1 ); + if( newp == NULL ) { + ber_memfree( p ); + return -1; + } + p = newp; + } + + p[total] = '\0'; + *valuep = p; + *vlenp = total; + + return 0; +} diff --git a/libraries/libldif/line64.c b/libraries/libldif/line64.c index 94c3f9dd4b46e7d5ff5daa38ebea1a898e61c945..1d0310793b98a030a41aa0b47b7695d0c7af1f56 100644 --- a/libraries/libldif/line64.c +++ b/libraries/libldif/line64.c @@ -143,9 +143,8 @@ ldif_parse_line( /* no value is present, error out */ ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, "ldif_parse_line: %s missing base64 value\n", type ); - value = NULL; - vlen = 0; - goto done; + ber_memfree( freeme ); + return( -1 ); } byte = value = s; @@ -196,9 +195,8 @@ ldif_parse_line( /* no value is present, error out */ ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, "ldif_parse_line: %s missing URL value\n", type ); - value = NULL; - vlen = 0; - goto done; + ber_memfree( freeme ); + return( -1 ); } if( ldif_fetch_url( s, &value, &vlen ) ) { @@ -214,7 +212,6 @@ ldif_parse_line( vlen = (int) (d - s); } -done: type = ber_strdup( type ); if( type == NULL ) { @@ -225,7 +222,7 @@ done: return( -1 ); } - if( !url && value != NULL ) { + if( !url ) { p = ber_memalloc( vlen + 1 ); if( p == NULL ) { ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,