📄 search.c
字号:
} else#endif /* SLAP_ACL_HONOR_DISCLOSE */ { ber_dupbv( &matched_dn, &matched->e_name ); erefs = is_entry_referral( matched ) ? get_entry_referrals( op, matched ) : NULL; if ( rs->sr_err == DB_NOTFOUND ) rs->sr_err = LDAP_REFERRAL; rs->sr_matched = matched_dn.bv_val; }#ifdef SLAP_ZONE_ALLOC slap_zn_runlock(bdb->bi_cache.c_zctx, matched);#endif bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, matched, &lock); matched = NULL; if ( erefs ) { rs->sr_ref = referral_rewrite( erefs, &matched_dn, &op->o_req_dn, op->oq_search.rs_scope ); ber_bvarray_free( erefs ); } } else {#ifdef SLAP_ZONE_ALLOC slap_zn_runlock(bdb->bi_cache.c_zctx, matched);#endif rs->sr_ref = referral_rewrite( default_referral, NULL, &op->o_req_dn, op->oq_search.rs_scope ); rs->sr_err = rs->sr_ref != NULL ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT; } send_ldap_result( op, rs ); if ( !opinfo ) LOCK_ID_FREE (bdb->bi_dbenv, locker ); if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } if ( !BER_BVISNULL( &matched_dn ) ) { ber_memfree( matched_dn.bv_val ); rs->sr_matched = NULL; } return rs->sr_err; }#ifdef SLAP_ACL_HONOR_DISCLOSE /* NOTE: __NEW__ "search" access is required * on searchBase object */ if ( ! access_allowed_mask( op, e, slap_schema.si_ad_entry, NULL, ACL_SEARCH, NULL, &mask ) ) { if ( !ACL_GRANT( mask, ACL_DISCLOSE ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } else { rs->sr_err = LDAP_INSUFFICIENT_ACCESS; }#ifdef SLAP_ZONE_ALLOC slap_zn_runlock(bdb->bi_cache.c_zctx, e);#endif if ( e != &e_root ) { bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock); } send_ldap_result( op, rs ); return rs->sr_err; }#endif /* SLAP_ACL_HONOR_DISCLOSE */ if ( !manageDSAit && e != &e_root && is_entry_referral( e ) ) { /* entry is a referral, don't allow add */ struct berval matched_dn = BER_BVNULL; BerVarray erefs = NULL; ber_dupbv( &matched_dn, &e->e_name ); erefs = get_entry_referrals( op, e ); rs->sr_err = LDAP_REFERRAL;#ifdef SLAP_ZONE_ALLOC slap_zn_runlock(bdb->bi_cache.c_zctx, e);#endif bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock ); e = NULL; if ( erefs ) { rs->sr_ref = referral_rewrite( erefs, &matched_dn, &op->o_req_dn, op->oq_search.rs_scope ); ber_bvarray_free( erefs ); if ( !rs->sr_ref ) { rs->sr_text = "bad_referral object"; } } Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_search) ": entry is referral\n", 0, 0, 0 ); rs->sr_matched = matched_dn.bv_val; send_ldap_result( op, rs ); if ( !opinfo ) { LOCK_ID_FREE (bdb->bi_dbenv, locker ); } ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; ber_memfree( matched_dn.bv_val ); rs->sr_matched = NULL; return 1; } if ( get_assert( op ) && ( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE )) { rs->sr_err = LDAP_ASSERTION_FAILED;#ifdef SLAP_ZONE_ALLOC slap_zn_runlock(bdb->bi_cache.c_zctx, e);#endif if ( e != &e_root ) { bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock); } send_ldap_result( op, rs ); return 1; } /* compute it anyway; root does not use it */ stoptime = op->o_time + op->ors_tlimit; /* need normalized dn below */ ber_dupbv( &realbase, &e->e_nname ); /* Copy info to base, must free entry before accessing the database * in search_candidates, to avoid deadlocks. */ base.e_private = e->e_private; base.e_nname = realbase; base.e_id = e->e_id;#ifdef SLAP_ZONE_ALLOC slap_zn_runlock(bdb->bi_cache.c_zctx, e);#endif if ( e != &e_root ) { bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock); } e = NULL; /* select candidates */ if ( op->oq_search.rs_scope == LDAP_SCOPE_BASE ) { rs->sr_err = base_candidate( op->o_bd, &base, candidates ); } else { BDB_IDL_ZERO( candidates ); BDB_IDL_ZERO( scopes ); rs->sr_err = search_candidates( op, rs, &base, locker, candidates, scopes ); } /* start cursor at beginning of candidates. */ cursor = 0; if ( candidates[0] == 0 ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_search) ": no candidates\n", 0, 0, 0 ); goto nochange; } /* if not root and candidates exceed to-be-checked entries, abort */ if ( op->ors_limit /* isroot == FALSE */ && op->ors_limit->lms_s_unchecked != -1 && BDB_IDL_N(candidates) > (unsigned) op->ors_limit->lms_s_unchecked ) { rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED; send_ldap_result( op, rs ); rs->sr_err = LDAP_SUCCESS; goto done; } if ( op->ors_limit == NULL /* isroot == TRUE */ || !op->ors_limit->lms_s_pr_hide ) { tentries = BDB_IDL_N(candidates); } if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED ) { PagedResultsState *ps = op->o_pagedresults_state; /* deferred cookie parsing */ rs->sr_err = parse_paged_cookie( op, rs ); if ( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto done; } if ( (ID)( ps->ps_cookie ) == 0 ) { id = bdb_idl_first( candidates, &cursor ); } else { if ( ps->ps_size == 0 ) { rs->sr_err = LDAP_SUCCESS; rs->sr_text = "search abandoned by pagedResult size=0"; send_ldap_result( op, rs ); goto done; } for ( id = bdb_idl_first( candidates, &cursor ); id != NOID && id <= (ID)( ps->ps_cookie ); id = bdb_idl_next( candidates, &cursor ) ) { /* empty */; } } if ( cursor == NOID ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_search) ": no paged results candidates\n", 0, 0, 0 ); send_paged_response( op, rs, &lastid, 0 ); rs->sr_err = LDAP_OTHER; goto done; } goto loop_begin; } for ( id = bdb_idl_first( candidates, &cursor ); id != NOID ; id = bdb_idl_next( candidates, &cursor ) ) { int scopeok;loop_begin: /* check for abandon */ if ( op->o_abandon ) { rs->sr_err = SLAPD_ABANDON; goto done; } /* check time limit */ if ( op->ors_tlimit != SLAP_NO_LIMIT && slap_get_time() > stoptime ) { rs->sr_err = LDAP_TIMELIMIT_EXCEEDED; rs->sr_ref = rs->sr_v2ref; send_ldap_result( op, rs ); rs->sr_err = LDAP_SUCCESS; goto done; }fetch_entry_retry: /* get the entry with reader lock */ ei = NULL; rs->sr_err = bdb_cache_find_id( op, ltid, id, &ei, 0, locker, &lock ); if (rs->sr_err == LDAP_BUSY) { rs->sr_text = "ldap server busy"; send_ldap_result( op, rs ); goto done; } else if ( rs->sr_err == DB_LOCK_DEADLOCK || rs->sr_err == DB_LOCK_NOTGRANTED ) { goto fetch_entry_retry; } if ( ei && rs->sr_err == LDAP_SUCCESS ) { e = ei->bei_e; } else { e = NULL; } if ( e == NULL ) { if( !BDB_IDL_IS_RANGE(candidates) ) { /* only complain for non-range IDLs */ Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_search) ": candidate %ld not found\n", (long) id, 0, 0 ); } goto loop_continue; } rs->sr_entry = e; if ( is_entry_subentry( e ) ) { if( op->oq_search.rs_scope != LDAP_SCOPE_BASE ) { if(!get_subentries_visibility( op )) { /* only subentries are visible */ goto loop_continue; } } else if ( get_subentries( op ) && !get_subentries_visibility( op )) { /* only subentries are visible */ goto loop_continue; } } else if ( get_subentries_visibility( op )) { /* only subentries are visible */ goto loop_continue; } /* Does this candidate actually satisfy the search scope? * * Note that we don't lock access to the bei_parent pointer. * Since only leaf nodes can be deleted, the parent of any * node will always be a valid node. Also since we have * a Read lock on the data, it cannot be renamed out of the * scope while we are looking at it, and unless we're using * BDB_HIER, its parents cannot be moved either. */ scopeok = 0; switch( op->ors_scope ) { case LDAP_SCOPE_BASE: /* This is always true, yes? */ if ( id == base.e_id ) scopeok = 1; break; case LDAP_SCOPE_ONELEVEL: if ( ei->bei_parent->bei_id == base.e_id ) scopeok = 1; break;#ifdef LDAP_SCOPE_CHILDREN case LDAP_SCOPE_CHILDREN: if ( id == base.e_id ) break; /* Fall-thru */#endif case LDAP_SCOPE_SUBTREE: { EntryInfo *tmp; for ( tmp = BEI(e); tmp; tmp = tmp->bei_parent ) { if ( tmp->bei_id == base.e_id ) { scopeok = 1; break; } } } break; } /* aliases were already dereferenced in candidate list */ if ( op->ors_deref & LDAP_DEREF_SEARCHING ) { /* but if the search base is an alias, and we didn't * deref it when finding, return it. */ if ( is_entry_alias(e) && ((op->ors_deref & LDAP_DEREF_FINDING) || !bvmatch(&e->e_nname, &op->o_req_ndn))) { goto loop_continue; } /* scopes is only non-empty for onelevel or subtree */ if ( !scopeok && BDB_IDL_N(scopes) ) { unsigned x; if ( op->ors_scope == LDAP_SCOPE_ONELEVEL ) { x = bdb_idl_search( scopes, e->e_id ); if ( scopes[x] == e->e_id ) scopeok = 1; } else { /* subtree, walk up the tree */ EntryInfo *tmp = BEI(e); for (;tmp->bei_parent; tmp=tmp->bei_parent) { x = bdb_idl_search( scopes, tmp->bei_id ); if ( scopes[x] == tmp->bei_id ) { scopeok = 1; break; } } } } } /* Not in scope, ignore it */ if ( !scopeok ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_search) ": %ld scope not okay\n", (long) id, 0, 0 ); goto loop_continue; } /* * if it's a referral, add it to the list of referrals. only do * this for non-base searches, and don't check the filter * explicitly here since it's only a candidate anyway. */ if ( !manageDSAit && op->oq_search.rs_scope != LDAP_SCOPE_BASE && is_entry_referral( e ) ) { BerVarray erefs = get_entry_referrals( op, e ); rs->sr_ref = referral_rewrite( erefs, &e->e_name, NULL, op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL ? LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE ); send_search_reference( op, rs ); ber_bvarray_free( rs->sr_ref ); ber_bvarray_free( erefs ); rs->sr_ref = NULL; goto loop_continue; } if ( !manageDSAit && is_entry_glue( e )) { goto loop_continue; } /* if it matches the filter and scope, send it */ rs->sr_err = test_filter( op, rs->sr_entry, op->oq_search.rs_filter ); if ( rs->sr_err == LDAP_COMPARE_TRUE ) { /* check size limit */ if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) { if ( rs->sr_nentries >= ((PagedResultsState *)op->o_pagedresults_state)->ps_size ) {#ifdef SLAP_ZONE_ALLOC slap_zn_runlock(bdb->bi_cache.c_zctx, e);#endif bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock ); e = NULL; send_paged_response( op, rs, &lastid, tentries ); goto done; } lastid = id;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -