static ber_slen_t sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { ber_slen_t ret; char ebuf[128]; ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len ); if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) { int err = sock_errno(); if ( ret < 0 ) { ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, "%swrite: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt, (long)len, AC_STRERROR_R( err, ebuf, sizeof ebuf ) ); } else { ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, "%swrite: want=%ld, written=%ld\n", (char *)sbiod->sbiod_pvt, (long)len, (long)ret ); ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, (const char *)buf, ret ); } sock_errset(err); } return ret; }
/* * Write to the ber buffer. * Note that ber_start_seqorset/ber_put_seqorset() bypass ber_write(). */ ber_slen_t ber_write( BerElement *ber, LDAP_CONST char *buf, ber_len_t len, int zero ) /* nonzero is unsupported from OpenLDAP 2.4.18 */ { char **p; assert( ber != NULL ); assert( buf != NULL ); assert( LBER_VALID( ber ) ); if ( zero != 0 ) { ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug, "%s", "ber_write: nonzero 4th argument not supported\n" ); return( -1 ); } p = ber->ber_sos_ptr == NULL ? &ber->ber_ptr : &ber->ber_sos_ptr; if ( len > (ber_len_t) (ber->ber_end - *p) ) { if ( ber_realloc( ber, len ) != 0 ) return( -1 ); } AC_MEMCPY( *p, buf, len ); *p += len; return( (ber_slen_t) len ); }
static ber_len_t sb_sasl_generic_pkt_length( struct sb_sasl_generic_data *p, const unsigned char *buf, int debuglevel ) { ber_len_t size; assert( buf != NULL ); size = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; if ( size > p->max_recv ) { /* somebody is trying to mess me up. */ ber_log_printf( LDAP_DEBUG_ANY, debuglevel, "sb_sasl_generic_pkt_length: " "received illegal packet length of %lu bytes\n", (unsigned long)size ); size = 16; /* this should lead to an error. */ } return size + 4; /* include the size !!! */ }
static ber_slen_t sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len ) { ber_slen_t ret; ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len ); if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) { int err = errno; if ( ret < 0 ) { ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt, (long)len, STRERROR( errno ) ); } else { ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt, (long)len, (long)ret ); ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug, (const char *)buf, ret ); } errno = err; } return ret; }
int ber_flush2( Sockbuf *sb, BerElement *ber, int freeit ) { ber_len_t towrite; ber_slen_t rc; assert( sb != NULL ); assert( ber != NULL ); assert( SOCKBUF_VALID( sb ) ); assert( LBER_VALID( ber ) ); if ( ber->ber_rwptr == NULL ) { ber->ber_rwptr = ber->ber_buf; } towrite = ber->ber_ptr - ber->ber_rwptr; if ( sb->sb_debug ) { ber_log_printf( LDAP_DEBUG_TRACE, sb->sb_debug, "ber_flush2: %ld bytes to sd %ld%s\n", towrite, (long) sb->sb_fd, ber->ber_rwptr != ber->ber_buf ? " (re-flush)" : "" ); ber_log_bprint( LDAP_DEBUG_BER, sb->sb_debug, ber->ber_rwptr, towrite ); } while ( towrite > 0 ) { #ifdef LBER_TRICKLE sleep(1); rc = ber_int_sb_write( sb, ber->ber_rwptr, 1 ); #else rc = ber_int_sb_write( sb, ber->ber_rwptr, towrite ); #endif if ( rc <= 0 ) { if ( freeit & LBER_FLUSH_FREE_ON_ERROR ) ber_free( ber, 1 ); return -1; } towrite -= rc; ber->ber_rwptr += rc; } if ( freeit & LBER_FLUSH_FREE_ON_SUCCESS ) ber_free( ber, 1 ); return 0; }
static ber_slen_t sb_sasl_generic_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) { struct sb_sasl_generic_data *p; int ret; ber_len_t len2; assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); p = (struct sb_sasl_generic_data *)sbiod->sbiod_pvt; /* Is there anything left in the buffer? */ if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) { ret = ber_pvt_sb_do_write( sbiod, &p->buf_out ); if ( ret < 0 ) return ret; /* Still have something left?? */ if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) { sock_errset(EAGAIN); return -1; } } len2 = p->max_send - 100; /* For safety margin */ len2 = len > len2 ? len2 : len; /* If we're just retrying a partial write, tell the * caller it's done. Let them call again if there's * still more left to write. */ if ( p->flags & LDAP_PVT_SASL_PARTIAL_WRITE ) { p->flags ^= LDAP_PVT_SASL_PARTIAL_WRITE; return len2; } /* now encode the next packet. */ p->ops->reset_buf( p, &p->buf_out ); ret = p->ops->encode( p, buf, len2, &p->buf_out ); if ( ret != 0 ) { ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug, "sb_sasl_generic_write: failed to encode packet\n" ); sock_errset(EIO); return -1; } ret = ber_pvt_sb_do_write( sbiod, &p->buf_out ); if ( ret < 0 ) { /* error? */ int err = sock_errno(); /* caller can retry this */ if ( err == EAGAIN || err == EWOULDBLOCK || err == EINTR ) p->flags |= LDAP_PVT_SASL_PARTIAL_WRITE; return ret; } else if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) { /* partial write? pretend nothing got written */ p->flags |= LDAP_PVT_SASL_PARTIAL_WRITE; sock_errset(EAGAIN); len2 = -1; } /* return number of bytes encoded, not written, to ensure * no byte is encoded twice (even if only sent once). */ return len2; }
static ber_slen_t sb_sasl_generic_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) { struct sb_sasl_generic_data *p; ber_slen_t ret, bufptr; assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); p = (struct sb_sasl_generic_data *)sbiod->sbiod_pvt; /* Are there anything left in the buffer? */ ret = ber_pvt_sb_copy_out( &p->buf_in, buf, len ); bufptr = ret; len -= ret; if ( len == 0 ) return bufptr; p->ops->reset_buf( p, &p->buf_in ); /* Read the length of the packet */ while ( p->sec_buf_in.buf_ptr < 4 ) { ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base + p->sec_buf_in.buf_ptr, 4 - p->sec_buf_in.buf_ptr ); #ifdef EINTR if ( ( ret < 0 ) && ( errno == EINTR ) ) continue; #endif if ( ret <= 0 ) return bufptr ? bufptr : ret; p->sec_buf_in.buf_ptr += ret; } /* The new packet always starts at p->sec_buf_in.buf_base */ ret = sb_sasl_generic_pkt_length(p, (unsigned char *) p->sec_buf_in.buf_base, sbiod->sbiod_sb->sb_debug ); /* Grow the packet buffer if neccessary */ if ( ( p->sec_buf_in.buf_size < (ber_len_t) ret ) && ber_pvt_sb_grow_buffer( &p->sec_buf_in, ret ) < 0 ) { sock_errset(ENOMEM); return -1; } p->sec_buf_in.buf_end = ret; /* Did we read the whole encrypted packet? */ while ( p->sec_buf_in.buf_ptr < p->sec_buf_in.buf_end ) { /* No, we have got only a part of it */ ret = p->sec_buf_in.buf_end - p->sec_buf_in.buf_ptr; ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base + p->sec_buf_in.buf_ptr, ret ); #ifdef EINTR if ( ( ret < 0 ) && ( errno == EINTR ) ) continue; #endif if ( ret <= 0 ) return bufptr ? bufptr : ret; p->sec_buf_in.buf_ptr += ret; } /* Decode the packet */ ret = p->ops->decode( p, &p->sec_buf_in, &p->buf_in ); /* Drop the packet from the input buffer */ sb_sasl_generic_drop_packet( p, sbiod->sbiod_sb->sb_debug ); if ( ret != 0 ) { ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug, "sb_sasl_generic_read: failed to decode packet\n" ); sock_errset(EIO); return -1; } bufptr += ber_pvt_sb_copy_out( &p->buf_in, (char*) buf + bufptr, len ); return bufptr; }