Commit 0d9ca77f authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

updated ldif fixes

libldap getaddrinfo thread safety
ready for release
parent 91b4bfb2
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
......
......@@ -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}
......
......@@ -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
......
......@@ -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;
......
......@@ -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;
......
/* $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
/* 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;
}