From cac00c6a97bbbbcec75f2ebcffaae1dd1769a28e Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Tue, 26 Aug 2014 20:07:40 +0100 Subject: [PATCH] ITS#7702 fix results with aliases Aliases pointing within the original search scope could cause the same entry to be returned multiple times. Check for subtree scope and duplicate scopes. --- servers/slapd/back-mdb/dn2id.c | 8 +++++++- servers/slapd/back-mdb/proto-mdb.h | 3 ++- servers/slapd/back-mdb/search.c | 17 ++++++++++------- servers/slapd/back-mdb/tools.c | 2 +- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/servers/slapd/back-mdb/dn2id.c b/servers/slapd/back-mdb/dn2id.c index f54ab998e9..e658b625f3 100644 --- a/servers/slapd/back-mdb/dn2id.c +++ b/servers/slapd/back-mdb/dn2id.c @@ -556,7 +556,8 @@ mdb_id2name( MDB_cursor **cursp, ID id, struct berval *name, - struct berval *nname ) + struct berval *nname, + ID *iscopes ) { struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; MDB_dbi dbi = mdb->mi_dn2id; @@ -589,6 +590,11 @@ mdb_id2name( ptr = data.mv_data; ptr += data.mv_size - sizeof(ID); memcpy( &id, ptr, sizeof(ID) ); + if ( iscopes ) { + rc = mdb_idl_search( iscopes, id ); + if ( iscopes[rc] == id ) + return MDB_KEYEXIST; + } d = data.mv_data; nrlen = (d->nrdnlen[0] << 8) | d->nrdnlen[1]; rlen = data.mv_size - sizeof(diskNode) - nrlen; diff --git a/servers/slapd/back-mdb/proto-mdb.h b/servers/slapd/back-mdb/proto-mdb.h index 3671425dbf..99e2828dea 100644 --- a/servers/slapd/back-mdb/proto-mdb.h +++ b/servers/slapd/back-mdb/proto-mdb.h @@ -123,7 +123,8 @@ int mdb_id2name( MDB_cursor **cursp, ID eid, struct berval *name, - struct berval *nname); + struct berval *nname, + ID *iscopes ); int mdb_idscope( Operation *op, diff --git a/servers/slapd/back-mdb/search.c b/servers/slapd/back-mdb/search.c index d90125e8e4..f0eec7e524 100644 --- a/servers/slapd/back-mdb/search.c +++ b/servers/slapd/back-mdb/search.c @@ -722,12 +722,9 @@ dn2entry_retry: if (scopes[0].mid > 1) { cursor = 1; for (cscope = 1; cscope <= scopes[0].mid; cscope++) { - /* Ignore the original base */ - if (scopes[cscope].mid == base->e_id) - continue; iscopes[cursor++] = scopes[cscope].mid; } - iscopes[0] = scopes[0].mid - 1; + iscopes[0] = scopes[0].mid; } else { iscopes[0] = 0; } @@ -740,7 +737,7 @@ dn2entry_retry: id = NOID; else id = isc.id; - cscope = 0; + cscope = 1; /* skip original base */ } else { id = mdb_idl_first( candidates, &cursor ); wwctx.mcd = NULL; @@ -952,7 +949,7 @@ notfound: pdn = base->e_name; pndn = base->e_nname; } else { - mdb_id2name( op, ltid, &isc.mc, scopes[isc.nscope].mid, &pdn, &pndn ); + mdb_id2name( op, ltid, &isc.mc, scopes[isc.nscope].mid, &pdn, &pndn, NULL ); } e->e_name.bv_len = pdn.bv_len; e->e_nname.bv_len = pndn.bv_len; @@ -1129,7 +1126,13 @@ loop_continue: mdb_entry_return( op, base ); rs->sr_err = mdb_id2entry(op, mci, isc.id, &base); if ( !rs->sr_err ) { - mdb_id2name( op, ltid, &isc.mc, isc.id, &base->e_name, &base->e_nname ); + rc = mdb_id2name( op, ltid, &isc.mc, isc.id, &base->e_name, &base->e_nname, + op->ors_scope == LDAP_SCOPE_SUBTREE ? iscopes : NULL ); + if ( rc == MDB_KEYEXIST ) { + mdb_entry_return( op, base ); + base = NULL; + continue; + } isc.numrdns = 0; if (isc.oscope == LDAP_SCOPE_ONELEVEL) isc.oscope = LDAP_SCOPE_BASE; diff --git a/servers/slapd/back-mdb/tools.c b/servers/slapd/back-mdb/tools.c index a84de6f4c8..7ccf824482 100644 --- a/servers/slapd/back-mdb/tools.c +++ b/servers/slapd/back-mdb/tools.c @@ -380,7 +380,7 @@ mdb_tool_entry_get_int( BackendDB *be, ID id, Entry **ep ) op.o_tmpmemctx = NULL; op.o_tmpmfuncs = &ch_mfuncs; if ( slapMode & SLAP_TOOL_READONLY ) { - rc = mdb_id2name( &op, mdb_tool_txn, &idcursor, id, &dn, &ndn ); + rc = mdb_id2name( &op, mdb_tool_txn, &idcursor, id, &dn, &ndn, NULL ); if ( rc ) { rc = LDAP_OTHER; if ( e ) { -- 2.39.5