From a81ca188454b343e91568d49c0ac408660dcb66c Mon Sep 17 00:00:00 2001 From: Bart Hartgers Date: Wed, 3 Mar 1999 16:38:56 +0000 Subject: [PATCH] Added support in liblber and libldap for partial reads, i.e. situations in which only part of a LDAPMessage is available on a socket. The server-code seemed to handle this correctly already, so I didn't touch it. My apologies for the hack in ber_get_next :-). --- include/lber.h | 7 +- libraries/liblber/io.c | 227 ++++++++++++++++++++++------------- libraries/liblber/sockbuf.c | 91 +++++++++++--- libraries/libldap/ldap-int.h | 8 +- libraries/libldap/request.c | 2 + libraries/libldap/result.c | 71 ++++++----- libraries/libldap/unbind.c | 2 + 7 files changed, 274 insertions(+), 134 deletions(-) diff --git a/include/lber.h b/include/lber.h index 5af98579ae..bf939f90b3 100644 --- a/include/lber.h +++ b/include/lber.h @@ -177,6 +177,7 @@ LDAP_F long ber_read LDAP_P(( BerElement *ber, char *buf, unsigned long len )); LDAP_F long ber_write LDAP_P(( BerElement *ber, char *buf, unsigned long len, int nosos )); LDAP_F void ber_free LDAP_P(( BerElement *ber, int freebuf )); +LDAP_F void ber_clear LDAP_P(( BerElement *ber, int freebuf )); LDAP_F int ber_flush LDAP_P(( Sockbuf *sb, BerElement *ber, int freeit )); LDAP_F BerElement *ber_alloc LDAP_P(( void )); LDAP_F BerElement *der_alloc LDAP_P(( void )); @@ -205,9 +206,9 @@ lber_set_option LDAP_P((void *item, int option, void *invalue)); /* * LBER Sockbuf functions */ -LDAP_F Sockbuf *lber_pvt_sockbuf_alloc LDAP_P((void)); -LDAP_F Sockbuf *lber_pvt_sockbuf_alloc_fd LDAP_P((int fd)); -LDAP_F void lber_pvt_sockbuf_free LDAP_P((Sockbuf *sb)); +LDAP_F Sockbuf *lber_pvt_sk_alloc LDAP_P((void)); +LDAP_F Sockbuf *lber_pvt_sb_alloc_fd LDAP_P((int fd)); +LDAP_F void lber_pvt_sb_free LDAP_P((Sockbuf *sb)); LDAP_END_DECL diff --git a/libraries/liblber/io.c b/libraries/liblber/io.c index dd8bc5f14f..7d529500d7 100644 --- a/libraries/liblber/io.c +++ b/libraries/liblber/io.c @@ -32,11 +32,25 @@ #include "lber-int.h" +#ifdef LDAP_DEBUG +#include +#else +#define assert(cond) +#endif + static long BerRead LDAP_P(( Sockbuf *sb, char *buf, long len )); static int ber_realloc LDAP_P(( BerElement *ber, unsigned long len )); #define EXBUFSIZ 1024 +/* probably far too large... */ +#define MAX_BERBUFSIZE (128*1024) + +#if defined( DOS ) && !defined( _WIN32 ) && (MAX_BERBUFSIZE > 65535) +# undef MAX_BERBUFSIZE +# define MAX_BERBUFSIZE 65535 +#endif + static long BerRead( Sockbuf *sb, char *buf, long len ) { @@ -329,6 +343,7 @@ ber_reset( BerElement *ber, int was_writing ) ber->ber_rwptr = NULL; } +#if 0 /* return the tag - LBER_DEFAULT returned means trouble */ static unsigned long get_tag( Sockbuf *sb ) @@ -363,21 +378,22 @@ get_tag( Sockbuf *sb ) /* want leading, not trailing 0's */ return( tag >> (sizeof(long) - i - 1) ); } +#endif + +/* + * A rewrite of get_get_next that can safely be called multiple times + * for the same packet. It will simply continue were it stopped until + * a full packet is read. + */ unsigned long ber_get_next( Sockbuf *sb, unsigned long *len, BerElement *ber ) { - unsigned long tag = 0, netlen, toread; - unsigned char lc; - long rc; - long noctets; - unsigned int diff; - if ( ber->ber_debug ) { lber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug, "ber_get_next\n" ); } - + /* * Any ber element looks like this: tag length contents. * Assuming everything's ok, we return the tag byte (we @@ -389,95 +405,140 @@ ber_get_next( Sockbuf *sb, unsigned long *len, BerElement *ber ) * 2) definite lengths * 3) primitive encodings used whenever possible */ + + if (ber->ber_rwptr == NULL) { + assert( ber->ber_buf == NULL ); + ber->ber_rwptr = (char *) &ber->ber_tag; + ber->ber_tag = 0; + } - /* - * first time through - malloc the buffer, set up ptrs, and - * read the tag and the length and as much of the rest as we can - */ - - if ( ber->ber_rwptr == NULL ) { - /* - * First, we read the tag. - */ - - if ( (tag = get_tag( sb )) == LBER_DEFAULT ) { - return( LBER_DEFAULT ); - } - ber->ber_tag = tag; - - /* - * Next, read the length. The first byte contains the length - * of the length. If bit 8 is set, the length is the long - * form, otherwise it's the short form. We don't allow a - * length that's greater than what we can hold in an unsigned - * long. - */ - - *len = netlen = 0; - if ( lber_pvt_sb_read( sb, (char *) &lc, 1 ) != 1 ) { - return( LBER_DEFAULT ); +#define PTR_IN_VAR( ptr, var )\ +(((ptr)>=(char *) &(var)) && ((ptr)< (char *) &(var)+sizeof(var))) + + if (PTR_IN_VAR(ber->ber_rwptr, ber->ber_tag)) { + if (ber->ber_rwptr == (char *) &ber->ber_tag) { + if (lber_pvt_sb_read( sb, ber->ber_rwptr, 1)<=0) + return LBER_DEFAULT; + if ((ber->ber_rwptr[0] & LBER_BIG_TAG_MASK) + != LBER_BIG_TAG_MASK) { + ber->ber_tag = ber->ber_rwptr[0]; + ber->ber_rwptr = (char *) &ber->ber_usertag; + goto get_lenbyte; + } + ber->ber_rwptr++; } - if ( lc & 0x80 ) { - noctets = (lc & 0x7f); - if ( noctets > sizeof(unsigned long) ) - return( LBER_DEFAULT ); - diff = sizeof(unsigned long) - noctets; - if ( BerRead( sb, (char *) &netlen + diff, noctets ) != - noctets ) { - return( LBER_DEFAULT ); + do { + /* reading the tag... */ + if (lber_pvt_sb_read( sb, ber->ber_rwptr, 1)<=0) + return LBER_DEFAULT; + if (! (ber->ber_rwptr[0] & LBER_MORE_TAG_MASK) ) { + ber->ber_tag>>=sizeof(ber->ber_tag) - + ((char *) &ber->ber_tag - ber->ber_rwptr); + ber->ber_rwptr = (char *) &ber->ber_usertag; + goto get_lenbyte; + } + } while (PTR_IN_VAR(ber->ber_rwptr,ber->ber_tag)); + errno = ERANGE; /* this is a serious error. */ + return LBER_DEFAULT; + } +get_lenbyte: + if (ber->ber_rwptr==(char *) &ber->ber_usertag) { + unsigned char c; + if (lber_pvt_sb_read( sb, (char *) &c, 1)<=0) + return LBER_DEFAULT; + if (c & 0x80) { + int len = c & 0x7f; + if ( (len==0) || ( len>sizeof( ber->ber_len ) ) ) { + errno = ERANGE; + return LBER_DEFAULT; } - *len = AC_NTOHL( netlen ); + ber->ber_rwptr = (char *) &ber->ber_len + + sizeof(ber->ber_len) - len; + ber->ber_len = 0; } else { - *len = lc; + ber->ber_len = c; + goto fill_buffer; } - ber->ber_len = *len; - - /* - * Finally, malloc a buffer for the contents and read it in. - * It's this buffer that's passed to all the other ber decoding - * routines. - */ - -#if defined( DOS ) && !defined( _WIN32 ) - if ( *len > 65535 ) { /* DOS can't allocate > 64K */ - return( LBER_DEFAULT ); - } -#endif /* DOS && !_WIN32 */ -#ifdef DEADWOOD - if ( ( sb->sb_options & LBER_MAX_INCOMING_SIZE ) && - *len > (unsigned long) sb->sb_max_incoming ) { - return( LBER_DEFAULT ); + } + if (PTR_IN_VAR(ber->ber_rwptr, ber->ber_len)) { + int res; + int to_go; + to_go = (char *) &ber->ber_len + sizeof( ber->ber_len ) - + ber->ber_rwptr; + assert( to_go > 0 ); + res = lber_pvt_sb_read( sb, ber->ber_rwptr, to_go ); + if (res <=0) + return LBER_DEFAULT; + ber->ber_rwptr += res; + if (res==to_go) { + /* convert length. */ + ber->ber_len = AC_NTOHL( ber->ber_len ); + goto fill_buffer; + } else { +#if defined( EWOULDBLOCK ) + errno = EWOULDBLOCK; +#elif defined( EAGAIN ) + errno = EAGAIN; +#endif + return LBER_DEFAULT; } -#endif - if ( (ber->ber_buf = (char *) malloc( (size_t)*len )) == NULL ) { - return( LBER_DEFAULT ); + } +fill_buffer: + /* now fill the buffer. */ + if (ber->ber_buf==NULL) { + if (ber->ber_len > MAX_BERBUFSIZE) { + errno = ERANGE; + return LBER_DEFAULT; } - ber->ber_ptr = ber->ber_buf; - ber->ber_end = ber->ber_buf + *len; + ber->ber_buf = (char *) malloc( ber->ber_len ); + if (ber->ber_buf==NULL) + return LBER_DEFAULT; ber->ber_rwptr = ber->ber_buf; + ber->ber_ptr = ber->ber_buf; + ber->ber_end = ber->ber_buf + ber->ber_len; } - - toread = (unsigned long)ber->ber_end - (unsigned long)ber->ber_rwptr; - do { - if ( (rc = lber_pvt_sb_read( sb, ber->ber_rwptr, (long)toread )) <= 0 ) { - return( LBER_DEFAULT ); + if ((ber->ber_rwptr>=ber->ber_buf) && (ber->ber_rwptrber_end)) { + int res; + int to_go; + + to_go = ber->ber_end - ber->ber_rwptr; + assert( to_go > 0 ); + + res = lber_pvt_sb_read( sb, ber->ber_rwptr, to_go ); + if (res<=0) + return LBER_DEFAULT; + ber->ber_rwptr+=res; + + if (resber_rwptr += rc; - } while ( toread > 0 ); - - if ( ber->ber_debug ) { - lber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug, - "ber_get_next: tag 0x%lx len %ld contents:\n", - tag, ber->ber_len ); - - lber_log_dump( LDAP_DEBUG_BER, ber->ber_debug, ber, 1 ); + + ber->ber_rwptr = NULL; + *len = ber->ber_len; + if ( ber->ber_debug ) { + lber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug, + "ber_get_next: tag 0x%lx len %ld contents:\n", + ber->ber_tag, ber->ber_len ); + lber_log_dump( LDAP_DEBUG_BER, ber->ber_debug, ber, 1 ); + } + return (ber->ber_tag); } + assert( 0 ); /* ber structure is messed up ?*/ + return LBER_DEFAULT; +} - *len = ber->ber_len; +void ber_clear( BerElement *ber, int freebuf ) +{ + if ((freebuf) && (ber->ber_buf)) + free( ber->ber_buf ); + ber->ber_buf = NULL; ber->ber_rwptr = NULL; - return( ber->ber_tag ); + ber->ber_end = NULL; } Sockbuf *lber_pvt_sb_alloc( void ) diff --git a/libraries/liblber/sockbuf.c b/libraries/liblber/sockbuf.c index 8902af162d..4fec6f9f8f 100644 --- a/libraries/liblber/sockbuf.c +++ b/libraries/liblber/sockbuf.c @@ -29,6 +29,8 @@ #ifdef LDAP_DEBUG #include +#undef TEST_PARTIAL_READ +#undef TEST_PARTIAL_WRITE #else #define assert( cond ) #endif @@ -112,16 +114,16 @@ packet_length( char *buf ) static int grow_buffer( Sockbuf_Buf * buf, long minsize ) { - /* round to nearest 2k */ - if (minsize < MIN_BUF_SIZE) { - minsize = MIN_BUF_SIZE; - } else { - minsize=((minsize-1)|2047)+1; - if (minsize > MAX_BUF_SIZE) { + long pw=MIN_BUF_SIZE; + + for(;(pw MAX_BUF_SIZE) { /* this could mean that somebody is trying to crash us. */ return -1; } } + minsize = pw; + if (buf->buf_sizebuf_base==NULL) || ((buf->buf_end==0) && (buf->buf_ptr==0))) { /* empty buffer */ @@ -309,13 +311,23 @@ lber_pvt_sb_read( Sockbuf *sb, void *buf_arg, long len ) /* breaks slapd :-) */ assert( lber_pvt_sb_in_use( sb ) ); #endif + +#ifdef TEST_PARTIAL_READ + if ((rand() & 3)==1) { /* 1 out of 4 */ + errno = EWOULDBLOCK; + return -1; + } + + len = (rand() % len)+1; +#endif buf = (char *) buf_arg; - len = sockbuf_copy_out( sb, &buf, len ); - - if (len==0) { - return (buf - (char *) buf_arg); + if (sb->sb_buf.buf_ptr!=sb->sb_buf.buf_end) { + len = sockbuf_copy_out( sb, &buf, len ); + if (len==0) { + return (buf - (char *) buf_arg); + } } #ifdef USE_SASL @@ -336,8 +348,15 @@ lber_pvt_sb_read( Sockbuf *sb, void *buf_arg, long len ) } for(;;) { /* read from stream into sb_sec_buf_in */ - ret = sockbuf_io_read( sb, sb->sb_sec_buf_in.buf_base + + for(;;) { + ret = sockbuf_io_read( sb, sb->sb_sec_buf_in.buf_base + sb->sb_sec_buf_in.buf_ptr, max ); +#ifdef EINTR + if ((ret<0) && (errno==EINTR)) + continue; +#endif + break; + } if (ret<=0) { /* read error. return */ goto do_return; @@ -393,10 +412,17 @@ decode_packet: long max; max = sb->sb_buf.buf_size - sb->sb_buf.buf_end; if (max>len) { - ret = sockbuf_io_read( sb, + for(;;) { + ret = sockbuf_io_read( sb, sb->sb_buf.buf_base + sb->sb_buf.buf_end, - max ); + max ); +#ifdef EINTR + if ((ret<0) && (errno==EINTR)) + continue; +#endif + break; + } if (ret<=0) { /* some error occured */ goto do_return; @@ -408,7 +434,14 @@ decode_packet: } } /* no read_ahead, just try to put the data in the buf. */ - ret = sockbuf_io_read( sb, buf, len ); + for(;;) { + ret = sockbuf_io_read( sb, buf, len ); +#ifdef EINTR + if ((ret<0) && (errno==EINTR)) + continue; +#endif + break; + } if (ret>0) { buf+=ret; len-=ret; @@ -433,8 +466,15 @@ long sockbuf_do_write( Sockbuf *sb ) to_go = sb->sb_sec_out.buf_end - sb->sb_sec_out.buf_ptr; assert( to_go > 0 ); /* there is something left of the last time... */ - ret = sockbuf_io_write( sb, sb->sb_sec_out.buf_base+ - sb->sb_sec_out.buf_ptr, to_go ); + for(;;) { + ret = sockbuf_io_write( sb, sb->sb_sec_out.buf_base+ + sb->sb_sec_out.buf_ptr, to_go ); +#ifdef EINTR + if ((ret<0) && (errno==EINTR)) + continue; +#endif + break; + } if (ret<=0) /* error */ return ret; sb->sb_sec_out.buf_ptr += ret; @@ -453,6 +493,16 @@ long lber_pvt_sb_write( Sockbuf *sb, void *buf, long len_arg ) /* unfortunately breaks slapd */ assert( lber_pvt_sb_in_use( sb ) ); #endif +#ifdef TEST_PARTIAL_WRITE + if ((rand() & 3)==1) { /* 1 out of 4 */ + errno = EWOULDBLOCK; + return -1; + } + + len_arg = (rand() % len_arg)+1; + len = len_arg; +#endif + #ifdef USE_SASL if (sb->sb_sec) { assert( sb->sb_sec_prev_len <= len ); @@ -477,7 +527,14 @@ long lber_pvt_sb_write( Sockbuf *sb, void *buf, long len_arg ) return len_arg; } else { #endif - return sockbuf_io_write( sb, buf, len ); + for(;;) { + ret = sockbuf_io_write( sb, buf, len ); +#ifdef EINTR + if ((ret<0) && (errno==EINTR)) + continue; +#endif + break; + } #ifdef USE_SASL } #endif diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h index 474807582e..9f27a0a6a3 100644 --- a/libraries/libldap/ldap-int.h +++ b/libraries/libldap/ldap-int.h @@ -127,6 +127,7 @@ typedef struct ldap_conn { LDAPServer *lconn_server; char *lconn_krbinstance; struct ldap_conn *lconn_next; + BerElement lconn_ber;/* ber receiving on this conn. */ } LDAPConn; @@ -227,8 +228,11 @@ struct ldap { /* stuff used by connectionless searches. */ char *ld_cldapdn; /* DN used in connectionless search */ int ld_cldapnaddr; /* number of addresses */ - void **ld_cldapaddrs;/* addresses to send request to */ - + void **ld_cldapaddrs;/* addresses to send request to */ +#ifndef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS + /* BerElement that this connection is receiving. */ + BerElement ld_ber; +#endif /* do not mess with the rest though */ BERTranslateProc ld_lber_encode_translate_proc; BERTranslateProc ld_lber_decode_translate_proc; diff --git a/libraries/libldap/request.c b/libraries/libldap/request.c index ab00e00986..5b8ecc8c5e 100644 --- a/libraries/libldap/request.c +++ b/libraries/libldap/request.c @@ -21,6 +21,7 @@ #include #include "ldap-int.h" +#include "lber.h" #if defined( LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS ) || defined( LDAP_API_FEATURE_X_OPENLDAP_V2_DNS ) static LDAPConn *find_connection LDAP_P(( LDAP *ld, LDAPServer *srv, int any )); @@ -444,6 +445,7 @@ ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind ) } ldap_close_connection( lc->lconn_sb ); lber_pvt_sb_destroy( lc->lconn_sb ); + ber_clear( &lc->lconn_ber, 1 ); } prevlc = NULL; for ( tmplc = ld->ld_conns; tmplc != NULL; diff --git a/libraries/libldap/result.c b/libraries/libldap/result.c index df532f08f6..40729f18c5 100644 --- a/libraries/libldap/result.c +++ b/libraries/libldap/result.c @@ -28,12 +28,12 @@ static int ldap_mark_abandoned LDAP_P(( LDAP *ld, int msgid )); static int wait4msg LDAP_P(( LDAP *ld, int msgid, int all, struct timeval *timeout, LDAPMessage **result )); #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS -static int read1msg LDAP_P(( LDAP *ld, int msgid, int all, Sockbuf *sb, LDAPConn *lc, +static int try_read1msg LDAP_P(( LDAP *ld, int msgid, int all, Sockbuf *sb, LDAPConn *lc, LDAPMessage **result )); static unsigned long build_result_ber LDAP_P(( LDAP *ld, BerElement *ber, LDAPRequest *lr )); static void merge_error_info LDAP_P(( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr )); #else /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */ -static int read1msg LDAP_P(( LDAP *ld, int msgid, int all, Sockbuf *sb, +static int try_read1msg LDAP_P(( LDAP *ld, int msgid, int all, Sockbuf *sb, LDAPMessage **result )); #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */ #if defined( LDAP_CONNECTIONLESS ) || !defined( LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS ) @@ -182,7 +182,7 @@ wait4msg( LDAP *ld, int msgid, int all, struct timeval *timeout, if ( rc == -1 ) { rc = -2; /* select interrupted: loop */ } else { - rc = read1msg( ld, msgid, all, &ld->ld_sb, result ); + rc = try_read1msg( ld, msgid, all, &ld->ld_sb, result ); } #else /* !LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */ #ifdef LDAP_DEBUG @@ -193,7 +193,7 @@ wait4msg( LDAP *ld, int msgid, int all, struct timeval *timeout, #endif /* LDAP_DEBUG */ for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) { if ( lber_pvt_sb_data_ready(lc->lconn_sb) ) { - rc = read1msg( ld, msgid, all, lc->lconn_sb, + rc = try_read1msg( ld, msgid, all, lc->lconn_sb, lc, result ); break; } @@ -232,7 +232,7 @@ wait4msg( LDAP *ld, int msgid, int all, struct timeval *timeout, LDAP_CONNST_CONNECTED && ldap_is_read_ready( ld, lc->lconn_sb )) { - rc = read1msg( ld, msgid, all, + rc = try_read1msg( ld, msgid, all, lc->lconn_sb, lc, result ); } } @@ -259,13 +259,13 @@ wait4msg( LDAP *ld, int msgid, int all, struct timeval *timeout, static int -read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, +try_read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS LDAPConn *lc, #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */ LDAPMessage **result ) { - BerElement ber; + BerElement *ber; LDAPMessage *new, *l, *prev, *tmp; long id; unsigned long tag, len; @@ -275,30 +275,47 @@ read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, BerElement tmpber; int rc, refer_cnt, hadref, simple_request; unsigned long lderr; + + ber = &lc->lconn_ber; +#else + ber = &ld->ld_ber; #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */ Debug( LDAP_DEBUG_TRACE, "read1msg\n", 0, 0, 0 ); - +#if 0 ber_init_w_nullc( &ber, 0 ); ldap_set_ber_options( ld, &ber ); - +#endif /* get the next message */ - if ( (tag = ber_get_next( sb, &len, &ber )) + if ( (tag = ber_get_next( sb, &len, ber )) != LDAP_TAG_MESSAGE ) { - ld->ld_errno = (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN : - LDAP_LOCAL_ERROR); - return( -1 ); + if ( tag == LBER_DEFAULT) { +#ifdef LDAP_DEBUG + Debug( LDAP_DEBUG_CONNS, + "ber_get_next failed.\n", 0, 0, 0 ); +#endif +#ifdef EWOULDBLOCK + if (errno==EWOULDBLOCK) return -2; +#endif +#ifdef EAGAIN + if (errno == EAGAIN) return -2; +#endif + ld->ld_errno = LDAP_SERVER_DOWN; + return -1; + } + ld->ld_errno = LDAP_LOCAL_ERROR; + return -1; } /* message id */ - if ( ber_get_int( &ber, &id ) == LBER_ERROR ) { + if ( ber_get_int( ber, &id ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; return( -1 ); } /* if it's been abandoned, toss it */ if ( ldap_abandoned( ld, (int)id ) ) { - free( ber.ber_buf ); /* gack! */ + ber_clear( ber, 1 ); /* gack! */ return( -2 ); /* continue looking */ } @@ -307,7 +324,7 @@ read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, Debug( LDAP_DEBUG_ANY, "no request for response with msgid %ld (tossing)\n", id, 0, 0 ); - free( ber.ber_buf ); /* gack! */ + ber_clear( ber, 1 ); /* gack! */ return( -2 ); /* continue looking */ } Debug( LDAP_DEBUG_TRACE, "got %s msgid %ld, original id %d\n", @@ -317,7 +334,7 @@ read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */ /* the message type */ - if ( (tag = ber_peek_tag( &ber, &len )) == LBER_ERROR ) { + if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; return( -1 ); } @@ -334,7 +351,7 @@ read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, ( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) != LDAP_OPT_OFF ) ) ) { - tmpber = ber; /* struct copy */ + tmpber = *ber; /* struct copy */ if ( ber_scanf( &tmpber, "{iaa}", &lderr, &lr->lr_res_matched, &lr->lr_res_error ) != LBER_ERROR ) { @@ -365,8 +382,7 @@ Debug( LDAP_DEBUG_TRACE, "read1msg: %d new referrals\n", refer_cnt, 0, 0 ); if ( refer_cnt != 0 ) { /* chasing referrals */ - free( ber.ber_buf ); /* gack! */ - ber.ber_buf = NULL; + ber_clear( ber, 1 ); /* gack! */ if ( refer_cnt < 0 ) { return( -1 ); /* fatal error */ } @@ -377,8 +393,7 @@ Debug( LDAP_DEBUG_TRACE, simple_request = ( hadref ? 0 : 1 ); } else { /* request with referrals or child request */ - free( ber.ber_buf ); /* gack! */ - ber.ber_buf = NULL; + ber_clear( ber, 1 ); /* gack! */ } while ( lr->lr_parent != NULL ) { @@ -400,11 +415,8 @@ Debug( LDAP_DEBUG_TRACE, lr->lr_res_errno, lr->lr_res_error ? lr->lr_res_error : "", lr->lr_res_matched ? lr->lr_res_matched : "" ); if ( !simple_request ) { - if ( ber.ber_buf != NULL ) { - free( ber.ber_buf ); /* gack! */ - ber.ber_buf = NULL; - } - if ( build_result_ber( ld, &ber, lr ) + ber_clear( ber, 1 ); /* gack! */ + if ( build_result_ber( ld, ber, lr ) == LBER_ERROR ) { ld->ld_errno = LDAP_NO_MEMORY; rc = -1; /* fatal error */ @@ -420,7 +432,7 @@ lr->lr_res_matched ? lr->lr_res_matched : "" ); } } - if ( ber.ber_buf == NULL ) { + if ( ber->ber_buf == NULL ) { return( rc ); } @@ -433,7 +445,8 @@ lr->lr_res_matched ? lr->lr_res_matched : "" ); } new->lm_msgid = (int)id; new->lm_msgtype = tag; - new->lm_ber = ber_dup( &ber ); + new->lm_ber = ber_dup( ber ); + ber_clear( ber, 0 ); /* don't kill buffer */ #ifndef LDAP_NOCACHE if ( ld->ld_cache != NULL ) { diff --git a/libraries/libldap/unbind.c b/libraries/libldap/unbind.c index a1c91e5e71..7f17a1bb73 100644 --- a/libraries/libldap/unbind.c +++ b/libraries/libldap/unbind.c @@ -91,6 +91,8 @@ ldap_ld_free( LDAP *ld, int close ) #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS if ( ld->ld_selectinfo != NULL ) ldap_free_select_info( ld->ld_selectinfo ); +#else + ber_clear( &(ld->ld_ber), 1 ); #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */ if ( ld->ld_options.ldo_defbase != NULL ) -- 2.39.5