int monitor_back_compare( Operation *op, SlapReply *rs ) { monitor_info_t *mi = ( monitor_info_t * ) op->o_bd->be_private; Entry *e, *matched = NULL; int rc; /* get entry with reader lock */ monitor_cache_dn2entry( op, rs, &op->o_req_ndn, &e, &matched ); if ( e == NULL ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; if ( matched ) { if ( !access_allowed_mask( op, matched, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL, NULL ) ) { /* do nothing */ ; } else { rs->sr_matched = matched->e_dn; } } send_ldap_result( op, rs ); if ( matched ) { monitor_cache_release( mi, matched ); rs->sr_matched = NULL; } return rs->sr_err; } monitor_entry_update( op, rs, e ); rs->sr_err = slap_compare_entry( op, e, op->orc_ava ); rc = rs->sr_err; switch ( rc ) { case LDAP_COMPARE_FALSE: case LDAP_COMPARE_TRUE: rc = LDAP_SUCCESS; break; } send_ldap_result( op, rs ); rs->sr_err = rc; monitor_cache_release( mi, e ); return rs->sr_err; }
int wt_compare( Operation *op, SlapReply *rs ) { struct wt_info *wi = (struct wt_info *) op->o_bd->be_private; Entry *e = NULL; int manageDSAit = get_manageDSAit( op ); int rc; wt_ctx *wc = NULL; Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(wt_compare) ": %s\n", op->o_req_dn.bv_val, 0, 0 ); wc = wt_ctx_get(op, wi); if( !wc ){ Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(wt_compare) ": wt_ctx_get failed\n", 0, 0, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; send_ldap_result( op, rs ); return rs->sr_err; } rs->sr_err = wt_dn2entry(op->o_bd, wc, &op->o_req_ndn, &e); switch( rs->sr_err ) { case 0: case WT_NOTFOUND: break; default: rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } if ( rs->sr_err == WT_NOTFOUND ) { if ( e != NULL ) { /* return referral only if "disclose" is granted on the object */ if ( ! access_allowed( op, e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } else { rs->sr_matched = ch_strdup( e->e_dn ); if ( is_entry_referral( e )) { BerVarray ref = get_entry_referrals( op, e ); rs->sr_ref = referral_rewrite( ref, &e->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); ber_bvarray_free( ref ); } else { rs->sr_ref = NULL; } rs->sr_err = LDAP_REFERRAL; } wt_entry_return( e ); e = NULL; } else { rs->sr_ref = referral_rewrite( default_referral, NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT; } rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; send_ldap_result( op, rs ); goto done; } if (!manageDSAit && is_entry_referral( e ) ) { /* return referral only if "disclose" is granted on the object */ if ( !access_allowed( op, e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } else { /* entry is a referral, don't allow compare */ rs->sr_ref = get_entry_referrals( op, e ); rs->sr_err = LDAP_REFERRAL; rs->sr_matched = e->e_name.bv_val; } Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); send_ldap_result( op, rs ); ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; rs->sr_matched = NULL; goto done; } rs->sr_err = slap_compare_entry( op, e, op->orc_ava ); return_results: send_ldap_result( op, rs ); switch ( rs->sr_err ) { case LDAP_COMPARE_FALSE: case LDAP_COMPARE_TRUE: rs->sr_err = LDAP_SUCCESS; break; } done: if ( e != NULL ) { wt_entry_return( e ); } return rs->sr_err; }
int bdb_compare( Operation *op, SlapReply *rs ) { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; Entry *e = NULL; EntryInfo *ei; int manageDSAit = get_manageDSAit( op ); DB_TXN *rtxn; DB_LOCK lock; rs->sr_err = bdb_reader_get(op, bdb->bi_dbenv, &rtxn); switch(rs->sr_err) { case 0: break; default: send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); return rs->sr_err; } dn2entry_retry: /* get entry */ rs->sr_err = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1, &lock ); switch( rs->sr_err ) { case DB_NOTFOUND: case 0: break; case LDAP_BUSY: rs->sr_text = "ldap server busy"; goto return_results; case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto dn2entry_retry; default: rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } e = ei->bei_e; if ( rs->sr_err == DB_NOTFOUND ) { if ( e != NULL ) { /* return referral only if "disclose" is granted on the object */ if ( ! access_allowed( op, e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } else { rs->sr_matched = ch_strdup( e->e_dn ); rs->sr_ref = is_entry_referral( e ) ? get_entry_referrals( op, e ) : NULL; rs->sr_err = LDAP_REFERRAL; } bdb_cache_return_entry_r( bdb, e, &lock ); e = NULL; } else { rs->sr_ref = referral_rewrite( default_referral, NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT; } send_ldap_result( op, rs ); ber_bvarray_free( rs->sr_ref ); free( (char *)rs->sr_matched ); rs->sr_ref = NULL; rs->sr_matched = NULL; goto done; } if (!manageDSAit && is_entry_referral( e ) ) { /* return referral only if "disclose" is granted on the object */ if ( !access_allowed( op, e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } else { /* entry is a referral, don't allow compare */ rs->sr_ref = get_entry_referrals( op, e ); rs->sr_err = LDAP_REFERRAL; rs->sr_matched = e->e_name.bv_val; } Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); send_ldap_result( op, rs ); ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; rs->sr_matched = NULL; goto done; } rs->sr_err = slap_compare_entry( op, e, op->orc_ava ); return_results: send_ldap_result( op, rs ); switch ( rs->sr_err ) { case LDAP_COMPARE_FALSE: case LDAP_COMPARE_TRUE: rs->sr_err = LDAP_SUCCESS; break; } done: /* free entry */ if ( e != NULL ) { bdb_cache_return_entry_r( bdb, e, &lock ); } return rs->sr_err; }
int fe_op_compare( Operation *op, SlapReply *rs ) { Entry *entry = NULL; AttributeAssertion *ava = op->orc_ava; BackendDB *bd = op->o_bd; if( strcasecmp( op->o_req_ndn.bv_val, LDAP_ROOT_DSE ) == 0 ) { if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; } rs->sr_err = root_dse_info( op->o_conn, &entry, &rs->sr_text ); if( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; } } else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) { if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) { send_ldap_result( op, rs ); rs->sr_err = 0; goto cleanup; } rs->sr_err = schema_info( &entry, &rs->sr_text ); if( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); rs->sr_err = 0; goto cleanup; } } if( entry ) { rs->sr_err = slap_compare_entry( op, entry, ava ); entry_free( entry ); send_ldap_result( op, rs ); if( rs->sr_err == LDAP_COMPARE_TRUE || rs->sr_err == LDAP_COMPARE_FALSE ) { rs->sr_err = LDAP_SUCCESS; } goto cleanup; } /* * We could be serving multiple database backends. Select the * appropriate one, or send a referral to our "referral server" * if we don't hold it. */ op->o_bd = select_backend( &op->o_req_ndn, 0 ); if ( op->o_bd == NULL ) { rs->sr_ref = referral_rewrite( default_referral, NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); rs->sr_err = LDAP_REFERRAL; if (!rs->sr_ref) rs->sr_ref = default_referral; op->o_bd = bd; send_ldap_result( op, rs ); if (rs->sr_ref != default_referral) ber_bvarray_free( rs->sr_ref ); rs->sr_err = 0; goto cleanup; } /* check restrictions */ if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; } /* check for referrals */ if( backend_check_referrals( op, rs ) != LDAP_SUCCESS ) { goto cleanup; } if ( SLAP_SHADOW(op->o_bd) && get_dontUseCopy(op) ) { /* don't use shadow copy */ send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "copy not used" ); } else if ( ava->aa_desc == slap_schema.si_ad_entryDN ) { send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "entryDN compare not supported" ); } else if ( ava->aa_desc == slap_schema.si_ad_subschemaSubentry ) { send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "subschemaSubentry compare not supported" ); #ifndef SLAP_COMPARE_IN_FRONTEND } else if ( ava->aa_desc == slap_schema.si_ad_hasSubordinates && op->o_bd->be_has_subordinates ) { int rc, hasSubordinates = LDAP_SUCCESS; rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &entry ); if ( rc == 0 && entry ) { if ( ! access_allowed( op, entry, ava->aa_desc, &ava->aa_value, ACL_COMPARE, NULL ) ) { rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS; } else { rc = rs->sr_err = op->o_bd->be_has_subordinates( op, entry, &hasSubordinates ); be_entry_release_r( op, entry ); } } if ( rc == 0 ) { int asserted; asserted = bvmatch( &ava->aa_value, &slap_true_bv ) ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE; if ( hasSubordinates == asserted ) { rs->sr_err = LDAP_COMPARE_TRUE; } else { rs->sr_err = LDAP_COMPARE_FALSE; } } else { /* return error only if "disclose" * is granted on the object */ if ( backend_access( op, NULL, &op->o_req_ndn, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) == LDAP_INSUFFICIENT_ACCESS ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } } send_ldap_result( op, rs ); if ( rc == 0 ) { rs->sr_err = LDAP_SUCCESS; } } else if ( op->o_bd->be_compare ) { rs->sr_err = op->o_bd->be_compare( op, rs ); #endif /* ! SLAP_COMPARE_IN_FRONTEND */ } else { rs->sr_err = SLAP_CB_CONTINUE; } if ( rs->sr_err == SLAP_CB_CONTINUE ) { /* do our best to compare that AVA * * NOTE: this code is used only * if SLAP_COMPARE_IN_FRONTEND * is #define'd (it's not by default) * or if op->o_bd->be_compare is NULL. * * FIXME: one potential issue is that * if SLAP_COMPARE_IN_FRONTEND overlays * are not executed for compare. */ BerVarray vals = NULL; int rc = LDAP_OTHER; rs->sr_err = backend_attribute( op, NULL, &op->o_req_ndn, ava->aa_desc, &vals, ACL_COMPARE ); switch ( rs->sr_err ) { default: /* return error only if "disclose" * is granted on the object */ if ( backend_access( op, NULL, &op->o_req_ndn, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) == LDAP_INSUFFICIENT_ACCESS ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } break; case LDAP_SUCCESS: if ( value_find_ex( op->oq_compare.rs_ava->aa_desc, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, vals, &ava->aa_value, op->o_tmpmemctx ) == 0 ) { rs->sr_err = LDAP_COMPARE_TRUE; break; } else { rs->sr_err = LDAP_COMPARE_FALSE; } rc = LDAP_SUCCESS; break; } send_ldap_result( op, rs ); if ( rc == 0 ) { rs->sr_err = LDAP_SUCCESS; } if ( vals ) { ber_bvarray_free_x( vals, op->o_tmpmemctx ); } } cleanup:; op->o_bd = bd; return rs->sr_err; }
int mdb_compare( Operation *op, SlapReply *rs ) { struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; Entry *e = NULL; int manageDSAit = get_manageDSAit( op ); MDB_txn *rtxn; mdb_op_info opinfo = {{{0}}}, *moi = &opinfo; rs->sr_err = mdb_opinfo_get(op, mdb, 1, &moi); switch(rs->sr_err) { case 0: break; default: send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); return rs->sr_err; } rtxn = moi->moi_txn; /* get entry */ rs->sr_err = mdb_dn2entry( op, rtxn, NULL, &op->o_req_ndn, &e, NULL, 1 ); switch( rs->sr_err ) { case MDB_NOTFOUND: case 0: break; case LDAP_BUSY: rs->sr_text = "ldap server busy"; goto return_results; default: rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } if ( rs->sr_err == MDB_NOTFOUND ) { if ( e != NULL ) { /* return referral only if "disclose" is granted on the object */ if ( ! access_allowed( op, e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } else { rs->sr_matched = ch_strdup( e->e_dn ); if ( is_entry_referral( e )) { BerVarray ref = get_entry_referrals( op, e ); rs->sr_ref = referral_rewrite( ref, &e->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); ber_bvarray_free( ref ); } else { rs->sr_ref = NULL; } rs->sr_err = LDAP_REFERRAL; } mdb_entry_return( op, e ); e = NULL; } else { rs->sr_ref = referral_rewrite( default_referral, NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT; } rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; send_ldap_result( op, rs ); goto done; } if (!manageDSAit && is_entry_referral( e ) ) { /* return referral only if "disclose" is granted on the object */ if ( !access_allowed( op, e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } else { /* entry is a referral, don't allow compare */ rs->sr_ref = get_entry_referrals( op, e ); rs->sr_err = LDAP_REFERRAL; rs->sr_matched = e->e_name.bv_val; } Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); send_ldap_result( op, rs ); ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; rs->sr_matched = NULL; goto done; } rs->sr_err = slap_compare_entry( op, e, op->orc_ava ); return_results: send_ldap_result( op, rs ); switch ( rs->sr_err ) { case LDAP_COMPARE_FALSE: case LDAP_COMPARE_TRUE: rs->sr_err = LDAP_SUCCESS; break; } done: if ( moi == &opinfo ) { mdb_txn_reset( moi->moi_txn ); LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next ); } else { moi->moi_ref--; } /* free entry */ if ( e != NULL ) { mdb_entry_return( op, e ); } return rs->sr_err; }