X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Fliblber%2Fio.c;h=74abb24fd4d22b1516e1b5dc0b5dfd41af1a75e2;hb=9cfcdc432bd89fe243adb29a91ce1d8fddad459d;hp=023110f8c8b22f476c1d700a5272460e8914468d;hpb=90465762286569deb2cd53b4e1b5de2f07d11d9e;p=openldap diff --git a/libraries/liblber/io.c b/libraries/liblber/io.c index 023110f8c8..74abb24fd4 100644 --- a/libraries/liblber/io.c +++ b/libraries/liblber/io.c @@ -1,7 +1,7 @@ /* io.c - ber general i/o routines */ /* $OpenLDAP$ */ /* - * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -33,36 +33,7 @@ #endif #include "lber-int.h" - -#define EXBUFSIZ 1024 - -static ber_slen_t -BerRead( - Sockbuf *sb, - unsigned char *buf, - ber_len_t len ) -{ - ber_slen_t c; - ber_slen_t nread = 0; - - assert( sb != NULL ); - assert( buf != NULL ); - - assert( SOCKBUF_VALID( sb ) ); - - while ( len > 0 ) { - if ( (c = ber_int_sb_read( sb, buf, len )) <= 0 ) { - if ( nread > 0 ) - break; - return( c ); - } - buf+=c; - nread+=c; - len-=c; - } - - return( nread ); -} +#include "ldap_log.h" ber_slen_t ber_read( @@ -75,7 +46,7 @@ ber_read( assert( ber != NULL ); assert( buf != NULL ); - assert( BER_VALID( ber ) ); + assert( LBER_VALID( ber ) ); nleft = ber_pvt_ber_remaining( ber ); actuallen = nleft < len ? nleft : len; @@ -97,7 +68,7 @@ ber_write( assert( ber != NULL ); assert( buf != NULL ); - assert( BER_VALID( ber ) ); + assert( LBER_VALID( ber ) ); if ( nosos || ber->ber_sos == NULL ) { if ( ber->ber_ptr + len > ber->ber_end ) { @@ -123,20 +94,32 @@ ber_write( int ber_realloc( BerElement *ber, ber_len_t len ) { - ber_len_t need, have, total; + ber_len_t total; Seqorset *s; long off; char *oldbuf; assert( ber != NULL ); assert( len > 0 ); - - assert( BER_VALID( ber ) ); + assert( LBER_VALID( ber ) ); total = ber_pvt_ber_total( ber ); - have = total / EXBUFSIZ; - need = (len < EXBUFSIZ ? 1 : (len + (EXBUFSIZ - 1)) / EXBUFSIZ); - total = have * EXBUFSIZ + need * EXBUFSIZ; + +#define LBER_EXBUFSIZ 4060 /* a few words less than 2^N for binary buddy */ +#if defined( LBER_EXBUFSIZ ) && LBER_EXBUFSIZ > 0 +# ifndef notdef + /* don't realloc by small amounts */ + total += len < LBER_EXBUFSIZ ? LBER_EXBUFSIZ : len; +# else + { /* not sure what value this adds */ + ber_len_t have = (total + (LBER_EXBUFSIZE - 1)) / LBER_EXBUFSIZ; + ber_len_t need = (len + (LBER_EXBUFSIZ - 1)) / LBER_EXBUFSIZ; + total = ( have + need ) * LBER_EXBUFSIZ; + } +# endif +#else + total += len; /* realloc just what's needed */ +#endif oldbuf = ber->ber_buf; @@ -170,6 +153,25 @@ ber_realloc( BerElement *ber, ber_len_t len ) return( 0 ); } +void +ber_free_buf( BerElement *ber ) +{ + Seqorset *s, *next; + + assert( LBER_VALID( ber ) ); + + if ( ber->ber_buf) LBER_FREE( ber->ber_buf ); + + for( s = ber->ber_sos ; s != NULL ; s = next ) { + next = s->sos_next; + LBER_FREE( s ); + } + + ber->ber_buf = NULL; + ber->ber_sos = NULL; + ber->ber_valid = LBER_UNINITIALIZED; +} + void ber_free( BerElement *ber, int freebuf ) { @@ -181,21 +183,8 @@ ber_free( BerElement *ber, int freebuf ) return; } - assert( BER_VALID( ber ) ); - - if ( freebuf ) { - Seqorset *s, *next; - LBER_FREE( ber->ber_buf ); - - for( s = ber->ber_sos ; s != NULL ; s = next ) { - next = s->sos_next; - LBER_FREE( s ); - } - } - - ber->ber_buf = NULL; - ber->ber_sos = NULL; - ber->ber_valid = LBER_UNINITIALIZED; + if( freebuf ) + ber_free_buf( ber ); LBER_FREE( (char *) ber ); } @@ -203,14 +192,14 @@ ber_free( BerElement *ber, int freebuf ) int ber_flush( Sockbuf *sb, BerElement *ber, int freeit ) { - ber_len_t nwritten, towrite; + ber_len_t towrite; ber_slen_t rc; assert( sb != NULL ); assert( ber != NULL ); assert( SOCKBUF_VALID( sb ) ); - assert( BER_VALID( ber ) ); + assert( LBER_VALID( ber ) ); if ( ber->ber_rwptr == NULL ) { ber->ber_rwptr = ber->ber_buf; @@ -219,11 +208,14 @@ ber_flush( Sockbuf *sb, BerElement *ber, int freeit ) if ( sb->sb_debug ) { #ifdef NEW_LOGGING - LDAP_LOG(( "liblber", LDAP_LEVEL_DETAIL1, + LDAP_LOG( BER, DETAIL1, "ber_flush: %ld bytes to sd %ld%s\n", towrite, (long)sb->sb_fd, - ber->ber_rwptr != ber->ber_buf ? " (re-flush)" : "" )); - BER_DUMP(( "liblber", LDAP_LEVEL_DETAIL2, ber, 1 )); + ber->ber_rwptr != ber->ber_buf ? " (re-flush)" : "" ); + + if(LDAP_LOGS_TEST(BER, DETAIL2)) + BER_DUMP(( "liblber", LDAP_LEVEL_DETAIL2, ber, 1 )); + #else ber_log_printf( LDAP_DEBUG_ANY, sb->sb_debug, "ber_flush: %ld bytes to sd %ld%s\n", @@ -234,16 +226,14 @@ ber_flush( Sockbuf *sb, BerElement *ber, int freeit ) #endif } - nwritten = 0; - do { + while ( towrite > 0 ) { rc = ber_int_sb_write( sb, ber->ber_rwptr, towrite ); if (rc<=0) { return -1; } towrite -= rc; - nwritten += rc; ber->ber_rwptr += rc; - } while ( towrite > 0 ); + } if ( freeit ) ber_free( ber, 1 ); @@ -269,7 +259,7 @@ ber_alloc_t( int options ) ber->ber_options = options; ber->ber_debug = ber_int_debug; - assert( BER_VALID( ber ) ); + assert( LBER_VALID( ber ) ); return ber; } @@ -291,7 +281,7 @@ ber_dup( BerElement *ber ) BerElement *new; assert( ber != NULL ); - assert( BER_VALID( ber ) ); + assert( LBER_VALID( ber ) ); if ( (new = ber_alloc_t( ber->ber_options )) == NULL ) { return NULL; @@ -299,18 +289,17 @@ ber_dup( BerElement *ber ) *new = *ber; - assert( BER_VALID( new ) ); + assert( LBER_VALID( new ) ); return( new ); } -/* OLD U-Mich ber_init() */ void -ber_init_w_nullc( BerElement *ber, int options ) +ber_init2( BerElement *ber, struct berval *bv, int options ) { assert( ber != NULL ); - ber_int_options.lbo_valid = LBER_INITIALIZED; + ber_int_options.lbo_valid = LBER_INITIALIZED; (void) memset( (char *)ber, '\0', sizeof( BerElement )); ber->ber_valid = LBER_VALID_BERELEMENT; @@ -318,7 +307,20 @@ ber_init_w_nullc( BerElement *ber, int options ) ber->ber_options = (char) options; ber->ber_debug = ber_int_debug; - assert( BER_VALID( ber ) ); + if ( bv != NULL ) { + ber->ber_buf = bv->bv_val; + ber->ber_ptr = ber->ber_buf; + ber->ber_end = ber->ber_buf + bv->bv_len; + } + + assert( LBER_VALID( ber ) ); +} + +/* OLD U-Mich ber_init() */ +void +ber_init_w_nullc( BerElement *ber, int options ) +{ + ber_init2( ber, NULL, options ); } /* New C-API ber_init() */ @@ -410,7 +412,7 @@ void ber_reset( BerElement *ber, int was_writing ) { assert( ber != NULL ); - assert( BER_VALID( ber ) ); + assert( LBER_VALID( ber ) ); if ( was_writing ) { ber->ber_end = ber->ber_ptr; @@ -440,10 +442,10 @@ ber_get_next( assert( ber != NULL ); assert( SOCKBUF_VALID( sb ) ); - assert( BER_VALID( ber ) ); + assert( LBER_VALID( ber ) ); #ifdef NEW_LOGGING - LDAP_LOG(( "liblber", LDAP_LEVEL_ENTRY, "ber_get_next: enter\n" )); + LDAP_LOG( BER, ENTRY, "ber_get_next: enter\n", 0, 0, 0 ); #else ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug, "ber_get_next\n" ); @@ -460,121 +462,139 @@ ber_get_next( * 2) definite lengths * 3) primitive encodings used whenever possible */ - + if (ber->ber_rwptr == NULL) { /* XXYYZ * dtest does like this assert. */ /* assert( ber->ber_buf == NULL ); */ - ber->ber_rwptr = (char *) &ber->ber_tag; + ber->ber_rwptr = (char *) &ber->ber_len-1; + ber->ber_ptr = ber->ber_rwptr; ber->ber_tag = 0; } -#undef PTR_IN_VAR -#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 (ber_int_sb_read( sb, ber->ber_rwptr, 1)<=0) - return LBER_DEFAULT; + while (ber->ber_rwptr > (char *)&ber->ber_tag && ber->ber_rwptr < + (char *)(&ber->ber_usertag + 1)) { + ber_slen_t i; + char buf[sizeof(ber->ber_len)-1]; + ber_len_t tlen = 0; - 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 ((i=ber_int_sb_read( sb, ber->ber_rwptr, + (char *)(&ber->ber_usertag+1)-ber->ber_rwptr))<=0) { + return LBER_DEFAULT; } - do { - /* reading the tag... */ - if (ber_int_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; + ber->ber_rwptr += i; + + /* We got at least one byte, try to parse the tag. */ + if (ber->ber_ptr == (char *)&ber->ber_len-1) { + ber_tag_t tag; + unsigned char *p = (unsigned char *)ber->ber_ptr; + tag = *p++; + if ((tag & LBER_BIG_TAG_MASK) == LBER_BIG_TAG_MASK) { + for (i=1; (char *)pber_rwptr; i++,p++) { + tag <<= 8; + tag |= *p; + if (!(*p & LBER_MORE_TAG_MASK)) + break; + /* Is the tag too big? */ + if (i == sizeof(ber_tag_t)-1) { + errno = ERANGE; + return LBER_DEFAULT; + } + } + /* Did we run out of bytes? */ + if ((char *)p == ber->ber_rwptr) { + return LBER_DEFAULT; + } + p++; } - } 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 (ber_int_sb_read( sb, (char *) &c, 1)<=0) { - return LBER_DEFAULT; + ber->ber_tag = tag; + ber->ber_ptr = (char *)p; } - if (c & 0x80U) { - int len = c & 0x7fU; - if ( (len==0) || ( len>sizeof( ber->ber_len ) ) ) { + if (i == 1) continue; + + /* Now look for the length */ + if (*ber->ber_ptr & 0x80) { /* multi-byte */ + int llen = *(unsigned char *)ber->ber_ptr++ & 0x7f; + if (llen > (int)sizeof(ber_len_t)) { errno = ERANGE; return LBER_DEFAULT; } - - ber->ber_rwptr = (char *) &ber->ber_len + - sizeof(ber->ber_len) - len; - ber->ber_len = 0; - + /* Not enough bytes? */ + if (ber->ber_rwptr - ber->ber_ptr < llen) { + return LBER_DEFAULT; + } + for (i=0; iber_ptrber_rwptr; i++,ber->ber_ptr++) { + tlen <<=8; + tlen |= *(unsigned char *)ber->ber_ptr; + } } else { - ber->ber_len = c; - goto fill_buffer; + tlen = *(unsigned char *)ber->ber_ptr++; } - } - - if (PTR_IN_VAR(ber->ber_rwptr, ber->ber_len)) { - unsigned char netlen[sizeof(ber_len_t)]; - - ber_slen_t res; - ber_slen_t to_go; - to_go = (char *) &ber->ber_len + sizeof( ber->ber_len ) - - ber->ber_rwptr; - assert( to_go > 0 ); - - res = BerRead( sb, netlen, to_go ); - if (res <= 0) { - return LBER_DEFAULT; + /* Are there leftover data bytes inside ber->ber_len? */ + if (ber->ber_ptr < (char *)&ber->ber_usertag) { + if (ber->ber_rwptr < (char *)&ber->ber_usertag) + i = ber->ber_rwptr - ber->ber_ptr; + else + i = (char *)&ber->ber_usertag - ber->ber_ptr; + AC_MEMCPY(buf, ber->ber_ptr, i); + ber->ber_ptr += i; + } else { + i = 0; } - ber->ber_rwptr += res; + ber->ber_len = tlen; - /* convert length. */ - for( to_go = 0; to_go < res ; to_go++ ) { - ber->ber_len <<= 8; - ber->ber_len |= netlen[to_go]; - } + /* now fill the buffer. */ - if (PTR_IN_VAR(ber->ber_rwptr, ber->ber_len)) { + /* make sure length is reasonable */ + if ( ber->ber_len == 0 ) { + errno = ERANGE; + return LBER_DEFAULT; + } else if ( sb->sb_max_incoming && ber->ber_len > sb->sb_max_incoming ) { +#ifdef NEW_LOGGING + LDAP_LOG( BER, ERR, + "ber_get_next: sockbuf_max_incoming limit hit " + "(%d > %d)\n", ber->ber_len, sb->sb_max_incoming, 0 ); +#else + ber_log_printf( LDAP_DEBUG_CONNS, ber->ber_debug, + "ber_get_next: sockbuf_max_incoming limit hit " + "(%ld > %ld)\n", ber->ber_len, sb->sb_max_incoming ); +#endif + errno = ERANGE; return LBER_DEFAULT; } - } - -fill_buffer: - /* now fill the buffer. */ - - /* make sure length is reasonable */ - if ( ber->ber_len == 0 || - ( sb->sb_max_incoming && ber->ber_len > sb->sb_max_incoming )) - { - errno = ERANGE; - return LBER_DEFAULT; - } - if (ber->ber_buf==NULL) { - ber->ber_buf = (char *) LBER_MALLOC( ber->ber_len ); if (ber->ber_buf==NULL) { - return LBER_DEFAULT; + ber_len_t l = ber->ber_rwptr - ber->ber_ptr; + /* ber->ber_ptr is always <= ber->ber->ber_rwptr. + * make sure ber->ber_len agrees with what we've + * already read. + */ + if ( ber->ber_len < i + l ) { + errno = ERANGE; + return LBER_DEFAULT; + } + ber->ber_buf = (char *) LBER_MALLOC( ber->ber_len + 1 ); + if (ber->ber_buf==NULL) { + return LBER_DEFAULT; + } + ber->ber_end = ber->ber_buf + ber->ber_len; + if (i) { + AC_MEMCPY(ber->ber_buf, buf, i); + } + if (l > 0) { + AC_MEMCPY(ber->ber_buf + i, ber->ber_ptr, l); + i += l; + } + ber->ber_ptr = ber->ber_buf; + ber->ber_usertag = 0; + if ((ber_len_t)i == ber->ber_len) { + goto done; + } + ber->ber_rwptr = ber->ber_buf + i; } - ber->ber_rwptr = ber->ber_buf; - ber->ber_ptr = ber->ber_buf; - ber->ber_end = ber->ber_buf + ber->ber_len; } if ((ber->ber_rwptr>=ber->ber_buf) && (ber->ber_rwptrber_end)) { @@ -597,15 +617,16 @@ fill_buffer: #endif return LBER_DEFAULT; } - +done: ber->ber_rwptr = NULL; *len = ber->ber_len; if ( ber->ber_debug ) { #ifdef NEW_LOGGING - LDAP_LOG(( "liblber", LDAP_LEVEL_DETAIL1, - "ber_get_next: tag 0x%lx len %ld\n", - ber->ber_tag, ber->ber_len )); - BER_DUMP(( "liblber", LDAP_LEVEL_DETAIL2, ber, 1 )); + LDAP_LOG( BER, DETAIL1, + "ber_get_next: tag 0x%lx len %ld\n", + ber->ber_tag, ber->ber_len, 0 ); + if(LDAP_LOGS_TEST(BER, DETAIL2)) + BER_DUMP(( "liblber", LDAP_LEVEL_DETAIL2, ber, 1 )); #else ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug, "ber_get_next: tag 0x%lx len %ld contents:\n",