From: Hallvard Furuseth Date: Tue, 11 Nov 2008 23:49:00 +0000 (+0000) Subject: ITS#5408 part 7 - Search operation bugs in r_enum_tree(). X-Git-Tag: ACLCHECK_0~1119 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=7c3cba840cb0220e8ca6a42a663c3dc0b9f42fde;p=openldap ITS#5408 part 7 - Search operation bugs in r_enum_tree(). - Do not modify op->ors_scope, pass scope parameter instead. - Save copies of dn/ndn before sending with REP_ENTRY_MODIFIABLE. - Only the search baseDN may produce noSuchObject. - More accurate result code. --- diff --git a/servers/slapd/back-ldif/ldif.c b/servers/slapd/back-ldif/ldif.c index 330bb34aeb..a7474c28e9 100644 --- a/servers/slapd/back-ldif/ldif.c +++ b/servers/slapd/back-ldif/ldif.c @@ -554,20 +554,33 @@ typedef struct bvlist { static int r_enum_tree(enumCookie *ck, struct berval *path, int base, - struct berval *pdn, struct berval *pndn) + int scope, struct berval *pdn, struct berval *pndn) { Entry *e = NULL; int fd = 0, rc = LDAP_SUCCESS; + struct berval dn = BER_BVC( "" ), ndn = BER_BVC( "" ); - if ( !base ) { + if ( base <= 0 ) { rc = ldif_read_entry( ck->op, path->bv_val, pdn, pndn, &e, ck->rs == NULL ? NULL : &ck->rs->sr_text ); if ( rc != LDAP_SUCCESS ) { - return LDAP_NO_SUCH_OBJECT; + /* Only the search baseDN may produce noSuchObject. */ + return rc == LDAP_NO_SUCH_OBJECT && base ? LDAP_OTHER : rc; } - if ( ck->op->ors_scope == LDAP_SCOPE_BASE || - ck->op->ors_scope == LDAP_SCOPE_SUBTREE ) { + if ( scope != LDAP_SCOPE_BASE ) { + /* Copy DN/NDN since we send the entry with REP_ENTRY_MODIFIABLE, + * which bconfig.c seems to need. (TODO: see config_rename_one.) + */ + if ( ber_dupbv( &dn, &e->e_name ) == NULL || + ber_dupbv( &ndn, &e->e_nname ) == NULL ) + { + rc = LDAP_OTHER; + goto done; + } + } + + if ( scope == LDAP_SCOPE_BASE || scope == LDAP_SCOPE_SUBTREE ) { /* Send right away? */ if ( ck->rs ) { /* @@ -581,7 +594,7 @@ static int r_enum_tree(enumCookie *ck, struct berval *path, int base, BerVarray erefs = get_entry_referrals( ck->op, e ); ck->rs->sr_ref = referral_rewrite( erefs, &e->e_name, NULL, - ck->op->ors_scope ); + scope ); ck->rs->sr_entry = e; rc = send_search_reference( ck->op, ck->rs ); @@ -620,7 +633,7 @@ static int r_enum_tree(enumCookie *ck, struct berval *path, int base, } } - if ( ck->op->ors_scope != LDAP_SCOPE_BASE ) { + if ( scope != LDAP_SCOPE_BASE ) { DIR * dir_of_path; bvlist *list = NULL, *ptr; @@ -686,10 +699,10 @@ static int r_enum_tree(enumCookie *ck, struct berval *path, int base, } closedir(dir_of_path); - if (ck->op->ors_scope == LDAP_SCOPE_ONELEVEL) - ck->op->ors_scope = LDAP_SCOPE_BASE; - else if ( ck->op->ors_scope == LDAP_SCOPE_SUBORDINATE) - ck->op->ors_scope = LDAP_SCOPE_SUBTREE; + if ( scope == LDAP_SCOPE_ONELEVEL ) + scope = LDAP_SCOPE_BASE; + else if ( scope == LDAP_SCOPE_SUBORDINATE ) + scope = LDAP_SCOPE_SUBTREE; while ( ( ptr = list ) ) { struct berval fpath; @@ -701,9 +714,7 @@ static int r_enum_tree(enumCookie *ck, struct berval *path, int base, AC_MEMCPY( ptr->bv.bv_val + ptr->off, ptr->num.bv_val, ptr->num.bv_len ); fullpath( path, &ptr->bv, &fpath ); - rc = r_enum_tree(ck, &fpath, 0, - e != NULL ? &e->e_name : pdn, - e != NULL ? &e->e_nname : pndn ); + rc = r_enum_tree( ck, &fpath, 0, scope, &dn, &ndn ); free(fpath.bv_val); } if ( ptr->num.bv_val ) @@ -714,6 +725,10 @@ static int r_enum_tree(enumCookie *ck, struct berval *path, int base, } done: if ( fd ) entry_free( e ); + if ( !BER_BVISEMPTY( &dn ) ) + ber_memfree( dn.bv_val ); + if ( !BER_BVISEMPTY( &ndn ) ) + ber_memfree( ndn.bv_val ); return rc; } @@ -729,7 +744,8 @@ enum_tree( dnParent( &ck->op->o_req_dn, &pdn ); dnParent( &ck->op->o_req_ndn, &pndn ); dn2path( ck->op->o_bd, &ck->op->o_req_ndn, &path ); - rc = r_enum_tree(ck, &path, BER_BVISEMPTY( &ck->op->o_req_ndn ) ? 1 : 0, &pdn, &pndn); + rc = r_enum_tree( ck, &path, BER_BVISEMPTY( &ck->op->o_req_ndn ) ? 1 : -1, + ck->op->ors_scope, &pdn, &pndn ); ch_free( path.bv_val ); return rc; }