From: Howard Chu Date: Mon, 26 Oct 2009 18:49:42 +0000 (+0000) Subject: ITS#6327 fix sb_sasl_generic_write retval for partial writes X-Git-Tag: ACLCHECK_0~169 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=1155f5ff2084b5d165ab07530991b945488a615b;p=openldap ITS#6327 fix sb_sasl_generic_write retval for partial writes --- diff --git a/include/ldap_pvt.h b/include/ldap_pvt.h index 85c0345b48..bcf0f161a2 100644 --- a/include/ldap_pvt.h +++ b/include/ldap_pvt.h @@ -297,6 +297,8 @@ struct sb_sasl_generic_data { const struct sb_sasl_generic_ops *ops; void *ops_private; Sockbuf_IO_Desc *sbiod; + int flags; +#define LDAP_PVT_SASL_PARTIAL_WRITE 1 ber_len_t min_send; ber_len_t max_send; ber_len_t max_recv; diff --git a/libraries/libldap/sasl.c b/libraries/libldap/sasl.c index 5fb209ace0..dca65d93b5 100644 --- a/libraries/libldap/sasl.c +++ b/libraries/libldap/sasl.c @@ -503,6 +503,7 @@ sb_sasl_generic_setup( Sockbuf_IO_Desc *sbiod, void *arg ) p->ops = i->ops; p->ops_private = i->ops_private; p->sbiod = sbiod; + p->flags = 0; ber_pvt_sb_buf_init( &p->sec_buf_in ); ber_pvt_sb_buf_init( &p->buf_in ); ber_pvt_sb_buf_init( &p->buf_out ); @@ -678,6 +679,7 @@ 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, sent; assert( sbiod != NULL ); assert( SOCKBUF_VALID( sbiod->sbiod_sb ) ); @@ -696,14 +698,25 @@ sb_sasl_generic_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) } } + /* If we're just retrying a partial write, ignore + * the first byte of this request since we fudged it + * below on the previous call. + */ + if ( p->flags & LDAP_PVT_SASL_PARTIAL_WRITE ) { + p->flags ^= LDAP_PVT_SASL_PARTIAL_WRITE; + len--; + if ( !len ) + return 1; + buf = (char *)buf + 1; + } + /* now encode the next packet. */ p->ops->reset_buf( p, &p->buf_out ); - if ( len > p->max_send - 100 ) { - len = p->max_send - 100; /* For safety margin */ - } + len2 = p->max_send - 100; /* For safety margin */ + len2 = len > len2 ? len2 : len; - ret = p->ops->encode( p, buf, len, &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, @@ -712,12 +725,21 @@ sb_sasl_generic_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) return -1; } - ret = ber_pvt_sb_do_write( sbiod, &p->buf_out ); + sent = ber_pvt_sb_do_write( sbiod, &p->buf_out ); + + if ( sent < 0 ) { + /* error? */ + len2 = sent; + } else if ( sent != p->buf_out.buf_end ) { + /* partial write? */ + len2--; + p->flags |= LDAP_PVT_SASL_PARTIAL_WRITE; + } /* return number of bytes encoded, not written, to ensure * no byte is encoded twice (even if only sent once). */ - return len; + return len2; } static int