]> git.sur5r.net Git - openldap/commitdiff
ITS#6327,ITS#6334
authorQuanah Gibson-Mount <quanah@openldap.org>
Sat, 31 Oct 2009 01:11:22 +0000 (01:11 +0000)
committerQuanah Gibson-Mount <quanah@openldap.org>
Sat, 31 Oct 2009 01:11:22 +0000 (01:11 +0000)
CHANGES
include/ldap_pvt.h
libraries/libldap/sasl.c

diff --git a/CHANGES b/CHANGES
index cdb2d6b3a09c5a110ff1e2d477278e51f8faa137..542dfd5ff19acdc1899667d4f9eaf921d8aff975 100644 (file)
--- 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)
index 49138125636c5125f68f24ca706c6612606e48b7..85a811c41e28d85da2778d6d7d8a26286fcb4d79 100644 (file)
@@ -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
index 5fb209ace00c1a8c10c5307f178fee295c4916f2..29fa3b2df41c15fbb7123e960bca9c079fa870f2 100644 (file)
@@ -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