[Date Prev][Date Next] [Chronological] [Thread] [Top]

(ITS#4533) Old request buffer is written to when following referrals



Full_Name: Kalle Svensson
Version: 2.3.20
OS: Solaris 9
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (81.93.143.194)


Hello openLDAP team!

I found a problem related to referrals. The re_encode_reqest() function in
libraries/libldap/request.c is replacing the DN in the original request with the
DN provided in the referral message. It is using ber_scanf()'s in-place format
string directive ("m") to read the original DN, and thus writing a \0 to the
original buffer and destroying the byte following immediately after the DN.
Here is a patch that uses the "o" directive instead:

*** request.c   Tue May  9 09:19:08 2006
--- request.c.fixed     Tue May  9 09:19:22 2006
***************
*** 1247,1253 ****
        ber_int_t       scope;
        int             rc;
        BerElement      tmpber, *ber;
!       struct berval           orig_dn;
        char            *dn;
  
        Debug( LDAP_DEBUG_TRACE,
--- 1247,1253 ----
        ber_int_t       scope;
        int             rc;
        BerElement      tmpber, *ber;
!       struct berval   *orig_dn;
        char            *dn;
  
        Debug( LDAP_DEBUG_TRACE,
***************
*** 1270,1287 ****
                return( NULL );
        }
  
        assert( tag != 0);
        if ( tag == LDAP_REQ_BIND ) {
                /* bind requests have a version number before the DN & other
stu
ff */
!               rtag = ber_scanf( &tmpber, "{im" /*}*/, &ver, &orig_dn );
  
        } else if ( tag == LDAP_REQ_DELETE ) {
                /* delete requests don't have a DN wrapping sequence */
!               rtag = ber_scanf( &tmpber, "m", &orig_dn );
  
        } else if ( tag == LDAP_REQ_SEARCH ) {
                /* search requests need to be re-scope-ed */
!               rtag = ber_scanf( &tmpber, "{me" /*"}"*/, &orig_dn, &scope );
  
                if( srv->lud_scope != LDAP_SCOPE_DEFAULT ) {
                        /* use the scope provided in reference */
--- 1270,1292 ----
                return( NULL );
        }
  
+         orig_dn = ( struct berval *) ber_memcalloc( 1, sizeof( struct berval
)
 );
+         if ( orig_dn == NULL ) {
+             return( NULL );
+         }
+ 
        assert( tag != 0);
        if ( tag == LDAP_REQ_BIND ) {
                /* bind requests have a version number before the DN & other
stu
ff */
!               rtag = ber_scanf( &tmpber, "{io" /*}*/, &ver, orig_dn );
  
        } else if ( tag == LDAP_REQ_DELETE ) {
                /* delete requests don't have a DN wrapping sequence */
!               rtag = ber_scanf( &tmpber, "o", orig_dn );
  
        } else if ( tag == LDAP_REQ_SEARCH ) {
                /* search requests need to be re-scope-ed */
!               rtag = ber_scanf( &tmpber, "{oe" /*"}"*/, orig_dn, &scope );
  
                if( srv->lud_scope != LDAP_SCOPE_DEFAULT ) {
                        /* use the scope provided in reference */
***************
*** 1310,1332 ****
                }
  
        } else {
!               rtag = ber_scanf( &tmpber, "{m" /*}*/, &orig_dn );
        }
  
        if( rtag == LBER_ERROR ) {
                ld->ld_errno = LDAP_DECODING_ERROR;
                return NULL;
        }
  
        if (( ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
                return NULL;
        }
  
        if ( srv->lud_dn == NULL ) {
!               dn = orig_dn.bv_val;
        } else {
!               dn = srv->lud_dn;
        }
  
        if ( tag == LDAP_REQ_BIND ) {
                rc = ber_printf( ber, "{it{is" /*}}*/, msgid, tag, ver, dn );
--- 1315,1340 ----
                }
  
        } else {
!               rtag = ber_scanf( &tmpber, "{o" /*}*/, orig_dn );
        }
  
        if( rtag == LBER_ERROR ) {
+                 ber_bvfree( orig_dn ); 
                ld->ld_errno = LDAP_DECODING_ERROR;
                return NULL;
        }
  
        if (( ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
+                 ber_bvfree( orig_dn ); 
                return NULL;
        }
  
        if ( srv->lud_dn == NULL ) {
!               dn = ber_strdup( orig_dn->bv_val );
        } else {
!               dn = ber_strdup( srv->lud_dn );
        }
+         ber_bvfree( orig_dn ); 
  
        if ( tag == LDAP_REQ_BIND ) {
                rc = ber_printf( ber, "{it{is" /*}}*/, msgid, tag, ver, dn );
***************
*** 1337,1342 ****
--- 1345,1351 ----
        } else {
                rc = ber_printf( ber, "{it{s" /*}}*/, msgid, tag, dn );
        }
+         ber_memfree( dn );
  
        if ( rc == -1 ) {
                ld->ld_errno = LDAP_ENCODING_ERROR;