From 98ea063e442a87f22f869ccd94b0a66c9c9561cb Mon Sep 17 00:00:00 2001 From: Quanah Gibson-Mount Date: Sat, 31 Oct 2009 01:11:22 +0000 Subject: [PATCH] ITS#6327,ITS#6334 --- CHANGES | 1 + include/ldap_pvt.h | 2 ++ libraries/libldap/sasl.c | 37 ++++++++++++++++++++++++++++++------- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/CHANGES b/CHANGES index cdb2d6b3a0..542dfd5ff1 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,7 @@ OpenLDAP 2.4 Change Log OpenLDAP 2.4.20 Engineering Fixed liblber inverted LBER_USE_DER test (ITS#6348) Fixed liblber to return failure on certain failures (ITS#6344) + Fixed libldap sasl buffer sizing (ITS#6327,ITS#6334) Fixed libldap uninitialized return value (ITS#6355) Fixed liblutil constant (ITS#5909) Added slapd handling of hex server IDs (ITS#6297) diff --git a/include/ldap_pvt.h b/include/ldap_pvt.h index 4913812563..85a811c41e 100644 --- a/include/ldap_pvt.h +++ b/include/ldap_pvt.h @@ -262,6 +262,8 @@ struct sb_sasl_generic_data { Sockbuf_Buf sec_buf_in; Sockbuf_Buf buf_in; Sockbuf_Buf buf_out; + unsigned int flags; +#define LDAP_PVT_SASL_PARTIAL_WRITE 1 }; #ifndef LDAP_PVT_SASL_LOCAL_SSF diff --git a/libraries/libldap/sasl.c b/libraries/libldap/sasl.c index 5fb209ace0..29fa3b2df4 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,13 +679,14 @@ 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; - /* Are there anything left in the buffer? */ + /* 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; @@ -696,14 +698,22 @@ sb_sasl_generic_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) } } - /* now encode the next packet. */ - p->ops->reset_buf( p, &p->buf_out ); + len2 = p->max_send - 100; /* For safety margin */ + len2 = len > len2 ? len2 : len; - if ( len > p->max_send - 100 ) { - len = p->max_send - 100; /* For safety margin */ + /* 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; } - ret = p->ops->encode( p, buf, len, &p->buf_out ); + /* 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, @@ -714,10 +724,23 @@ sb_sasl_generic_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) 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 */ + len2 = 0; + 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 -- 2.39.5