From: Howard Chu Date: Thu, 28 Aug 2014 17:21:21 +0000 (+0100) Subject: ITS#7702 better fix X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=9a8cb6091aaae1f4a3116962722b8f0421a90150;p=openldap ITS#7702 better fix Check for duplicate scopes in search_aliases, not later. --- diff --git a/servers/slapd/back-mdb/dn2id.c b/servers/slapd/back-mdb/dn2id.c index f54ab998e9..06e6ad3f92 100644 --- a/servers/slapd/back-mdb/dn2id.c +++ b/servers/slapd/back-mdb/dn2id.c @@ -778,6 +778,53 @@ mdb_idscopes( return MDB_SUCCESS; } +/* See if ID is a child of any of the scopes, + * return MDB_KEYEXIST if so. + */ +int +mdb_idscopechk( + Operation *op, + IdScopes *isc ) +{ + struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; + MDB_val key, data; + ID id, prev; + char *ptr; + int rc = 0; + unsigned int x; + + key.mv_size = sizeof(ID); + + if ( !isc->mc ) { + rc = mdb_cursor_open( isc->mt, mdb->mi_dn2id, &isc->mc ); + if ( rc ) return rc; + } + + id = isc->id; + + while (id) { + if ( !rc ) { + key.mv_data = &id; + rc = mdb_cursor_get( isc->mc, &key, &data, MDB_SET ); + if ( rc ) + return rc; + } + + ptr = data.mv_data; + ptr += data.mv_size - sizeof(ID); + prev = id; + memcpy( &id, ptr, sizeof(ID) ); + /* If we didn't advance, some parent is missing */ + if ( id == prev ) + return MDB_NOTFOUND; + + x = mdb_id2l_search( isc->scopes, id ); + if ( x <= isc->scopes[0].mid && isc->scopes[x].mid == id ) + return MDB_KEYEXIST; + } + return MDB_SUCCESS; +} + int mdb_dn2id_walk( Operation *op, diff --git a/servers/slapd/back-mdb/proto-mdb.h b/servers/slapd/back-mdb/proto-mdb.h index 3671425dbf..713900192a 100644 --- a/servers/slapd/back-mdb/proto-mdb.h +++ b/servers/slapd/back-mdb/proto-mdb.h @@ -138,6 +138,10 @@ int mdb_idscopes( Operation *op, struct IdScopes *isc ); +int mdb_idscopechk( + Operation *op, + struct IdScopes *isc ); + int mdb_dn2id_walk( Operation *op, struct IdScopes *isc ); diff --git a/servers/slapd/back-mdb/search.c b/servers/slapd/back-mdb/search.c index cbb66f7463..98b5f2557f 100644 --- a/servers/slapd/back-mdb/search.c +++ b/servers/slapd/back-mdb/search.c @@ -31,10 +31,9 @@ static int search_candidates( Operation *op, SlapReply *rs, Entry *e, - MDB_txn *txn, + IdScopes *isc, MDB_cursor *mci, ID *ids, - ID2L scopes, ID *stack ); static int parse_paged_cookie( Operation *op, SlapReply *rs ); @@ -131,9 +130,8 @@ static int search_aliases( Operation *op, SlapReply *rs, ID e_id, - MDB_txn *txn, + IdScopes *isc, MDB_cursor *mci, - ID2L scopes, ID *stack ) { ID *aliases, *curscop, *visited, *newsubs, *oldsubs, *tmp; @@ -159,7 +157,7 @@ static int search_aliases( /* Find all aliases in database */ MDB_IDL_ZERO( aliases ); - rs->sr_err = mdb_filter_candidates( op, txn, &af, aliases, + rs->sr_err = mdb_filter_candidates( op, isc->mt, &af, aliases, curscop, visited ); if (rs->sr_err != LDAP_SUCCESS || MDB_IDL_IS_ZERO( aliases )) { return rs->sr_err; @@ -177,7 +175,7 @@ static int search_aliases( /* Set curscop to only the aliases in the current scope. Start with * all the aliases, then get the intersection with the scope. */ - rs->sr_err = mdb_idscope( op, txn, e_id, aliases, curscop ); + rs->sr_err = mdb_idscope( op, isc->mt, e_id, aliases, curscop ); /* Dereference all of the aliases in the current scope. */ cursora = 0; @@ -199,7 +197,7 @@ static int search_aliases( /* Actually dereference the alias */ MDB_IDL_ZERO(tmp); - a = deref_base( op, rs, a, &matched, txn, + a = deref_base( op, rs, a, &matched, isc->mt, tmp, visited ); if (a) { /* If the target was not already in our current scopes, @@ -208,10 +206,18 @@ static int search_aliases( ID2 mid; mid.mid = a->e_id; mid.mval.mv_data = NULL; - if (mdb_id2l_insert(scopes, &mid) == 0) { + if (op->ors_scope == LDAP_SCOPE_SUBTREE) { + isc->id = a->e_id; + /* if ID is a child of any of our current scopes, + * ignore it, it's already included. + */ + if (mdb_idscopechk(op, isc)) + goto skip; + } + if (mdb_id2l_insert(isc->scopes, &mid) == 0) { mdb_idl_insert(newsubs, a->e_id); } - mdb_entry_return( op, a ); +skip: mdb_entry_return( op, a ); } else if (matched) { /* Alias could not be dereferenced, or it deref'd to @@ -639,7 +645,7 @@ dn2entry_retry: scopes[1].mid = base->e_id; scopes[1].mval.mv_data = NULL; rs->sr_err = search_candidates( op, rs, base, - ltid, mci, candidates, scopes, stack ); + &isc, mci, candidates, stack ); ncand = MDB_IDL_N( candidates ); if ( !base->e_id || ncand == NOID ) { /* grab entry count from id2entry stat @@ -1274,10 +1280,9 @@ static int search_candidates( Operation *op, SlapReply *rs, Entry *e, - MDB_txn *txn, + IdScopes *isc, MDB_cursor *mci, ID *ids, - ID2L scopes, ID *stack ) { struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; @@ -1340,13 +1345,13 @@ static int search_candidates( } if( op->ors_deref & LDAP_DEREF_SEARCHING ) { - rc = search_aliases( op, rs, e->e_id, txn, mci, scopes, stack ); + rc = search_aliases( op, rs, e->e_id, isc, mci, stack ); } else { rc = LDAP_SUCCESS; } if ( rc == LDAP_SUCCESS ) { - rc = mdb_filter_candidates( op, txn, f, ids, + rc = mdb_filter_candidates( op, isc->mt, f, ids, stack, stack+MDB_IDL_UM_SIZE ); }