/* Dispose of the contents of the array and the array itself according * to the flags value. If SLAP_SET_REFVAL, don't dispose of values; * if SLAP_SET_REFARR, don't dispose of the array itself. In case of * binary operators, there are LEFT flags and RIGHT flags, referring to * the first and the second operator arguments, respectively. In this * case, flags must be transformed using macros SLAP_SET_LREF2REF() and * SLAP_SET_RREF2REF() before calling this function. */ static void slap_set_dispose( SetCookie *cp, BerVarray set, unsigned flags ) { if ( flags & SLAP_SET_REFVAL ) { if ( ! ( flags & SLAP_SET_REFARR ) ) { cp->set_op->o_tmpfree( set, cp->set_op->o_tmpmemctx ); } } else { ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx ); } }
RETCODE backsql_FreeRow_x( BACKSQL_ROW_NTS *row, void *ctx ) { if ( row->cols == NULL ) { return SQL_ERROR; } ber_bvarray_free_x( row->col_names, ctx ); ber_memfree_x( row->col_prec, ctx ); ber_memfree_x( row->col_type, ctx ); ber_memvfree_x( (void **)row->cols, ctx ); ber_memfree_x( row->value_len, ctx ); return SQL_SUCCESS; }
static int indexer( Operation *op, wt_ctx *wc, AttributeDescription *ad, struct berval *atname, BerVarray vals, ID id, int opid, slap_mask_t mask ) { int rc, i; struct berval *keys; WT_CURSOR *cursor = NULL; WT_SESSION *session = wc->session; assert( mask != 0 ); cursor = wt_ctx_index_cursor(wc, atname, 1); if( !cursor ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(indexer) ": open index cursor failed: %s\n", atname->bv_val, 0, 0 ); goto done; } if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) { rc = wt_key_change( op->o_bd, cursor, &presence_key, id, opid ); if( rc ) { goto done; } } if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) { rc = ad->ad_type->sat_equality->smr_indexer( LDAP_FILTER_EQUALITY, mask, ad->ad_type->sat_syntax, ad->ad_type->sat_equality, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { for( i=0; keys[i].bv_val != NULL; i++ ) { rc = wt_key_change( op->o_bd, cursor, &keys[i], id, opid ); if( rc ) { ber_bvarray_free_x( keys, op->o_tmpmemctx ); goto done; } } ber_bvarray_free_x( keys, op->o_tmpmemctx ); } rc = LDAP_SUCCESS; } if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) { rc = ad->ad_type->sat_approx->smr_indexer( LDAP_FILTER_APPROX, mask, ad->ad_type->sat_syntax, ad->ad_type->sat_approx, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { for( i=0; keys[i].bv_val != NULL; i++ ) { rc = wt_key_change( op->o_bd, cursor, &keys[i], id, opid ); if( rc ) { ber_bvarray_free_x( keys, op->o_tmpmemctx ); goto done; } } ber_bvarray_free_x( keys, op->o_tmpmemctx ); } rc = LDAP_SUCCESS; } if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) { rc = ad->ad_type->sat_substr->smr_indexer( LDAP_FILTER_SUBSTRINGS, mask, ad->ad_type->sat_syntax, ad->ad_type->sat_substr, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { for( i=0; keys[i].bv_val != NULL; i++ ) { rc = wt_key_change( op->o_bd, cursor, &keys[i], id, opid ); if( rc ) { ber_bvarray_free_x( keys, op->o_tmpmemctx ); goto done; } } ber_bvarray_free_x( keys, op->o_tmpmemctx ); } rc = LDAP_SUCCESS; } done: if(cursor){ cursor->close(cursor); } return rc; }
static int approx_candidates( Operation *op, DB_TXN *rtxn, AttributeAssertion *ava, ID *ids, ID *tmp ) { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; DB *db; int i; int rc; slap_mask_t mask; struct berval prefix = {0, NULL}; struct berval *keys = NULL; MatchingRule *mr; Debug( LDAP_DEBUG_TRACE, "=> bdb_approx_candidates (%s)\n", ava->aa_desc->ad_cname.bv_val, 0, 0 ); BDB_IDL_ALL( bdb, ids ); rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_APPROX, &db, &mask, &prefix ); if ( rc == LDAP_INAPPROPRIATE_MATCHING ) { Debug( LDAP_DEBUG_ANY, "<= bdb_approx_candidates: (%s) not indexed\n", ava->aa_desc->ad_cname.bv_val, 0, 0 ); return 0; } if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "<= bdb_approx_candidates: (%s) " "index_param failed (%d)\n", ava->aa_desc->ad_cname.bv_val, rc, 0 ); return 0; } mr = ava->aa_desc->ad_type->sat_approx; if( !mr ) { /* no approx matching rule, try equality matching rule */ mr = ava->aa_desc->ad_type->sat_equality; } if( !mr ) { return 0; } if( !mr->smr_filter ) { return 0; } rc = (mr->smr_filter)( LDAP_FILTER_APPROX, mask, ava->aa_desc->ad_type->sat_syntax, mr, &prefix, &ava->aa_value, &keys, op->o_tmpmemctx ); if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "<= bdb_approx_candidates: (%s, %s) " "MR filter failed (%d)\n", prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc ); return 0; } if( keys == NULL ) { Debug( LDAP_DEBUG_TRACE, "<= bdb_approx_candidates: (%s) no keys (%s)\n", prefix.bv_val, ava->aa_desc->ad_cname.bv_val, 0 ); return 0; } for ( i= 0; keys[i].bv_val != NULL; i++ ) { rc = bdb_key_read( op->o_bd, db, rtxn, &keys[i], tmp, NULL, 0 ); if( rc == DB_NOTFOUND ) { BDB_IDL_ZERO( ids ); rc = 0; break; } else if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "<= bdb_approx_candidates: (%s) " "key read failed (%d)\n", ava->aa_desc->ad_cname.bv_val, rc, 0 ); break; } if( BDB_IDL_IS_ZERO( tmp ) ) { Debug( LDAP_DEBUG_TRACE, "<= bdb_approx_candidates: (%s) NULL\n", ava->aa_desc->ad_cname.bv_val, 0, 0 ); BDB_IDL_ZERO( ids ); break; } if ( i == 0 ) { BDB_IDL_CPY( ids, tmp ); } else { bdb_idl_intersection( ids, tmp ); } if( BDB_IDL_IS_ZERO( ids ) ) break; } ber_bvarray_free_x( keys, op->o_tmpmemctx ); Debug( LDAP_DEBUG_TRACE, "<= bdb_approx_candidates %ld, first=%ld, last=%ld\n", (long) ids[0], (long) BDB_IDL_FIRST(ids), (long) BDB_IDL_LAST(ids) ); return( rc ); }
static int dynlist_compare( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; dynlist_info_t *dli = (dynlist_info_t *)on->on_bi.bi_private; Operation o = *op; Entry *e = NULL; dynlist_map_t *dlm; for ( ; dli != NULL; dli = dli->dli_next ) { for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) if ( op->oq_compare.rs_ava->aa_desc == dlm->dlm_member_ad ) break; if ( dli->dli_dlm && dlm ) { /* This compare is for one of the attributes we're * interested in. We'll use slapd's existing dyngroup * evaluator to get the answer we want. */ BerVarray id = NULL, authz = NULL; o.o_do_not_cache = 1; if ( ad_dgIdentity && backend_attribute( &o, NULL, &o.o_req_ndn, ad_dgIdentity, &id, ACL_READ ) == LDAP_SUCCESS ) { /* if not rootdn and dgAuthz is present, * check if user can be authorized as dgIdentity */ if ( ad_dgAuthz && !BER_BVISEMPTY( id ) && !be_isroot( op ) && backend_attribute( &o, NULL, &o.o_req_ndn, ad_dgAuthz, &authz, ACL_READ ) == LDAP_SUCCESS ) { rs->sr_err = slap_sasl_matches( op, authz, &o.o_ndn, &o.o_ndn ); ber_bvarray_free_x( authz, op->o_tmpmemctx ); if ( rs->sr_err != LDAP_SUCCESS ) { goto done; } } o.o_dn = *id; o.o_ndn = *id; o.o_groups = NULL; /* authz changed, invalidate cached groups */ } rs->sr_err = backend_group( &o, NULL, &o.o_req_ndn, &o.oq_compare.rs_ava->aa_value, dli->dli_oc, dli->dli_ad ); switch ( rs->sr_err ) { case LDAP_SUCCESS: rs->sr_err = LDAP_COMPARE_TRUE; break; case LDAP_NO_SUCH_OBJECT: /* NOTE: backend_group() returns noSuchObject * if op_ndn does not exist; however, since * dynamic list expansion means that the * member attribute is virtually present, the * non-existence of the asserted value implies * the assertion is FALSE rather than * UNDEFINED */ rs->sr_err = LDAP_COMPARE_FALSE; break; } done:; if ( id ) ber_bvarray_free_x( id, o.o_tmpmemctx ); return SLAP_CB_CONTINUE; } } if ( overlay_entry_get_ov( &o, &o.o_req_ndn, NULL, NULL, 0, &e, on ) != LDAP_SUCCESS || e == NULL ) { return SLAP_CB_CONTINUE; } if ( ad_dgIdentity ) { Attribute *id = attrs_find( e->e_attrs, ad_dgIdentity ); if ( id ) { Attribute *authz; /* if not rootdn and dgAuthz is present, * check if user can be authorized as dgIdentity */ if ( ad_dgAuthz && !BER_BVISEMPTY( &id->a_nvals[0] ) && !be_isroot( op ) && ( authz = attrs_find( e->e_attrs, ad_dgAuthz ) ) ) { if ( slap_sasl_matches( op, authz->a_nvals, &o.o_ndn, &o.o_ndn ) != LDAP_SUCCESS ) { goto release; } } o.o_dn = id->a_vals[0]; o.o_ndn = id->a_nvals[0]; o.o_groups = NULL; } } dli = (dynlist_info_t *)on->on_bi.bi_private; for ( ; dli != NULL && rs->sr_err != LDAP_COMPARE_TRUE; dli = dli->dli_next ) { Attribute *a; slap_callback cb; SlapReply r = { REP_SEARCH }; AttributeName an[2]; int rc; dynlist_sc_t dlc = { 0 }; if ( !is_entry_objectclass_or_sub( e, dli->dli_oc )) continue; /* if the entry has the right objectClass, generate * the dynamic list and compare */ dlc.dlc_dli = dli; cb.sc_private = &dlc; cb.sc_response = dynlist_sc_save_entry; cb.sc_cleanup = NULL; cb.sc_next = NULL; o.o_callback = &cb; o.o_tag = LDAP_REQ_SEARCH; o.ors_limit = NULL; o.ors_tlimit = SLAP_NO_LIMIT; o.ors_slimit = SLAP_NO_LIMIT; o.o_bd = select_backend( &o.o_req_ndn, 1 ); if ( !o.o_bd || !o.o_bd->be_search ) { goto release; } o.ors_filterstr = *slap_filterstr_objectClass_pres; o.ors_filter = (Filter *) slap_filter_objectClass_pres; o.ors_scope = LDAP_SCOPE_BASE; o.ors_deref = LDAP_DEREF_NEVER; an[0].an_name = op->orc_ava->aa_desc->ad_cname; an[0].an_desc = op->orc_ava->aa_desc; BER_BVZERO( &an[1].an_name ); o.ors_attrs = an; o.ors_attrsonly = 0; o.o_acl_priv = ACL_COMPARE; rc = o.o_bd->be_search( &o, &r ); if ( o.o_dn.bv_val != op->o_dn.bv_val ) { slap_op_groups_free( &o ); } if ( rc != 0 ) { goto release; } if ( dlc.dlc_e != NULL ) { r.sr_entry = dlc.dlc_e; } if ( r.sr_err != LDAP_SUCCESS || r.sr_entry == NULL ) { /* error? */ goto release; } for ( a = attrs_find( r.sr_entry->e_attrs, op->orc_ava->aa_desc ); a != NULL; a = attrs_find( a->a_next, op->orc_ava->aa_desc ) ) { /* if we're here, we got a match... */ rs->sr_err = LDAP_COMPARE_FALSE; if ( attr_valfind( a, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, &op->orc_ava->aa_value, NULL, op->o_tmpmemctx ) == 0 ) { rs->sr_err = LDAP_COMPARE_TRUE; break; } } if ( r.sr_flags & REP_ENTRY_MUSTBEFREED ) { entry_free( r.sr_entry ); } } release:; if ( e != NULL ) { overlay_entry_release_ov( &o, e, 0, on ); } return SLAP_CB_CONTINUE; }
static int equality_candidates( Operation *op, MDB_txn *rtxn, AttributeAssertion *ava, ID *ids, ID *tmp ) { MDB_dbi dbi; int i; int rc; slap_mask_t mask; struct berval prefix = {0, NULL}; struct berval *keys = NULL; MatchingRule *mr; Debug( LDAP_DEBUG_TRACE, "=> mdb_equality_candidates (%s)\n", ava->aa_desc->ad_cname.bv_val, 0, 0 ); if ( ava->aa_desc == slap_schema.si_ad_entryDN ) { ID id; rc = mdb_dn2id( op, rtxn, NULL, &ava->aa_value, &id, NULL, NULL, NULL ); if ( rc == LDAP_SUCCESS ) { /* exactly one ID can match */ ids[0] = 1; ids[1] = id; } if ( rc == MDB_NOTFOUND ) { MDB_IDL_ZERO( ids ); rc = 0; } return rc; } MDB_IDL_ALL( ids ); rc = mdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY, &dbi, &mask, &prefix ); if ( rc == LDAP_INAPPROPRIATE_MATCHING ) { Debug( LDAP_DEBUG_ANY, "<= mdb_equality_candidates: (%s) not indexed\n", ava->aa_desc->ad_cname.bv_val, 0, 0 ); return 0; } if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "<= mdb_equality_candidates: (%s) " "index_param failed (%d)\n", ava->aa_desc->ad_cname.bv_val, rc, 0 ); return 0; } mr = ava->aa_desc->ad_type->sat_equality; if( !mr ) { return 0; } if( !mr->smr_filter ) { return 0; } rc = (mr->smr_filter)( LDAP_FILTER_EQUALITY, mask, ava->aa_desc->ad_type->sat_syntax, mr, &prefix, &ava->aa_value, &keys, op->o_tmpmemctx ); if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "<= mdb_equality_candidates: (%s, %s) " "MR filter failed (%d)\n", prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc ); return 0; } if( keys == NULL ) { Debug( LDAP_DEBUG_TRACE, "<= mdb_equality_candidates: (%s) no keys\n", ava->aa_desc->ad_cname.bv_val, 0, 0 ); return 0; } for ( i= 0; keys[i].bv_val != NULL; i++ ) { rc = mdb_key_read( op->o_bd, rtxn, dbi, &keys[i], tmp, NULL, 0 ); if( rc == MDB_NOTFOUND ) { MDB_IDL_ZERO( ids ); rc = 0; break; } else if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "<= mdb_equality_candidates: (%s) " "key read failed (%d)\n", ava->aa_desc->ad_cname.bv_val, rc, 0 ); break; } if( MDB_IDL_IS_ZERO( tmp ) ) { Debug( LDAP_DEBUG_TRACE, "<= mdb_equality_candidates: (%s) NULL\n", ava->aa_desc->ad_cname.bv_val, 0, 0 ); MDB_IDL_ZERO( ids ); break; } if ( i == 0 ) { MDB_IDL_CPY( ids, tmp ); } else { mdb_idl_intersection( ids, tmp ); } if( MDB_IDL_IS_ZERO( ids ) ) break; } ber_bvarray_free_x( keys, op->o_tmpmemctx ); Debug( LDAP_DEBUG_TRACE, "<= mdb_equality_candidates: id=%ld, first=%ld, last=%ld\n", (long) ids[0], (long) MDB_IDL_FIRST(ids), (long) MDB_IDL_LAST(ids) ); return( rc ); }
static int inequality_candidates( Operation *op, MDB_txn *rtxn, AttributeAssertion *ava, ID *ids, ID *tmp, int gtorlt ) { MDB_dbi dbi; int rc; slap_mask_t mask; struct berval prefix = {0, NULL}; struct berval *keys = NULL; MatchingRule *mr; MDB_cursor *cursor = NULL; Debug( LDAP_DEBUG_TRACE, "=> mdb_inequality_candidates (%s)\n", ava->aa_desc->ad_cname.bv_val, 0, 0 ); MDB_IDL_ALL( ids ); rc = mdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY, &dbi, &mask, &prefix ); if ( rc == LDAP_INAPPROPRIATE_MATCHING ) { Debug( LDAP_DEBUG_ANY, "<= mdb_inequality_candidates: (%s) not indexed\n", ava->aa_desc->ad_cname.bv_val, 0, 0 ); return 0; } if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "<= mdb_inequality_candidates: (%s) " "index_param failed (%d)\n", ava->aa_desc->ad_cname.bv_val, rc, 0 ); return 0; } mr = ava->aa_desc->ad_type->sat_equality; if( !mr ) { return 0; } if( !mr->smr_filter ) { return 0; } rc = (mr->smr_filter)( LDAP_FILTER_EQUALITY, mask, ava->aa_desc->ad_type->sat_syntax, mr, &prefix, &ava->aa_value, &keys, op->o_tmpmemctx ); if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "<= mdb_inequality_candidates: (%s, %s) " "MR filter failed (%d)\n", prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc ); return 0; } if( keys == NULL ) { Debug( LDAP_DEBUG_TRACE, "<= mdb_inequality_candidates: (%s) no keys\n", ava->aa_desc->ad_cname.bv_val, 0, 0 ); return 0; } MDB_IDL_ZERO( ids ); while(1) { rc = mdb_key_read( op->o_bd, rtxn, dbi, &keys[0], tmp, &cursor, gtorlt ); if( rc == MDB_NOTFOUND ) { rc = 0; break; } else if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "<= mdb_inequality_candidates: (%s) " "key read failed (%d)\n", ava->aa_desc->ad_cname.bv_val, rc, 0 ); break; } if( MDB_IDL_IS_ZERO( tmp ) ) { Debug( LDAP_DEBUG_TRACE, "<= mdb_inequality_candidates: (%s) NULL\n", ava->aa_desc->ad_cname.bv_val, 0, 0 ); break; } mdb_idl_union( ids, tmp ); if( op->ors_limit && op->ors_limit->lms_s_unchecked != -1 && MDB_IDL_N( ids ) >= (unsigned) op->ors_limit->lms_s_unchecked ) { mdb_cursor_close( cursor ); break; } } ber_bvarray_free_x( keys, op->o_tmpmemctx ); Debug( LDAP_DEBUG_TRACE, "<= mdb_inequality_candidates: id=%ld, first=%ld, last=%ld\n", (long) ids[0], (long) MDB_IDL_FIRST(ids), (long) MDB_IDL_LAST(ids) ); return( rc ); }
int asyncmeta_handle_search_msg(LDAPMessage *res, a_metaconn_t *mc, bm_context_t *bc, int candidate) { a_metainfo_t *mi; a_metatarget_t *mt; a_metasingleconn_t *msc; Operation *op = bc->op; SlapReply *rs; int i, rc = LDAP_SUCCESS, sres; SlapReply *candidates; char **references = NULL; LDAPControl **ctrls = NULL; a_dncookie dc; LDAPMessage *msg; ber_int_t id; rs = &bc->rs; mi = mc->mc_info; mt = mi->mi_targets[ candidate ]; msc = &mc->mc_conns[ candidate ]; dc.op = op; dc.target = mt; dc.to_from = MASSAGE_REP; id = ldap_msgid(res); candidates = bc->candidates; i = candidate; while (res && !META_BACK_CONN_INVALID(msc)) { for (msg = ldap_first_message(msc->msc_ldr, res); msg; msg = ldap_next_message(msc->msc_ldr, msg)) { switch(ldap_msgtype(msg)) { case LDAP_RES_SEARCH_ENTRY: Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_handle_search_msg: msc %p entry\n", op->o_log_prefix, msc ); if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { /* don't retry any more... */ candidates[ i ].sr_type = REP_RESULT; } /* count entries returned by target */ candidates[ i ].sr_nentries++; if (bc->c_peer_name.bv_val == op->o_conn->c_peer_name.bv_val && !op->o_abandon) { rs->sr_err = asyncmeta_send_entry( &bc->copy_op, rs, mc, i, msg ); } else { goto err_cleanup; } switch ( rs->sr_err ) { case LDAP_SIZELIMIT_EXCEEDED: asyncmeta_send_ldap_result(bc, op, rs); rs->sr_err = LDAP_SUCCESS; goto err_cleanup; case LDAP_UNAVAILABLE: rs->sr_err = LDAP_OTHER; break; default: break; } bc->is_ok++; break; case LDAP_RES_SEARCH_REFERENCE: if ( META_BACK_TGT_NOREFS( mt ) ) { rs->sr_err = LDAP_OTHER; asyncmeta_send_ldap_result(bc, op, rs); goto err_cleanup; } if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { /* don't retry any more... */ candidates[ i ].sr_type = REP_RESULT; } bc->is_ok++; rc = ldap_parse_reference( msc->msc_ldr, msg, &references, &rs->sr_ctrls, 0 ); if ( rc != LDAP_SUCCESS || references == NULL ) { rs->sr_err = LDAP_OTHER; asyncmeta_send_ldap_result(bc, op, rs); goto err_cleanup; } /* FIXME: merge all and return at the end */ { int cnt; for ( cnt = 0; references[ cnt ]; cnt++ ) ; rs->sr_ref = ber_memalloc_x( sizeof( struct berval ) * ( cnt + 1 ), op->o_tmpmemctx ); for ( cnt = 0; references[ cnt ]; cnt++ ) { ber_str2bv_x( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ], op->o_tmpmemctx ); } BER_BVZERO( &rs->sr_ref[ cnt ] ); } { dc.memctx = op->o_tmpmemctx; ( void )asyncmeta_referral_result_rewrite( &dc, rs->sr_ref ); } if ( rs->sr_ref != NULL ) { if (!BER_BVISNULL( &rs->sr_ref[ 0 ] ) ) { /* ignore return value by now */ ( void )send_search_reference( op, rs ); } ber_bvarray_free_x( rs->sr_ref, op->o_tmpmemctx ); rs->sr_ref = NULL; } /* cleanup */ if ( references ) { ber_memvfree( (void **)references ); } if ( rs->sr_ctrls ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } break; case LDAP_RES_INTERMEDIATE: if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { /* don't retry any more... */ candidates[ i ].sr_type = REP_RESULT; } bc->is_ok++; /* FIXME: response controls * are passed without checks */ rs->sr_err = ldap_parse_intermediate( msc->msc_ldr, msg, (char **)&rs->sr_rspoid, &rs->sr_rspdata, &rs->sr_ctrls, 0 ); if ( rs->sr_err != LDAP_SUCCESS ) { candidates[ i ].sr_type = REP_RESULT; rs->sr_err = LDAP_OTHER; asyncmeta_send_ldap_result(bc, op, rs); goto err_cleanup; } slap_send_ldap_intermediate( op, rs ); if ( rs->sr_rspoid != NULL ) { ber_memfree( (char *)rs->sr_rspoid ); rs->sr_rspoid = NULL; } if ( rs->sr_rspdata != NULL ) { ber_bvfree( rs->sr_rspdata ); rs->sr_rspdata = NULL; } if ( rs->sr_ctrls != NULL ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } break; case LDAP_RES_SEARCH_RESULT: if ( mi->mi_idle_timeout != 0 ) { asyncmeta_set_msc_time(msc); } Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_handle_search_msg: msc %p result\n", op->o_log_prefix, msc ); candidates[ i ].sr_type = REP_RESULT; candidates[ i ].sr_msgid = META_MSGID_IGNORE; /* NOTE: ignores response controls * (and intermediate response controls * as well, except for those with search * references); this may not be correct, * but if they're not ignored then * back-meta would need to merge them * consistently (think of pagedResults...) */ /* FIXME: response controls? */ rs->sr_err = ldap_parse_result( msc->msc_ldr, msg, &candidates[ i ].sr_err, (char **)&candidates[ i ].sr_matched, (char **)&candidates[ i ].sr_text, &references, &ctrls /* &candidates[ i ].sr_ctrls (unused) */ , 0 ); if ( rs->sr_err != LDAP_SUCCESS ) { candidates[ i ].sr_err = rs->sr_err; sres = slap_map_api2result( &candidates[ i ] ); candidates[ i ].sr_type = REP_RESULT; goto finish; } rs->sr_err = candidates[ i ].sr_err; /* massage matchedDN if need be */ if ( candidates[ i ].sr_matched != NULL ) { struct berval match, mmatch; ber_str2bv( candidates[ i ].sr_matched, 0, 0, &match ); candidates[ i ].sr_matched = NULL; dc.memctx = NULL; asyncmeta_dn_massage( &dc, &match, &mmatch ); if ( mmatch.bv_val == match.bv_val ) { candidates[ i ].sr_matched = ch_strdup( mmatch.bv_val ); } else { candidates[ i ].sr_matched = mmatch.bv_val; } bc->candidate_match++; ldap_memfree( match.bv_val ); } /* add references to array */ /* RFC 4511: referrals can only appear * if result code is LDAP_REFERRAL */ if ( references != NULL && references[ 0 ] != NULL && references[ 0 ][ 0 ] != '\0' ) { if ( rs->sr_err != LDAP_REFERRAL ) { Debug( LDAP_DEBUG_ANY, "%s asncmeta_search_result[%d]: " "got referrals with err=%d\n", op->o_log_prefix, i, rs->sr_err ); } else { BerVarray sr_ref; int cnt; for ( cnt = 0; references[ cnt ]; cnt++ ) ; sr_ref = ber_memalloc_x( sizeof( struct berval ) * ( cnt + 1 ), op->o_tmpmemctx ); for ( cnt = 0; references[ cnt ]; cnt++ ) { ber_str2bv_x( references[ cnt ], 0, 1, &sr_ref[ cnt ], op->o_tmpmemctx ); } BER_BVZERO( &sr_ref[ cnt ] ); dc.memctx = op->o_tmpmemctx; ( void )asyncmeta_referral_result_rewrite( &dc, sr_ref ); if ( rs->sr_v2ref == NULL ) { rs->sr_v2ref = sr_ref; } else { for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) { ber_bvarray_add_x( &rs->sr_v2ref, &sr_ref[ cnt ], op->o_tmpmemctx ); } ber_memfree_x( sr_ref, op->o_tmpmemctx ); } } } else if ( rs->sr_err == LDAP_REFERRAL ) { Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_search_result[%d]: " "got err=%d with null " "or empty referrals\n", op->o_log_prefix, i, rs->sr_err ); rs->sr_err = LDAP_NO_SUCH_OBJECT; } /* cleanup */ ber_memvfree( (void **)references ); sres = slap_map_api2result( rs ); if ( candidates[ i ].sr_err == LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_search_result[%d] " "match=\"%s\" err=%ld", op->o_log_prefix, i, candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "", (long) candidates[ i ].sr_err ); } else { Debug( LDAP_DEBUG_ANY, "%s asyncmeta_search_result[%d] " "match=\"%s\" err=%ld (%s)", op->o_log_prefix, i, candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "", (long) candidates[ i ].sr_err, ldap_err2string( candidates[ i ].sr_err ) ); } switch ( sres ) { case LDAP_NO_SUCH_OBJECT: /* is_ok is touched any time a valid * (even intermediate) result is * returned; as a consequence, if * a candidate returns noSuchObject * it is ignored and the candidate * is simply demoted. */ if ( bc->is_ok ) { sres = LDAP_SUCCESS; } break; case LDAP_SUCCESS: if ( ctrls != NULL && ctrls[0] != NULL ) { #ifdef SLAPD_META_CLIENT_PR LDAPControl *pr_c; pr_c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL ); if ( pr_c != NULL ) { BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; ber_tag_t tag; ber_int_t prsize; struct berval prcookie; /* unsolicited, do not accept */ if ( mt->mt_ps == 0 ) { rs->sr_err = LDAP_OTHER; goto err_pr; } ber_init2( ber, &pr_c->ldctl_value, LBER_USE_DER ); tag = ber_scanf( ber, "{im}", &prsize, &prcookie ); if ( tag == LBER_ERROR ) { rs->sr_err = LDAP_OTHER; goto err_pr; } /* more pages? new search request */ if ( !BER_BVISNULL( &prcookie ) && !BER_BVISEMPTY( &prcookie ) ) { if ( mt->mt_ps > 0 ) { /* ignore size if specified */ prsize = 0; } else if ( prsize == 0 ) { /* guess the page size from the entries returned so far */ prsize = candidates[ i ].sr_nentries; } candidates[ i ].sr_nentries = 0; candidates[ i ].sr_msgid = META_MSGID_IGNORE; candidates[ i ].sr_type = REP_INTERMEDIATE; assert( candidates[ i ].sr_matched == NULL ); assert( candidates[ i ].sr_text == NULL ); assert( candidates[ i ].sr_ref == NULL ); switch ( asyncmeta_back_search_start( &bc->copy_op, rs, mc, bc, i, &prcookie, prsize, 1 ) ) { case META_SEARCH_CANDIDATE: assert( candidates[ i ].sr_msgid >= 0 ); ldap_controls_free( ctrls ); // goto free_message; case META_SEARCH_ERR: case META_SEARCH_NEED_BIND: err_pr:; candidates[ i ].sr_err = rs->sr_err; candidates[ i ].sr_type = REP_RESULT; if ( META_BACK_ONERR_STOP( mi ) ) { asyncmeta_send_ldap_result(bc, op, rs); ldap_controls_free( ctrls ); goto err_cleanup; } /* fallthru */ case META_SEARCH_NOT_CANDIDATE: /* means that asyncmeta_back_search_start() * failed but onerr == continue */ candidates[ i ].sr_msgid = META_MSGID_IGNORE; candidates[ i ].sr_type = REP_RESULT; break; default: /* impossible */ assert( 0 ); break; } break; } } #endif /* SLAPD_META_CLIENT_PR */ ldap_controls_free( ctrls ); } /* fallthru */ case LDAP_REFERRAL: bc->is_ok++; break; case LDAP_SIZELIMIT_EXCEEDED: /* if a target returned sizelimitExceeded * and the entry count is equal to the * proxy's limit, the target would have * returned more, and the error must be * propagated to the client; otherwise, * the target enforced a limit lower * than what requested by the proxy; * ignore it */ candidates[ i ].sr_err = rs->sr_err; if ( rs->sr_nentries == op->ors_slimit || META_BACK_ONERR_STOP( mi ) ) { const char *save_text; got_err: save_text = rs->sr_text; rs->sr_text = candidates[ i ].sr_text; asyncmeta_send_ldap_result(bc, op, rs); if (candidates[ i ].sr_text != NULL) { ch_free( (char *)candidates[ i ].sr_text ); candidates[ i ].sr_text = NULL; } rs->sr_text = save_text; ldap_controls_free( ctrls ); goto err_cleanup; } break; default: candidates[ i ].sr_err = rs->sr_err; if ( META_BACK_ONERR_STOP( mi ) ) { goto got_err; } break; } /* if this is the last result we will ever receive, send it back */ rc = rs->sr_err; if (asyncmeta_is_last_result(mc, bc, i) == 0) { Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_handle_search_msg: msc %p last result\n", op->o_log_prefix, msc ); asyncmeta_search_last_result(mc, bc, i, sres); err_cleanup: rc = rs->sr_err; ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex ); asyncmeta_drop_bc( mc, bc); asyncmeta_clear_bm_context(bc); ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex ); ldap_msgfree(res); return rc; } finish: break; default: continue; } } ldap_msgfree(res); res = NULL; if (candidates[ i ].sr_type != REP_RESULT) { struct timeval tv = {0}; rc = ldap_result( msc->msc_ldr, id, LDAP_MSG_RECEIVED, &tv, &res ); if (res != NULL) { msc->msc_result_time = slap_get_time(); } } } ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex ); bc->bc_active--; ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex ); return rc; }
int ndb_back_compare( Operation *op, SlapReply *rs ) { struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private; Entry e = {0}; Attribute *a; int manageDSAit = get_manageDSAit( op ); NdbArgs NA; NdbRdns rdns; struct berval matched; /* Get our NDB handle */ rs->sr_err = ndb_thread_handle( op, &NA.ndb ); rdns.nr_num = 0; NA.rdns = &rdns; e.e_name = op->o_req_dn; e.e_nname = op->o_req_ndn; NA.e = &e; dn2entry_retry: NA.txn = NA.ndb->startTransaction(); rs->sr_text = NULL; if( !NA.txn ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_compare) ": startTransaction failed: %s (%d)\n", NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } NA.ocs = NULL; /* get entry */ rs->sr_err = ndb_entry_get_info( op, &NA, 0, &matched ); switch( rs->sr_err ) { case 0: break; case LDAP_NO_SUCH_OBJECT: rs->sr_matched = matched.bv_val; if ( NA.ocs ) ndb_check_referral( op, rs, &NA ); goto return_results; case LDAP_BUSY: rs->sr_text = "ldap server busy"; goto return_results; #if 0 case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto dn2entry_retry; #endif default: rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } rs->sr_err = ndb_entry_get_data( op, &NA, 0 ); ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx ); 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; rs->sr_flags |= REP_REF_MUSTBEFREED; } Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); goto return_results; } if ( get_assert( op ) && ( test_filter( op, &e, (Filter *)get_assertion( op )) != LDAP_COMPARE_TRUE )) { if ( !access_allowed( op, &e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } else { rs->sr_err = LDAP_ASSERTION_FAILED; } goto return_results; } if ( !access_allowed( op, &e, op->oq_compare.rs_ava->aa_desc, &op->oq_compare.rs_ava->aa_value, ACL_COMPARE, NULL ) ) { /* return error 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_err = LDAP_INSUFFICIENT_ACCESS; } goto return_results; } rs->sr_err = LDAP_NO_SUCH_ATTRIBUTE; for ( a = attrs_find( e.e_attrs, op->oq_compare.rs_ava->aa_desc ); a != NULL; a = attrs_find( a->a_next, op->oq_compare.rs_ava->aa_desc ) ) { rs->sr_err = LDAP_COMPARE_FALSE; if ( attr_valfind( a, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, &op->oq_compare.rs_ava->aa_value, NULL, op->o_tmpmemctx ) == 0 ) { rs->sr_err = LDAP_COMPARE_TRUE; break; } } return_results: NA.txn->close(); if ( e.e_attrs ) { attrs_free( e.e_attrs ); e.e_attrs = NULL; } send_ldap_result( op, rs ); switch ( rs->sr_err ) { case LDAP_COMPARE_FALSE: case LDAP_COMPARE_TRUE: rs->sr_err = LDAP_SUCCESS; break; } return rs->sr_err; }
int slap_set_filter( SLAP_SET_GATHER gatherer, SetCookie *cp, struct berval *fbv, struct berval *user, struct berval *target, BerVarray *results ) { #define STACK_SIZE 64 #define IS_SET(x) ( (unsigned long)(x) >= 256 ) #define IS_OP(x) ( (unsigned long)(x) < 256 ) #define SF_ERROR(x) do { rc = -1; goto _error; } while ( 0 ) #define SF_TOP() ( (BerVarray)( ( stp < 0 ) ? 0 : stack[ stp ] ) ) #define SF_POP() ( (BerVarray)( ( stp < 0 ) ? 0 : stack[ stp-- ] ) ) #define SF_PUSH(x) do { \ if ( stp >= ( STACK_SIZE - 1 ) ) SF_ERROR( overflow ); \ stack[ ++stp ] = (BerVarray)(long)(x); \ } while ( 0 ) BerVarray set, lset; BerVarray stack[ STACK_SIZE ] = { 0 }; int len, rc, stp; unsigned long op; char c, *filter = fbv->bv_val; if ( results ) { *results = NULL; } stp = -1; while ( ( c = *filter++ ) ) { set = NULL; switch ( c ) { case ' ': case '\t': case '\x0A': case '\x0D': break; case '(' /* ) */ : if ( IS_SET( SF_TOP() ) ) { SF_ERROR( syntax ); } SF_PUSH( c ); break; case /* ( */ ')': set = SF_POP(); if ( IS_OP( set ) ) { SF_ERROR( syntax ); } if ( SF_TOP() == (void *)'(' /* ) */ ) { SF_POP(); SF_PUSH( set ); set = NULL; } else if ( IS_OP( SF_TOP() ) ) { op = (unsigned long)SF_POP(); lset = SF_POP(); SF_POP(); set = slap_set_join( cp, lset, op, set ); if ( set == NULL ) { SF_ERROR( memory ); } SF_PUSH( set ); set = NULL; } else { SF_ERROR( syntax ); } break; case '|': /* union */ case '&': /* intersection */ case '+': /* string concatenation */ set = SF_POP(); if ( IS_OP( set ) ) { SF_ERROR( syntax ); } if ( SF_TOP() == 0 || SF_TOP() == (void *)'(' /* ) */ ) { SF_PUSH( set ); set = NULL; } else if ( IS_OP( SF_TOP() ) ) { op = (unsigned long)SF_POP(); lset = SF_POP(); set = slap_set_join( cp, lset, op, set ); if ( set == NULL ) { SF_ERROR( memory ); } SF_PUSH( set ); set = NULL; } else { SF_ERROR( syntax ); } SF_PUSH( c ); break; case '[' /* ] */: if ( ( SF_TOP() == (void *)'/' ) || IS_SET( SF_TOP() ) ) { SF_ERROR( syntax ); } for ( len = 0; ( c = *filter++ ) && ( c != /* [ */ ']' ); len++ ) ; if ( c == 0 ) { SF_ERROR( syntax ); } set = cp->set_op->o_tmpcalloc( 2, sizeof( struct berval ), cp->set_op->o_tmpmemctx ); if ( set == NULL ) { SF_ERROR( memory ); } set->bv_val = cp->set_op->o_tmpcalloc( len + 1, sizeof( char ), cp->set_op->o_tmpmemctx ); if ( BER_BVISNULL( set ) ) { SF_ERROR( memory ); } AC_MEMCPY( set->bv_val, &filter[ - len - 1 ], len ); set->bv_len = len; SF_PUSH( set ); set = NULL; break; case '-': if ( ( SF_TOP() == (void *)'/' ) && ( *filter == '*' || ASCII_DIGIT( *filter ) ) ) { SF_POP(); if ( *filter == '*' ) { set = set_parents( cp, SF_POP() ); filter++; } else { char *next = NULL; long parent = strtol( filter, &next, 10 ); if ( next == filter ) { SF_ERROR( syntax ); } set = SF_POP(); if ( parent != 0 ) { set = set_parent( cp, set, parent ); } filter = next; } if ( set == NULL ) { SF_ERROR( memory ); } SF_PUSH( set ); set = NULL; break; } else { c = *filter++; if ( c != '>' ) { SF_ERROR( syntax ); } /* fall through to next case */ } case '/': if ( IS_OP( SF_TOP() ) ) { SF_ERROR( syntax ); } SF_PUSH( '/' ); break; default: if ( !AD_LEADCHAR( c ) ) { SF_ERROR( syntax ); } filter--; for ( len = 1; ( c = filter[ len ] ) && AD_CHAR( c ); len++ ) { /* count */ if ( c == '-' && !AD_CHAR( filter[ len + 1 ] ) ) { break; } } if ( len == 4 && memcmp( "this", filter, len ) == 0 ) { assert( !BER_BVISNULL( target ) ); if ( ( SF_TOP() == (void *)'/' ) || IS_SET( SF_TOP() ) ) { SF_ERROR( syntax ); } set = cp->set_op->o_tmpcalloc( 2, sizeof( struct berval ), cp->set_op->o_tmpmemctx ); if ( set == NULL ) { SF_ERROR( memory ); } ber_dupbv_x( set, target, cp->set_op->o_tmpmemctx ); if ( BER_BVISNULL( set ) ) { SF_ERROR( memory ); } BER_BVZERO( &set[ 1 ] ); } else if ( len == 4 && memcmp( "user", filter, len ) == 0 ) { if ( ( SF_TOP() == (void *)'/' ) || IS_SET( SF_TOP() ) ) { SF_ERROR( syntax ); } if ( BER_BVISNULL( user ) ) { SF_ERROR( memory ); } set = cp->set_op->o_tmpcalloc( 2, sizeof( struct berval ), cp->set_op->o_tmpmemctx ); if ( set == NULL ) { SF_ERROR( memory ); } ber_dupbv_x( set, user, cp->set_op->o_tmpmemctx ); BER_BVZERO( &set[ 1 ] ); } else if ( SF_TOP() != (void *)'/' ) { SF_ERROR( syntax ); } else { struct berval fb2; AttributeDescription *ad = NULL; const char *text = NULL; SF_POP(); fb2.bv_val = filter; fb2.bv_len = len; if ( slap_bv2ad( &fb2, &ad, &text ) != LDAP_SUCCESS ) { SF_ERROR( syntax ); } /* NOTE: ad must have distinguishedName syntax * or expand in an LDAP URI if c == '*' */ set = set_chase( gatherer, cp, SF_POP(), ad, c == '*' ); if ( set == NULL ) { SF_ERROR( memory ); } if ( c == '*' ) { len++; } } filter += len; SF_PUSH( set ); set = NULL; break; } } set = SF_POP(); if ( IS_OP( set ) ) { SF_ERROR( syntax ); } if ( SF_TOP() == 0 ) { /* FIXME: ok ? */ ; } else if ( IS_OP( SF_TOP() ) ) { op = (unsigned long)SF_POP(); lset = SF_POP(); set = slap_set_join( cp, lset, op, set ); if ( set == NULL ) { SF_ERROR( memory ); } } else { SF_ERROR( syntax ); } rc = slap_set_isempty( set ) ? 0 : 1; if ( results ) { *results = set; set = NULL; } _error: if ( IS_SET( set ) ) { ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx ); } while ( ( set = SF_POP() ) ) { if ( IS_SET( set ) ) { ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx ); } } return rc; }
static BerVarray set_parents( SetCookie *cp, BerVarray set ) { int i, j, last; struct berval bv, pbv; BerVarray nset, vals; if ( set == NULL ) { set = cp->set_op->o_tmpcalloc( 1, sizeof( struct berval ), cp->set_op->o_tmpmemctx ); if ( set != NULL ) { BER_BVZERO( &set[ 0 ] ); } return set; } if ( BER_BVISNULL( &set[ 0 ] ) ) { return set; } nset = cp->set_op->o_tmpcalloc( 1, sizeof( struct berval ), cp->set_op->o_tmpmemctx ); if ( nset == NULL ) { ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx ); return NULL; } BER_BVZERO( &nset[ 0 ] ); for ( i = 0; !BER_BVISNULL( &set[ i ] ); i++ ) { int level = 1; pbv = bv = set[ i ]; for ( ; !BER_BVISEMPTY( &pbv ); dnParent( &bv, &pbv ) ) { level++; bv = pbv; } vals = cp->set_op->o_tmpcalloc( level + 1, sizeof( struct berval ), cp->set_op->o_tmpmemctx ); if ( vals == NULL ) { ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx ); ber_bvarray_free_x( nset, cp->set_op->o_tmpmemctx ); return NULL; } BER_BVZERO( &vals[ 0 ] ); last = 0; bv = set[ i ]; for ( j = 0 ; j < level ; j++ ) { ber_dupbv_x( &vals[ last ], &bv, cp->set_op->o_tmpmemctx ); last++; dnParent( &bv, &bv ); } BER_BVZERO( &vals[ last ] ); nset = slap_set_join( cp, nset, '|', vals ); } ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx ); return nset; }
/* Join two sets according to operator op and flags op_flags. * op can be: * '|' (or): the union between the two sets is returned, * eliminating duplicates * '&' (and): the intersection between the two sets * is returned * '+' (add): the inner product of the two sets is returned, * namely a set containing the concatenation of * all combinations of the two sets members, * except for duplicates. * The two sets are disposed of according to the flags as described * for slap_set_dispose(). */ BerVarray slap_set_join( SetCookie *cp, BerVarray lset, unsigned op_flags, BerVarray rset ) { BerVarray set; long i, j, last, rlast; unsigned op = ( op_flags & SLAP_SET_OPMASK ); set = NULL; switch ( op ) { case '|': /* union */ if ( lset == NULL || BER_BVISNULL( &lset[ 0 ] ) ) { if ( rset == NULL ) { if ( lset == NULL ) { set = cp->set_op->o_tmpcalloc( 1, sizeof( struct berval ), cp->set_op->o_tmpmemctx ); BER_BVZERO( &set[ 0 ] ); goto done2; } set = set_dup( cp, lset, SLAP_SET_LREF2REF( op_flags ) ); goto done2; } slap_set_dispose( cp, lset, SLAP_SET_LREF2REF( op_flags ) ); set = set_dup( cp, rset, SLAP_SET_RREF2REF( op_flags ) ); goto done2; } if ( rset == NULL || BER_BVISNULL( &rset[ 0 ] ) ) { slap_set_dispose( cp, rset, SLAP_SET_RREF2REF( op_flags ) ); set = set_dup( cp, lset, SLAP_SET_LREF2REF( op_flags ) ); goto done2; } /* worst scenario: no duplicates */ rlast = slap_set_size( rset ); i = slap_set_size( lset ) + rlast + 1; set = cp->set_op->o_tmpcalloc( i, sizeof( struct berval ), cp->set_op->o_tmpmemctx ); if ( set != NULL ) { /* set_chase() depends on this routine to * keep the first elements of the result * set the same (and in the same order) * as the left-set. */ for ( i = 0; !BER_BVISNULL( &lset[ i ] ); i++ ) { if ( op_flags & SLAP_SET_LREFVAL ) { ber_dupbv_x( &set[ i ], &lset[ i ], cp->set_op->o_tmpmemctx ); } else { set[ i ] = lset[ i ]; } } /* pointers to values have been used in set - don't free twice */ op_flags |= SLAP_SET_LREFVAL; last = i; for ( i = 0; !BER_BVISNULL( &rset[ i ] ); i++ ) { int exists = 0; for ( j = 0; !BER_BVISNULL( &set[ j ] ); j++ ) { if ( bvmatch( &rset[ i ], &set[ j ] ) ) { if ( !( op_flags & SLAP_SET_RREFVAL ) ) { cp->set_op->o_tmpfree( rset[ i ].bv_val, cp->set_op->o_tmpmemctx ); rset[ i ] = rset[ --rlast ]; BER_BVZERO( &rset[ rlast ] ); i--; } exists = 1; break; } } if ( !exists ) { if ( op_flags & SLAP_SET_RREFVAL ) { ber_dupbv_x( &set[ last ], &rset[ i ], cp->set_op->o_tmpmemctx ); } else { set[ last ] = rset[ i ]; } last++; } } /* pointers to values have been used in set - don't free twice */ op_flags |= SLAP_SET_RREFVAL; BER_BVZERO( &set[ last ] ); } break; case '&': /* intersection */ if ( lset == NULL || BER_BVISNULL( &lset[ 0 ] ) || rset == NULL || BER_BVISNULL( &rset[ 0 ] ) ) { set = cp->set_op->o_tmpcalloc( 1, sizeof( struct berval ), cp->set_op->o_tmpmemctx ); BER_BVZERO( &set[ 0 ] ); break; } else { long llen, rlen; BerVarray sset; llen = slap_set_size( lset ); rlen = slap_set_size( rset ); /* dup the shortest */ if ( llen < rlen ) { last = llen; set = set_dup( cp, lset, SLAP_SET_LREF2REF( op_flags ) ); lset = NULL; sset = rset; } else { last = rlen; set = set_dup( cp, rset, SLAP_SET_RREF2REF( op_flags ) ); rset = NULL; sset = lset; } if ( set == NULL ) { break; } for ( i = 0; !BER_BVISNULL( &set[ i ] ); i++ ) { for ( j = 0; !BER_BVISNULL( &sset[ j ] ); j++ ) { if ( bvmatch( &set[ i ], &sset[ j ] ) ) { break; } } if ( BER_BVISNULL( &sset[ j ] ) ) { cp->set_op->o_tmpfree( set[ i ].bv_val, cp->set_op->o_tmpmemctx ); set[ i ] = set[ --last ]; BER_BVZERO( &set[ last ] ); i--; } } } break; case '+': /* string concatenation */ i = slap_set_size( rset ); j = slap_set_size( lset ); /* handle empty set cases */ if ( i == 0 || j == 0 ) { set = cp->set_op->o_tmpcalloc( 1, sizeof( struct berval ), cp->set_op->o_tmpmemctx ); if ( set == NULL ) { break; } BER_BVZERO( &set[ 0 ] ); break; } set = cp->set_op->o_tmpcalloc( i * j + 1, sizeof( struct berval ), cp->set_op->o_tmpmemctx ); if ( set == NULL ) { break; } for ( last = 0, i = 0; !BER_BVISNULL( &lset[ i ] ); i++ ) { for ( j = 0; !BER_BVISNULL( &rset[ j ] ); j++ ) { struct berval bv; long k; /* don't concatenate with the empty string */ if ( BER_BVISEMPTY( &lset[ i ] ) ) { ber_dupbv_x( &bv, &rset[ j ], cp->set_op->o_tmpmemctx ); if ( bv.bv_val == NULL ) { ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx ); set = NULL; goto done; } } else if ( BER_BVISEMPTY( &rset[ j ] ) ) { ber_dupbv_x( &bv, &lset[ i ], cp->set_op->o_tmpmemctx ); if ( bv.bv_val == NULL ) { ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx ); set = NULL; goto done; } } else { bv.bv_len = lset[ i ].bv_len + rset[ j ].bv_len; bv.bv_val = cp->set_op->o_tmpalloc( bv.bv_len + 1, cp->set_op->o_tmpmemctx ); if ( bv.bv_val == NULL ) { ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx ); set = NULL; goto done; } AC_MEMCPY( bv.bv_val, lset[ i ].bv_val, lset[ i ].bv_len ); AC_MEMCPY( &bv.bv_val[ lset[ i ].bv_len ], rset[ j ].bv_val, rset[ j ].bv_len ); bv.bv_val[ bv.bv_len ] = '\0'; } for ( k = 0; k < last; k++ ) { if ( bvmatch( &set[ k ], &bv ) ) { cp->set_op->o_tmpfree( bv.bv_val, cp->set_op->o_tmpmemctx ); break; } } if ( k == last ) { set[ last++ ] = bv; } } } BER_BVZERO( &set[ last ] ); break; default: break; } done:; if ( lset ) slap_set_dispose( cp, lset, SLAP_SET_LREF2REF( op_flags ) ); if ( rset ) slap_set_dispose( cp, rset, SLAP_SET_RREF2REF( op_flags ) ); done2:; if ( LogTest( LDAP_DEBUG_ACL ) ) { if ( BER_BVISNULL( set ) ) { Debug( LDAP_DEBUG_ACL, " ACL set: empty\n", 0, 0, 0 ); } else { for ( i = 0; !BER_BVISNULL( &set[ i ] ); i++ ) { Debug( LDAP_DEBUG_ACL, " ACL set[%ld]=%s\n", i, set[i].bv_val, 0 ); } } } return set; }
int ndb_back_modrdn( Operation *op, SlapReply *rs ) { struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private; AttributeDescription *children = slap_schema.si_ad_children; AttributeDescription *entry = slap_schema.si_ad_entry; struct berval new_dn = BER_BVNULL, new_ndn = BER_BVNULL; Entry e = {0}; Entry e2 = {0}; char textbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof textbuf; struct berval *np_dn = NULL; /* newSuperior dn */ struct berval *np_ndn = NULL; /* newSuperior ndn */ int manageDSAit = get_manageDSAit( op ); int num_retries = 0; NdbArgs NA, NA2; NdbRdns rdns, rdn2; struct berval matched; LDAPControl **preread_ctrl = NULL; LDAPControl **postread_ctrl = NULL; LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; int num_ctrls = 0; int rc; Debug( LDAP_DEBUG_ARGS, "==>" LDAP_XSTRING(ndb_back_modrdn) "(%s,%s,%s)\n", op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val, op->oq_modrdn.rs_newSup ? op->oq_modrdn.rs_newSup->bv_val : "NULL" ); ctrls[num_ctrls] = NULL; slap_mods_opattrs( op, &op->orr_modlist, 1 ); e.e_name = op->o_req_dn; e.e_nname = op->o_req_ndn; /* Get our NDB handle */ rs->sr_err = ndb_thread_handle( op, &NA.ndb ); rdns.nr_num = 0; NA.rdns = &rdns; NA.e = &e; NA2.ndb = NA.ndb; NA2.e = &e2; NA2.rdns = &rdn2; if( 0 ) { retry: /* transaction retry */ NA.txn->close(); NA.txn = NULL; if ( e.e_attrs ) { attrs_free( e.e_attrs ); e.e_attrs = NULL; } Debug( LDAP_DEBUG_TRACE, "==>" LDAP_XSTRING(ndb_back_modrdn) ": retrying...\n", 0, 0, 0 ); if ( op->o_abandon ) { rs->sr_err = SLAPD_ABANDON; goto return_results; } if ( NA2.ocs ) { ber_bvarray_free_x( NA2.ocs, op->o_tmpmemctx ); } if ( NA.ocs ) { ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx ); } ndb_trans_backoff( ++num_retries ); } NA.ocs = NULL; NA2.ocs = NULL; /* begin transaction */ NA.txn = NA.ndb->startTransaction(); rs->sr_text = NULL; if( !NA.txn ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": startTransaction failed: %s (%d)\n", NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } NA2.txn = NA.txn; /* get entry */ rs->sr_err = ndb_entry_get_info( op, &NA, 1, &matched ); switch( rs->sr_err ) { case 0: break; case LDAP_NO_SUCH_OBJECT: Debug( LDAP_DEBUG_ARGS, "<=- ndb_back_modrdn: no such object %s\n", op->o_req_dn.bv_val, 0, 0 ); rs->sr_matched = matched.bv_val; if ( NA.ocs ) ndb_check_referral( op, rs, &NA ); goto return_results; #if 0 case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; #endif 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; } /* acquire and lock entry */ rs->sr_err = ndb_entry_get_data( op, &NA, 1 ); if ( rs->sr_err ) goto return_results; if ( !manageDSAit && is_entry_glue( &e )) { rs->sr_err = LDAP_NO_SUCH_OBJECT; goto return_results; } if ( get_assert( op ) && ( test_filter( op, &e, (Filter *)get_assertion( op )) != LDAP_COMPARE_TRUE )) { rs->sr_err = LDAP_ASSERTION_FAILED; goto return_results; } /* check write on old entry */ rs->sr_err = access_allowed( op, &e, entry, NULL, ACL_WRITE, NULL ); if ( ! rs->sr_err ) { Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0, 0, 0 ); rs->sr_text = "no write access to old entry"; rs->sr_err = LDAP_INSUFFICIENT_ACCESS; goto return_results; } /* Can't do it if we have kids */ rs->sr_err = ndb_has_children( &NA, &rc ); if ( rs->sr_err ) { Debug(LDAP_DEBUG_ARGS, "<=- " LDAP_XSTRING(ndb_back_modrdn) ": has_children failed: %s (%d)\n", NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } if ( rc == LDAP_COMPARE_TRUE ) { Debug(LDAP_DEBUG_ARGS, "<=- " LDAP_XSTRING(ndb_back_modrdn) ": non-leaf %s\n", op->o_req_dn.bv_val, 0, 0); rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF; rs->sr_text = "subtree rename not supported"; goto return_results; } if (!manageDSAit && is_entry_referral( &e ) ) { /* entry is a referral, don't allow modrdn */ rs->sr_ref = get_entry_referrals( op, &e ); Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": entry %s is referral\n", e.e_dn, 0, 0 ); rs->sr_err = LDAP_REFERRAL, rs->sr_matched = op->o_req_dn.bv_val; rs->sr_flags = REP_REF_MUSTBEFREED; goto return_results; } if ( be_issuffix( op->o_bd, &e.e_nname ) ) { /* There can only be one suffix entry */ rs->sr_err = LDAP_NAMING_VIOLATION; rs->sr_text = "cannot rename suffix entry"; goto return_results; } else { dnParent( &e.e_nname, &e2.e_nname ); dnParent( &e.e_name, &e2.e_name ); } /* check parent for "children" acl */ rs->sr_err = access_allowed( op, &e2, children, NULL, op->oq_modrdn.rs_newSup == NULL ? ACL_WRITE : ACL_WDEL, NULL ); if ( ! rs->sr_err ) { rs->sr_err = LDAP_INSUFFICIENT_ACCESS; Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, 0, 0 ); rs->sr_text = "no write access to old parent's children"; goto return_results; } Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": wr to children " "of entry %s OK\n", e2.e_name.bv_val, 0, 0 ); if ( op->oq_modrdn.rs_newSup != NULL ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": new parent \"%s\" requested...\n", op->oq_modrdn.rs_newSup->bv_val, 0, 0 ); /* newSuperior == oldParent? */ if( dn_match( &e2.e_nname, op->oq_modrdn.rs_nnewSup ) ) { Debug( LDAP_DEBUG_TRACE, "bdb_back_modrdn: " "new parent \"%s\" same as the old parent \"%s\"\n", op->oq_modrdn.rs_newSup->bv_val, e2.e_name.bv_val, 0 ); op->oq_modrdn.rs_newSup = NULL; /* ignore newSuperior */ } } if ( op->oq_modrdn.rs_newSup != NULL ) { if ( op->oq_modrdn.rs_newSup->bv_len ) { rdn2.nr_num = 0; np_dn = op->oq_modrdn.rs_newSup; np_ndn = op->oq_modrdn.rs_nnewSup; /* newSuperior == oldParent? - checked above */ /* newSuperior == entry being moved?, if so ==> ERROR */ if ( dnIsSuffix( np_ndn, &e.e_nname )) { rs->sr_err = LDAP_NO_SUCH_OBJECT; rs->sr_text = "new superior not found"; goto return_results; } /* Get Entry with dn=newSuperior. Does newSuperior exist? */ e2.e_name = *np_dn; e2.e_nname = *np_ndn; rs->sr_err = ndb_entry_get_info( op, &NA2, 1, NULL ); switch( rs->sr_err ) { case 0: break; case LDAP_NO_SUCH_OBJECT: Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": newSup(ndn=%s) not here!\n", np_ndn->bv_val, 0, 0); rs->sr_text = "new superior not found"; goto return_results; #if 0 case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; #endif 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 ( NA2.ocs ) { Attribute a; int i; for ( i=0; !BER_BVISNULL( &NA2.ocs[i] ); i++); a.a_numvals = i; a.a_desc = slap_schema.si_ad_objectClass; a.a_vals = NA2.ocs; a.a_nvals = NA2.ocs; a.a_next = NULL; e2.e_attrs = &a; if ( is_entry_alias( &e2 )) { /* parent is an alias, don't allow move */ Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": entry is alias\n", 0, 0, 0 ); rs->sr_text = "new superior is an alias"; rs->sr_err = LDAP_ALIAS_PROBLEM; goto return_results; } if ( is_entry_referral( &e2 ) ) { /* parent is a referral, don't allow move */ Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": entry is referral\n", 0, 0, 0 ); rs->sr_text = "new superior is a referral"; rs->sr_err = LDAP_OTHER; goto return_results; } } } /* check newSuperior for "children" acl */ rs->sr_err = access_allowed( op, &e2, children, NULL, ACL_WADD, NULL ); if( ! rs->sr_err ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": no wr to newSup children\n", 0, 0, 0 ); rs->sr_text = "no write access to new superior's children"; rs->sr_err = LDAP_INSUFFICIENT_ACCESS; goto return_results; } Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": wr to new parent OK id=%ld\n", (long) e2.e_id, 0, 0 ); } /* Build target dn and make sure target entry doesn't exist already. */ if (!new_dn.bv_val) { build_new_dn( &new_dn, &e2.e_name, &op->oq_modrdn.rs_newrdn, NULL ); } if (!new_ndn.bv_val) { build_new_dn( &new_ndn, &e2.e_nname, &op->oq_modrdn.rs_nnewrdn, NULL ); } Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": new ndn=%s\n", new_ndn.bv_val, 0, 0 ); /* Allow rename to same DN */ if ( !bvmatch ( &new_ndn, &e.e_nname )) { rdn2.nr_num = 0; e2.e_name = new_dn; e2.e_nname = new_ndn; NA2.ocs = &matched; rs->sr_err = ndb_entry_get_info( op, &NA2, 1, NULL ); NA2.ocs = NULL; switch( rs->sr_err ) { #if 0 case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; #endif case LDAP_NO_SUCH_OBJECT: break; case 0: rs->sr_err = LDAP_ALREADY_EXISTS; goto return_results; default: rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } } assert( op->orr_modlist != NULL ); if( op->o_preread ) { if( preread_ctrl == NULL ) { preread_ctrl = &ctrls[num_ctrls++]; ctrls[num_ctrls] = NULL; } if( slap_read_controls( op, rs, &e, &slap_pre_read_bv, preread_ctrl ) ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(ndb_back_modrdn) ": pre-read failed!\n", 0, 0, 0 ); if ( op->o_preread & SLAP_CONTROL_CRITICAL ) { /* FIXME: is it correct to abort * operation if control fails? */ goto return_results; } } } /* delete old DN */ rs->sr_err = ndb_entry_del_info( op->o_bd, &NA ); if ( rs->sr_err != 0 ) { Debug(LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(ndb_back_modrdn) ": dn2id del failed: %s (%d)\n", NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 ); #if 0 switch( rs->sr_err ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; } #endif rs->sr_err = LDAP_OTHER; rs->sr_text = "DN index delete fail"; goto return_results; } /* copy entry fields */ e2.e_attrs = e.e_attrs; e2.e_id = e.e_id; /* add new DN */ rs->sr_err = ndb_entry_put_info( op->o_bd, &NA2, 0 ); if ( rs->sr_err != 0 ) { Debug(LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(ndb_back_modrdn) ": dn2id add failed: %s (%d)\n", NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 ); #if 0 switch( rs->sr_err ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; } #endif rs->sr_err = LDAP_OTHER; rs->sr_text = "DN index add failed"; goto return_results; } /* modify entry */ rs->sr_err = ndb_modify_internal( op, &NA2, &rs->sr_text, textbuf, textlen ); if( rs->sr_err != LDAP_SUCCESS ) { Debug(LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(ndb_back_modrdn) ": modify failed: %s (%d)\n", NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 ); #if 0 switch( rs->sr_err ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; } #endif goto return_results; } e.e_attrs = e2.e_attrs; if( op->o_postread ) { if( postread_ctrl == NULL ) { postread_ctrl = &ctrls[num_ctrls++]; ctrls[num_ctrls] = NULL; } if( slap_read_controls( op, rs, &e2, &slap_post_read_bv, postread_ctrl ) ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(ndb_back_modrdn) ": post-read failed!\n", 0, 0, 0 ); if ( op->o_postread & SLAP_CONTROL_CRITICAL ) { /* FIXME: is it correct to abort * operation if control fails? */ goto return_results; } } } if( op->o_noop ) { if (( rs->sr_err=NA.txn->execute( NdbTransaction::Rollback, NdbOperation::AbortOnError, 1 )) != 0 ) { rs->sr_text = "txn_abort (no-op) failed"; } else { rs->sr_err = LDAP_X_NO_OPERATION; } } else { if (( rs->sr_err=NA.txn->execute( NdbTransaction::Commit, NdbOperation::AbortOnError, 1 )) != 0 ) { rs->sr_text = "txn_commit failed"; } else { rs->sr_err = LDAP_SUCCESS; } } if( rs->sr_err != LDAP_SUCCESS && rs->sr_err != LDAP_X_NO_OPERATION ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": txn_%s failed: %s (%d)\n", op->o_noop ? "abort (no-op)" : "commit", NA.txn->getNdbError().message, NA.txn->getNdbError().code ); rs->sr_err = LDAP_OTHER; goto return_results; } NA.txn->close(); NA.txn = NULL; Debug(LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": rdn modified%s id=%08lx dn=\"%s\"\n", op->o_noop ? " (no-op)" : "", e.e_id, op->o_req_dn.bv_val ); rs->sr_err = LDAP_SUCCESS; rs->sr_text = NULL; if( num_ctrls ) rs->sr_ctrls = ctrls; return_results: if ( NA2.ocs ) { ber_bvarray_free_x( NA2.ocs, op->o_tmpmemctx ); NA2.ocs = NULL; } if ( NA.ocs ) { ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx ); NA.ocs = NULL; } if ( e.e_attrs ) { attrs_free( e.e_attrs ); e.e_attrs = NULL; } if( NA.txn != NULL ) { NA.txn->execute( Rollback ); NA.txn->close(); } send_ldap_result( op, rs ); slap_graduate_commit_csn( op ); if( new_dn.bv_val != NULL ) free( new_dn.bv_val ); if( new_ndn.bv_val != NULL ) free( new_ndn.bv_val ); if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) { slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); slap_sl_free( *preread_ctrl, op->o_tmpmemctx ); } if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) { slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); slap_sl_free( *postread_ctrl, op->o_tmpmemctx ); } rs->sr_text = NULL; return rs->sr_err; }
int ndb_back_delete( Operation *op, SlapReply *rs ) { struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private; Entry e = {0}; Entry p = {0}; int manageDSAit = get_manageDSAit( op ); AttributeDescription *children = slap_schema.si_ad_children; AttributeDescription *entry = slap_schema.si_ad_entry; NdbArgs NA; NdbRdns rdns; struct berval matched; int num_retries = 0; int rc; LDAPControl **preread_ctrl = NULL; LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; int num_ctrls = 0; Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(ndb_back_delete) ": %s\n", op->o_req_dn.bv_val, 0, 0 ); ctrls[num_ctrls] = 0; /* allocate CSN */ if ( BER_BVISNULL( &op->o_csn ) ) { struct berval csn; char csnbuf[LDAP_PVT_CSNSTR_BUFSIZE]; csn.bv_val = csnbuf; csn.bv_len = sizeof(csnbuf); slap_get_csn( op, &csn, 1 ); } if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) { dnParent( &op->o_req_dn, &p.e_name ); dnParent( &op->o_req_ndn, &p.e_nname ); } /* Get our NDB handle */ rs->sr_err = ndb_thread_handle( op, &NA.ndb ); rdns.nr_num = 0; NA.rdns = &rdns; NA.ocs = NULL; NA.e = &e; e.e_name = op->o_req_dn; e.e_nname = op->o_req_ndn; if( 0 ) { retry: /* transaction retry */ NA.txn->close(); NA.txn = NULL; Debug( LDAP_DEBUG_TRACE, "==> " LDAP_XSTRING(ndb_back_delete) ": retrying...\n", 0, 0, 0 ); if ( op->o_abandon ) { rs->sr_err = SLAPD_ABANDON; goto return_results; } if ( NA.ocs ) { ber_bvarray_free( NA.ocs ); NA.ocs = NULL; } ndb_trans_backoff( ++num_retries ); } /* begin transaction */ NA.txn = NA.ndb->startTransaction(); rs->sr_text = NULL; if( !NA.txn ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_delete) ": startTransaction failed: %s (%d)\n", NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } /* get entry */ rs->sr_err = ndb_entry_get_info( op, &NA, 1, &matched ); switch( rs->sr_err ) { case 0: case LDAP_NO_SUCH_OBJECT: break; #if 0 case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; #endif 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 == LDAP_NO_SUCH_OBJECT || ( !manageDSAit && bvmatch( NA.ocs, &glue_bv ))) { Debug( LDAP_DEBUG_ARGS, "<=- " LDAP_XSTRING(ndb_back_delete) ": no such object %s\n", op->o_req_dn.bv_val, 0, 0); if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) { rs->sr_matched = matched.bv_val; if ( NA.ocs ) ndb_check_referral( op, rs, &NA ); } else { rs->sr_matched = p.e_name.bv_val; rs->sr_err = LDAP_NO_SUCH_OBJECT; } goto return_results; } /* check parent for "children" acl */ rs->sr_err = access_allowed( op, &p, children, NULL, ACL_WDEL, NULL ); if ( !rs->sr_err ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(ndb_back_delete) ": no write " "access to parent\n", 0, 0, 0 ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; rs->sr_text = "no write access to parent"; goto return_results; } rs->sr_err = ndb_entry_get_data( op, &NA, 1 ); rs->sr_err = access_allowed( op, &e, entry, NULL, ACL_WDEL, NULL ); if ( !rs->sr_err ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(ndb_back_delete) ": no write access " "to entry\n", 0, 0, 0 ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; rs->sr_text = "no write access to entry"; goto return_results; } if ( !manageDSAit && is_entry_referral( &e ) ) { /* entry is a referral, don't allow delete */ rs->sr_ref = get_entry_referrals( op, &e ); Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_delete) ": entry is referral\n", 0, 0, 0 ); rs->sr_err = LDAP_REFERRAL; rs->sr_matched = e.e_name.bv_val; rs->sr_flags = REP_REF_MUSTBEFREED; goto return_results; } if ( get_assert( op ) && ( test_filter( op, &e, (Filter *)get_assertion( op )) != LDAP_COMPARE_TRUE )) { rs->sr_err = LDAP_ASSERTION_FAILED; goto return_results; } /* pre-read */ if( op->o_preread ) { if( preread_ctrl == NULL ) { preread_ctrl = &ctrls[num_ctrls++]; ctrls[num_ctrls] = NULL; } if( slap_read_controls( op, rs, &e, &slap_pre_read_bv, preread_ctrl ) ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(ndb_back_delete) ": pre-read " "failed!\n", 0, 0, 0 ); if ( op->o_preread & SLAP_CONTROL_CRITICAL ) { /* FIXME: is it correct to abort * operation if control fails? */ goto return_results; } } } /* Can't do it if we have kids */ rs->sr_err = ndb_has_children( &NA, &rc ); if ( rs->sr_err ) { Debug(LDAP_DEBUG_ARGS, "<=- " LDAP_XSTRING(ndb_back_delete) ": has_children failed: %s (%d)\n", NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } if ( rc == LDAP_COMPARE_TRUE ) { Debug(LDAP_DEBUG_ARGS, "<=- " LDAP_XSTRING(ndb_back_delete) ": non-leaf %s\n", op->o_req_dn.bv_val, 0, 0); rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF; rs->sr_text = "subordinate objects must be deleted first"; goto return_results; } /* delete info */ rs->sr_err = ndb_entry_del_info( op->o_bd, &NA ); if ( rs->sr_err != 0 ) { Debug(LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(ndb_back_delete) ": del_info failed: %s (%d)\n", NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 ); rs->sr_text = "DN index delete failed"; rs->sr_err = LDAP_OTHER; goto return_results; } /* delete data */ rs->sr_err = ndb_entry_del_data( op->o_bd, &NA ); if ( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(ndb_back_delete) ": del_data failed: %s (%d)\n", NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 ); rs->sr_text = "entry delete failed"; rs->sr_err = LDAP_OTHER; goto return_results; } if( op->o_noop ) { if (( rs->sr_err=NA.txn->execute( NdbTransaction::Rollback, NdbOperation::AbortOnError, 1 )) != 0 ) { rs->sr_text = "txn (no-op) failed"; } else { rs->sr_err = LDAP_X_NO_OPERATION; } } else { if (( rs->sr_err=NA.txn->execute( NdbTransaction::Commit, NdbOperation::AbortOnError, 1 )) != 0 ) { rs->sr_text = "txn_commit failed"; } else { rs->sr_err = LDAP_SUCCESS; } } if( rs->sr_err != LDAP_SUCCESS && rs->sr_err != LDAP_X_NO_OPERATION ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_delete) ": txn_%s failed: %s (%d)\n", op->o_noop ? "abort (no-op)" : "commit", NA.txn->getNdbError().message, NA.txn->getNdbError().code ); rs->sr_err = LDAP_OTHER; rs->sr_text = "commit failed"; goto return_results; } NA.txn->close(); NA.txn = NULL; Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_delete) ": deleted%s id=%08lx dn=\"%s\"\n", op->o_noop ? " (no-op)" : "", e.e_id, op->o_req_dn.bv_val ); rs->sr_err = LDAP_SUCCESS; rs->sr_text = NULL; if( num_ctrls ) rs->sr_ctrls = ctrls; return_results: if ( NA.ocs ) { ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx ); NA.ocs = NULL; } /* free entry */ if( e.e_attrs != NULL ) { attrs_free( e.e_attrs ); e.e_attrs = NULL; } if( NA.txn != NULL ) { NA.txn->execute( Rollback ); NA.txn->close(); } send_ldap_result( op, rs ); slap_graduate_commit_csn( op ); if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) { slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); slap_sl_free( *preread_ctrl, op->o_tmpmemctx ); } return rs->sr_err; }
extern "C" int ndb_back_bind( Operation *op, SlapReply *rs ) { struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private; Entry e = {0}; Attribute *a; AttributeDescription *password = slap_schema.si_ad_userPassword; NdbArgs NA; Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(ndb_back_bind) ": dn: %s\n", op->o_req_dn.bv_val, 0, 0); /* allow noauth binds */ switch ( be_rootdn_bind( op, NULL ) ) { case LDAP_SUCCESS: /* frontend will send result */ return rs->sr_err = LDAP_SUCCESS; default: /* give the database a chance */ break; } /* Get our NDB handle */ rs->sr_err = ndb_thread_handle( op, &NA.ndb ); e.e_name = op->o_req_dn; e.e_nname = op->o_req_ndn; NA.e = &e; dn2entry_retry: NA.txn = NA.ndb->startTransaction(); rs->sr_text = NULL; if( !NA.txn ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_bind) ": startTransaction failed: %s (%d)\n", NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto done; } /* get entry */ { NdbRdns rdns; rdns.nr_num = 0; NA.rdns = &rdns; NA.ocs = NULL; rs->sr_err = ndb_entry_get_info( op, &NA, 0, NULL ); } switch(rs->sr_err) { case 0: break; case LDAP_NO_SUCH_OBJECT: rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; case LDAP_BUSY: rs->sr_text = "ldap_server_busy"; goto done; #if 0 case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto dn2entry_retry; #endif default: rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto done; } rs->sr_err = ndb_entry_get_data( op, &NA, 0 ); ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx ); ber_dupbv( &op->oq_bind.rb_edn, &e.e_name ); /* check for deleted */ if ( is_entry_subentry( &e ) ) { /* entry is an subentry, don't allow bind */ Debug( LDAP_DEBUG_TRACE, "entry is subentry\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( is_entry_alias( &e ) ) { /* entry is an alias, don't allow bind */ Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( is_entry_referral( &e ) ) { Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } switch ( op->oq_bind.rb_method ) { case LDAP_AUTH_SIMPLE: a = attr_find( e.e_attrs, password ); if ( a == NULL ) { rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( slap_passwd_check( op, &e, a, &op->oq_bind.rb_cred, &rs->sr_text ) != 0 ) { /* failure; stop front end from sending result */ rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } rs->sr_err = 0; break; default: assert( 0 ); /* should not be reachable */ rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED; rs->sr_text = "authentication method not supported"; } done: NA.txn->close(); if ( e.e_attrs ) { attrs_free( e.e_attrs ); e.e_attrs = NULL; } if ( rs->sr_err ) { send_ldap_result( op, rs ); } /* front end will send result on success (rs->sr_err==0) */ return rs->sr_err; }
static int indexer( Operation *op, MDB_txn *txn, struct mdb_attrinfo *ai, AttributeDescription *ad, struct berval *atname, BerVarray vals, ID id, int opid, slap_mask_t mask ) { int rc = LDAP_OTHER; struct berval *keys; MDB_cursor *mc = ai->ai_cursor; mdb_idl_keyfunc *keyfunc; char *err __maybe_unused; assert( mask != 0 ); if ( !mc ) { err = "c_open"; rc = mdb_cursor_open( txn, ai->ai_dbi, &mc ); if ( rc ) goto done; if ( slapMode & SLAP_TOOL_QUICK ) ai->ai_cursor = mc; } if ( opid == SLAP_INDEX_ADD_OP ) { #ifdef MDB_TOOL_IDL_CACHING if (( slapMode & SLAP_TOOL_QUICK ) && slap_tool_thread_max > 2 ) { keyfunc = mdb_tool_idl_add; mc = (MDB_cursor *)ai; } else #endif keyfunc = mdb_idl_insert_keys; } else keyfunc = mdb_idl_delete_keys; if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) { rc = keyfunc( op->o_bd, mc, presence_key, id ); if( rc ) { err = "presence"; goto done; } } if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) { rc = ad->ad_type->sat_equality->smr_indexer( LDAP_FILTER_EQUALITY, mask, ad->ad_type->sat_syntax, ad->ad_type->sat_equality, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { rc = keyfunc( op->o_bd, mc, keys, id ); ber_bvarray_free_x( keys, op->o_tmpmemctx ); if ( rc ) { err = "equality"; goto done; } } rc = LDAP_SUCCESS; } if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) { rc = ad->ad_type->sat_approx->smr_indexer( LDAP_FILTER_APPROX, mask, ad->ad_type->sat_syntax, ad->ad_type->sat_approx, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { rc = keyfunc( op->o_bd, mc, keys, id ); ber_bvarray_free_x( keys, op->o_tmpmemctx ); if ( rc ) { err = "approx"; goto done; } } rc = LDAP_SUCCESS; } if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) { rc = ad->ad_type->sat_substr->smr_indexer( LDAP_FILTER_SUBSTRINGS, mask, ad->ad_type->sat_syntax, ad->ad_type->sat_substr, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { rc = keyfunc( op->o_bd, mc, keys, id ); ber_bvarray_free_x( keys, op->o_tmpmemctx ); if( rc ) { err = "substr"; goto done; } } rc = LDAP_SUCCESS; } done: if ( !(slapMode & SLAP_TOOL_QUICK)) { if (mc == ai->ai_cursor) ai->ai_cursor = NULL; mdb_cursor_close( mc ); } switch( rc ) { /* The callers all know how to deal with these results */ case 0: break; /* Anything else is bad news */ default: rc = LDAP_OTHER; } return rc; }
static int asyncmeta_send_entry( Operation *op, SlapReply *rs, a_metaconn_t *mc, int target, LDAPMessage *e ) { a_metainfo_t *mi = mc->mc_info; struct berval a, mapped = BER_BVNULL; int check_sorted_attrs = 0; Entry ent = {0}; BerElement ber = *ldap_get_message_ber( e ); Attribute *attr, **attrp; struct berval bdn, dn = BER_BVNULL; const char *text; a_dncookie dc; ber_len_t len; int rc; void *mem_mark; mem_mark = slap_sl_mark( op->o_tmpmemctx ); ber_set_option( &ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); if ( ber_scanf( &ber, "l{", &len ) == LBER_ERROR ) { return LDAP_DECODING_ERROR; } if ( ber_set_option( &ber, LBER_OPT_REMAINING_BYTES, &len ) != LBER_OPT_SUCCESS ) { return LDAP_OTHER; } if ( ber_scanf( &ber, "m{", &bdn ) == LBER_ERROR ) { return LDAP_DECODING_ERROR; } /* * Rewrite the dn of the result, if needed */ dc.op = op; dc.target = mi->mi_targets[ target ]; dc.memctx = op->o_tmpmemctx; dc.to_from = MASSAGE_REP; asyncmeta_dn_massage( &dc, &bdn, &dn ); /* * Note: this may fail if the target host(s) schema differs * from the one known to the meta, and a DN with unknown * attributes is returned. * * FIXME: should we log anything, or delegate to dnNormalize? */ rc = dnPrettyNormal( NULL, &dn, &ent.e_name, &ent.e_nname, op->o_tmpmemctx ); if ( dn.bv_val != bdn.bv_val ) { op->o_tmpfree( dn.bv_val, op->o_tmpmemctx ); } BER_BVZERO( &dn ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s asyncmeta_send_entry(\"%s\"): " "invalid DN syntax\n", op->o_log_prefix, ent.e_name.bv_val ); rc = LDAP_INVALID_DN_SYNTAX; goto done; } /* * cache dn */ if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED ) { ( void )asyncmeta_dncache_update_entry( &mi->mi_cache, &ent.e_nname, target ); } attrp = &ent.e_attrs; while ( ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) { int last = 0; slap_syntax_validate_func *validate; slap_syntax_transform_func *pretty; if ( ber_pvt_ber_remaining( &ber ) < 0 ) { Debug( LDAP_DEBUG_ANY, "%s asyncmeta_send_entry(\"%s\"): " "unable to parse attr \"%s\".\n", op->o_log_prefix, ent.e_name.bv_val, a.bv_val ); rc = LDAP_OTHER; goto done; } if ( ber_pvt_ber_remaining( &ber ) == 0 ) { break; } attr = op->o_tmpcalloc( 1, sizeof(Attribute), op->o_tmpmemctx ); if ( slap_bv2ad( &a, &attr->a_desc, &text ) != LDAP_SUCCESS) { if ( slap_bv2undef_ad( &a, &attr->a_desc, &text, SLAP_AD_PROXIED ) != LDAP_SUCCESS ) { Debug(LDAP_DEBUG_ANY, "%s meta_send_entry(\"%s\"): " "slap_bv2undef_ad(%s): %s\n", op->o_log_prefix, ent.e_name.bv_val, mapped.bv_val, text ); ( void )ber_scanf( &ber, "x" /* [W] */ ); op->o_tmpfree( attr, op->o_tmpmemctx ); continue; } } if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) check_sorted_attrs = 1; /* no subschemaSubentry */ if ( attr->a_desc == slap_schema.si_ad_subschemaSubentry || attr->a_desc == slap_schema.si_ad_entryDN ) { /* * We eat target's subschemaSubentry because * a search for this value is likely not * to resolve to the appropriate backend; * later, the local subschemaSubentry is * added. * * We also eat entryDN because the frontend * will reattach it without checking if already * present... */ ( void )ber_scanf( &ber, "x" /* [W] */ ); op->o_tmpfree( attr, op->o_tmpmemctx ); continue; } if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR || attr->a_vals == NULL ) { attr->a_vals = (struct berval *)&slap_dummy_bv; } else { for ( last = 0; !BER_BVISNULL( &attr->a_vals[ last ] ); ++last ) ; } attr->a_numvals = last; validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate; pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty; if ( !validate && !pretty ) { ber_bvarray_free_x( attr->a_vals, op->o_tmpmemctx ); op->o_tmpfree( attr, op->o_tmpmemctx ); goto next_attr; } /* * It is necessary to try to rewrite attributes with * dn syntax because they might be used in ACLs as * members of groups; since ACLs are applied to the * rewritten stuff, no dn-based subecj clause could * be used at the ldap backend side (see * http://www.OpenLDAP.org/faq/data/cache/452.html) * The problem can be overcome by moving the dn-based * ACLs to the target directory server, and letting * everything pass thru the ldap backend. */ { int i; if ( attr->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) { asyncmeta_dnattr_result_rewrite( &dc, attr->a_vals ); } else if ( attr->a_desc == slap_schema.si_ad_ref ) { asyncmeta_referral_result_rewrite( &dc, attr->a_vals ); } for ( i = 0; i < last; i++ ) { struct berval pval; int rc; if ( pretty ) { rc = ordered_value_pretty( attr->a_desc, &attr->a_vals[i], &pval, op->o_tmpmemctx ); } else { rc = ordered_value_validate( attr->a_desc, &attr->a_vals[i], 0 ); } if ( rc ) { ber_memfree_x( attr->a_vals[i].bv_val, op->o_tmpmemctx ); if ( --last == i ) { BER_BVZERO( &attr->a_vals[ i ] ); break; } attr->a_vals[i] = attr->a_vals[last]; BER_BVZERO( &attr->a_vals[last] ); i--; continue; } if ( pretty ) { ber_memfree_x( attr->a_vals[i].bv_val, op->o_tmpmemctx ); attr->a_vals[i] = pval; } } if ( last == 0 && attr->a_vals != &slap_dummy_bv ) { ber_bvarray_free_x( attr->a_vals, op->o_tmpmemctx ); op->o_tmpfree( attr, op->o_tmpmemctx ); goto next_attr; } } if ( last && attr->a_desc->ad_type->sat_equality && attr->a_desc->ad_type->sat_equality->smr_normalize ) { int i; attr->a_nvals = op->o_tmpalloc( ( last + 1 ) * sizeof( struct berval ), op->o_tmpmemctx ); for ( i = 0; i<last; i++ ) { /* if normalizer fails, drop this value */ if ( ordered_value_normalize( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, attr->a_desc, attr->a_desc->ad_type->sat_equality, &attr->a_vals[i], &attr->a_nvals[i], op->o_tmpmemctx )) { ber_memfree_x( attr->a_vals[i].bv_val, op->o_tmpmemctx ); if ( --last == i ) { BER_BVZERO( &attr->a_vals[ i ] ); break; } attr->a_vals[i] = attr->a_vals[last]; BER_BVZERO( &attr->a_vals[last] ); i--; } } BER_BVZERO( &attr->a_nvals[i] ); if ( last == 0 ) { ber_bvarray_free_x( attr->a_vals, op->o_tmpmemctx ); ber_bvarray_free_x( attr->a_nvals, op->o_tmpmemctx ); op->o_tmpfree( attr, op->o_tmpmemctx ); goto next_attr; } } else { attr->a_nvals = attr->a_vals; } attr->a_numvals = last; *attrp = attr; attrp = &attr->a_next; next_attr:; } /* Check for sorted attributes */ if ( check_sorted_attrs ) { for ( attr = ent.e_attrs; attr; attr = attr->a_next ) { if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) { while ( attr->a_numvals > 1 ) { int i; int rc = slap_sort_vals( (Modifications *)attr, &text, &i, op->o_tmpmemctx ); if ( rc != LDAP_TYPE_OR_VALUE_EXISTS ) break; /* Strip duplicate values */ if ( attr->a_nvals != attr->a_vals ) ber_memfree_x( attr->a_nvals[i].bv_val, op->o_tmpmemctx ); ber_memfree_x( attr->a_vals[i].bv_val, op->o_tmpmemctx ); attr->a_numvals--; if ( (unsigned)i < attr->a_numvals ) { attr->a_vals[i] = attr->a_vals[attr->a_numvals]; if ( attr->a_nvals != attr->a_vals ) attr->a_nvals[i] = attr->a_nvals[attr->a_numvals]; } BER_BVZERO(&attr->a_vals[attr->a_numvals]); if ( attr->a_nvals != attr->a_vals ) BER_BVZERO(&attr->a_nvals[attr->a_numvals]); } attr->a_flags |= SLAP_ATTR_SORTED_VALS; } } } Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_send_entry(\"%s\"): " ".\n", op->o_log_prefix, ent.e_name.bv_val ); ldap_get_entry_controls( mc->mc_conns[target].msc_ldr, e, &rs->sr_ctrls ); rs->sr_entry = &ent; rs->sr_attrs = op->ors_attrs; rs->sr_operational_attrs = NULL; rs->sr_flags = mi->mi_targets[ target ]->mt_rep_flags; rs->sr_err = LDAP_SUCCESS; rc = send_search_entry( op, rs ); switch ( rc ) { case LDAP_UNAVAILABLE: rc = LDAP_OTHER; break; } done:; if ( rs->sr_ctrls != NULL ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } #if 0 while ( ent.e_attrs ) { attr = ent.e_attrs; ent.e_attrs = attr->a_next; if ( attr->a_nvals != attr->a_vals ) ber_bvarray_free_x( attr->a_nvals, op->o_tmpmemctx ); ber_bvarray_free_x( attr->a_vals, op->o_tmpmemctx ); op->o_tmpfree( attr, op->o_tmpmemctx ); } if (ent.e_name.bv_val != NULL) { op->o_tmpfree( ent.e_name.bv_val, op->o_tmpmemctx ); } if (ent.e_nname.bv_val != NULL) { op->o_tmpfree( ent.e_nname.bv_val, op->o_tmpmemctx ); } if (rs->sr_entry && rs->sr_entry != &ent) { entry_free( rs->sr_entry ); } #endif slap_sl_release( mem_mark, op->o_tmpmemctx ); rs->sr_entry = NULL; rs->sr_attrs = NULL; return rc; }
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 ndb_back_modify( Operation *op, SlapReply *rs ) { struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private; Entry e = {0}; int manageDSAit = get_manageDSAit( op ); char textbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof textbuf; int num_retries = 0; NdbArgs NA; NdbRdns rdns; struct berval matched; LDAPControl **preread_ctrl = NULL; LDAPControl **postread_ctrl = NULL; LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; int num_ctrls = 0; Debug( LDAP_DEBUG_ARGS, LDAP_XSTRING(ndb_back_modify) ": %s\n", op->o_req_dn.bv_val, 0, 0 ); ctrls[num_ctrls] = NULL; slap_mods_opattrs( op, &op->orm_modlist, 1 ); e.e_name = op->o_req_dn; e.e_nname = op->o_req_ndn; /* Get our NDB handle */ rs->sr_err = ndb_thread_handle( op, &NA.ndb ); rdns.nr_num = 0; NA.rdns = &rdns; NA.e = &e; if( 0 ) { retry: /* transaction retry */ NA.txn->close(); NA.txn = NULL; if( e.e_attrs ) { attrs_free( e.e_attrs ); e.e_attrs = NULL; } Debug(LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modify) ": retrying...\n", 0, 0, 0); if ( op->o_abandon ) { rs->sr_err = SLAPD_ABANDON; goto return_results; } if ( NA.ocs ) { ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx ); } ndb_trans_backoff( ++num_retries ); } NA.ocs = NULL; /* begin transaction */ NA.txn = NA.ndb->startTransaction(); rs->sr_text = NULL; if( !NA.txn ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modify) ": startTransaction failed: %s (%d)\n", NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } /* get entry or ancestor */ rs->sr_err = ndb_entry_get_info( op, &NA, 0, &matched ); switch( rs->sr_err ) { case 0: break; case LDAP_NO_SUCH_OBJECT: Debug( LDAP_DEBUG_ARGS, "<=- ndb_back_modify: no such object %s\n", op->o_req_dn.bv_val, 0, 0 ); rs->sr_matched = matched.bv_val; if (NA.ocs ) ndb_check_referral( op, rs, &NA ); goto return_results; #if 0 case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; #endif 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; } /* acquire and lock entry */ rs->sr_err = ndb_entry_get_data( op, &NA, 1 ); if ( !manageDSAit && is_entry_referral( &e ) ) { /* entry is a referral, don't allow modify */ rs->sr_ref = get_entry_referrals( op, &e ); Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modify) ": entry is referral\n", 0, 0, 0 ); rs->sr_err = LDAP_REFERRAL; rs->sr_matched = e.e_name.bv_val; rs->sr_flags = REP_REF_MUSTBEFREED; goto return_results; } if ( get_assert( op ) && ( test_filter( op, &e, (Filter*)get_assertion( op )) != LDAP_COMPARE_TRUE )) { rs->sr_err = LDAP_ASSERTION_FAILED; goto return_results; } if( op->o_preread ) { if( preread_ctrl == NULL ) { preread_ctrl = &ctrls[num_ctrls++]; ctrls[num_ctrls] = NULL; } if ( slap_read_controls( op, rs, &e, &slap_pre_read_bv, preread_ctrl ) ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(ndb_back_modify) ": pre-read " "failed!\n", 0, 0, 0 ); if ( op->o_preread & SLAP_CONTROL_CRITICAL ) { /* FIXME: is it correct to abort * operation if control fails? */ goto return_results; } } } /* Modify the entry */ rs->sr_err = ndb_modify_internal( op, &NA, &rs->sr_text, textbuf, textlen ); if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modify) ": modify failed (%d)\n", rs->sr_err, 0, 0 ); #if 0 switch( rs->sr_err ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; } #endif goto return_results; } if( op->o_postread ) { if( postread_ctrl == NULL ) { postread_ctrl = &ctrls[num_ctrls++]; ctrls[num_ctrls] = NULL; } if( slap_read_controls( op, rs, &e, &slap_post_read_bv, postread_ctrl ) ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(ndb_back_modify) ": post-read failed!\n", 0, 0, 0 ); if ( op->o_postread & SLAP_CONTROL_CRITICAL ) { /* FIXME: is it correct to abort * operation if control fails? */ goto return_results; } } } if( op->o_noop ) { if (( rs->sr_err=NA.txn->execute( NdbTransaction::Rollback, NdbOperation::AbortOnError, 1 )) != 0 ) { rs->sr_text = "txn_abort (no-op) failed"; } else { rs->sr_err = LDAP_X_NO_OPERATION; } } else { if (( rs->sr_err=NA.txn->execute( NdbTransaction::Commit, NdbOperation::AbortOnError, 1 )) != 0 ) { rs->sr_text = "txn_commit failed"; } else { rs->sr_err = LDAP_SUCCESS; } } if( rs->sr_err != LDAP_SUCCESS && rs->sr_err != LDAP_X_NO_OPERATION ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modify) ": txn_%s failed: %s (%d)\n", op->o_noop ? "abort (no-op)" : "commit", NA.txn->getNdbError().message, NA.txn->getNdbError().code ); rs->sr_err = LDAP_OTHER; goto return_results; } NA.txn->close(); NA.txn = NULL; Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modify) ": updated%s id=%08lx dn=\"%s\"\n", op->o_noop ? " (no-op)" : "", e.e_id, op->o_req_dn.bv_val ); rs->sr_err = LDAP_SUCCESS; rs->sr_text = NULL; if( num_ctrls ) rs->sr_ctrls = ctrls; return_results: if ( NA.ocs ) { ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx ); NA.ocs = NULL; } if ( e.e_attrs != NULL ) { attrs_free( e.e_attrs ); e.e_attrs = NULL; } if( NA.txn != NULL ) { NA.txn->execute( Rollback ); NA.txn->close(); } send_ldap_result( op, rs ); slap_graduate_commit_csn( op ); if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) { slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); slap_sl_free( *preread_ctrl, op->o_tmpmemctx ); } if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) { slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); slap_sl_free( *postread_ctrl, op->o_tmpmemctx ); } rs->sr_text = NULL; return rs->sr_err; }
static int indexer( Operation *op, DB_TXN *txn, AttributeDescription *ad, struct berval *atname, BerVarray vals, ID id, int opid, slap_mask_t mask ) { int rc, i; DB *db; struct berval *keys; assert( mask != 0 ); rc = bdb_db_cache( op->o_bd, atname, &db ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "bdb_index_read: Could not open DB %s\n", atname->bv_val, 0, 0 ); return LDAP_OTHER; } if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) { rc = bdb_key_change( op->o_bd, db, txn, &presence_key, id, opid ); if( rc ) { goto done; } } if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) { rc = ad->ad_type->sat_equality->smr_indexer( LDAP_FILTER_EQUALITY, mask, ad->ad_type->sat_syntax, ad->ad_type->sat_equality, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { for( i=0; keys[i].bv_val != NULL; i++ ) { rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid ); if( rc ) { ber_bvarray_free_x( keys, op->o_tmpmemctx ); goto done; } } ber_bvarray_free_x( keys, op->o_tmpmemctx ); } rc = LDAP_SUCCESS; } if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) { rc = ad->ad_type->sat_approx->smr_indexer( LDAP_FILTER_APPROX, mask, ad->ad_type->sat_syntax, ad->ad_type->sat_approx, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { for( i=0; keys[i].bv_val != NULL; i++ ) { rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid ); if( rc ) { ber_bvarray_free_x( keys, op->o_tmpmemctx ); goto done; } } ber_bvarray_free_x( keys, op->o_tmpmemctx ); } rc = LDAP_SUCCESS; } if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) { rc = ad->ad_type->sat_substr->smr_indexer( LDAP_FILTER_SUBSTRINGS, mask, ad->ad_type->sat_syntax, ad->ad_type->sat_substr, atname, vals, &keys, op->o_tmpmemctx ); if( rc == LDAP_SUCCESS && keys != NULL ) { for( i=0; keys[i].bv_val != NULL; i++ ) { rc = bdb_key_change( op->o_bd, db, txn, &keys[i], id, opid ); if( rc ) { ber_bvarray_free_x( keys, op->o_tmpmemctx ); goto done; } } ber_bvarray_free_x( keys, op->o_tmpmemctx ); } rc = LDAP_SUCCESS; } done: switch( rc ) { /* The callers all know how to deal with these results */ case 0: case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: break; /* Anything else is bad news */ default: rc = LDAP_OTHER; } return rc; }
static int comp_equality_candidates ( Operation *op, MDB_txn *rtxn, MatchingRuleAssertion *mra, ComponentAssertion *ca, ID *ids, ID *tmp, ID *stack) { MDB_dbi dbi; int i; int rc; slap_mask_t mask; struct berval prefix = {0, NULL}; struct berval *keys = NULL; MatchingRule *mr = mra->ma_rule; Syntax *sat_syntax; ComponentReference* cr_list, *cr; AttrInfo *ai; MDB_IDL_ALL( ids ); if ( !ca->ca_comp_ref ) return 0; ai = mdb_attr_mask( op->o_bd->be_private, mra->ma_desc ); if( ai ) { cr_list = ai->ai_cr; } else { return 0; } /* find a component reference to be indexed */ sat_syntax = ca->ca_ma_rule->smr_syntax; for ( cr = cr_list ; cr ; cr = cr->cr_next ) { if ( cr->cr_string.bv_len == ca->ca_comp_ref->cr_string.bv_len && strncmp( cr->cr_string.bv_val, ca->ca_comp_ref->cr_string.bv_val,cr->cr_string.bv_len ) == 0 ) break; } if ( !cr ) return 0; rc = mdb_index_param( op->o_bd, mra->ma_desc, LDAP_FILTER_EQUALITY, &dbi, &mask, &prefix ); if( rc != LDAP_SUCCESS ) { return 0; } if( !mr ) { return 0; } if( !mr->smr_filter ) { return 0; } rc = (ca->ca_ma_rule->smr_filter)( LDAP_FILTER_EQUALITY, cr->cr_indexmask, sat_syntax, ca->ca_ma_rule, &prefix, &ca->ca_ma_value, &keys, op->o_tmpmemctx ); if( rc != LDAP_SUCCESS ) { return 0; } if( keys == NULL ) { return 0; } for ( i= 0; keys[i].bv_val != NULL; i++ ) { rc = mdb_key_read( op->o_bd, rtxn, dbi, &keys[i], tmp, NULL, 0 ); if( rc == MDB_NOTFOUND ) { MDB_IDL_ZERO( ids ); rc = 0; break; } else if( rc != LDAP_SUCCESS ) { break; } if( MDB_IDL_IS_ZERO( tmp ) ) { MDB_IDL_ZERO( ids ); break; } if ( i == 0 ) { MDB_IDL_CPY( ids, tmp ); } else { mdb_idl_intersection( ids, tmp ); } if( MDB_IDL_IS_ZERO( ids ) ) break; } ber_bvarray_free_x( keys, op->o_tmpmemctx ); Debug( LDAP_DEBUG_TRACE, "<= comp_equality_candidates: id=%ld, first=%ld, last=%ld\n", (long) ids[0], (long) MDB_IDL_FIRST(ids), (long) MDB_IDL_LAST(ids) ); return( rc ); }
static int dynlist_compare( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; dynlist_info_t *dli = (dynlist_info_t *)on->on_bi.bi_private; Operation o = *op; Entry *e = NULL; dynlist_map_t *dlm; BackendDB *be; for ( ; dli != NULL; dli = dli->dli_next ) { for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) if ( op->oq_compare.rs_ava->aa_desc == dlm->dlm_member_ad ) break; if ( dlm ) { /* This compare is for one of the attributes we're * interested in. We'll use slapd's existing dyngroup * evaluator to get the answer we want. */ BerVarray id = NULL, authz = NULL; o.o_do_not_cache = 1; if ( ad_dgIdentity && backend_attribute( &o, NULL, &o.o_req_ndn, ad_dgIdentity, &id, ACL_READ ) == LDAP_SUCCESS ) { /* if not rootdn and dgAuthz is present, * check if user can be authorized as dgIdentity */ if ( ad_dgAuthz && !BER_BVISEMPTY( id ) && !be_isroot( op ) && backend_attribute( &o, NULL, &o.o_req_ndn, ad_dgAuthz, &authz, ACL_READ ) == LDAP_SUCCESS ) { rs->sr_err = slap_sasl_matches( op, authz, &o.o_ndn, &o.o_ndn ); ber_bvarray_free_x( authz, op->o_tmpmemctx ); if ( rs->sr_err != LDAP_SUCCESS ) { goto done; } } o.o_dn = *id; o.o_ndn = *id; o.o_groups = NULL; /* authz changed, invalidate cached groups */ } rs->sr_err = backend_group( &o, NULL, &o.o_req_ndn, &o.oq_compare.rs_ava->aa_value, dli->dli_oc, dli->dli_ad ); switch ( rs->sr_err ) { case LDAP_SUCCESS: rs->sr_err = LDAP_COMPARE_TRUE; break; case LDAP_NO_SUCH_OBJECT: /* NOTE: backend_group() returns noSuchObject * if op_ndn does not exist; however, since * dynamic list expansion means that the * member attribute is virtually present, the * non-existence of the asserted value implies * the assertion is FALSE rather than * UNDEFINED */ rs->sr_err = LDAP_COMPARE_FALSE; break; } done:; if ( id ) ber_bvarray_free_x( id, o.o_tmpmemctx ); return SLAP_CB_CONTINUE; } } be = select_backend( &o.o_req_ndn, 1 ); if ( !be || !be->be_search ) { return SLAP_CB_CONTINUE; } if ( overlay_entry_get_ov( &o, &o.o_req_ndn, NULL, NULL, 0, &e, on ) != LDAP_SUCCESS || e == NULL ) { return SLAP_CB_CONTINUE; } /* check for dynlist objectClass; done if not found */ dli = (dynlist_info_t *)on->on_bi.bi_private; while ( dli != NULL && !is_entry_objectclass_or_sub( e, dli->dli_oc ) ) { dli = dli->dli_next; } if ( dli == NULL ) { goto release; } if ( ad_dgIdentity ) { Attribute *id = attrs_find( e->e_attrs, ad_dgIdentity ); if ( id ) { Attribute *authz; /* if not rootdn and dgAuthz is present, * check if user can be authorized as dgIdentity */ if ( ad_dgAuthz && !BER_BVISEMPTY( &id->a_nvals[0] ) && !be_isroot( op ) && ( authz = attrs_find( e->e_attrs, ad_dgAuthz ) ) ) { if ( slap_sasl_matches( op, authz->a_nvals, &o.o_ndn, &o.o_ndn ) != LDAP_SUCCESS ) { goto release; } } o.o_dn = id->a_vals[0]; o.o_ndn = id->a_nvals[0]; o.o_groups = NULL; } } /* generate dynamic list with dynlist_response() and compare */ { SlapReply r = { REP_SEARCH }; dynlist_cc_t dc = { { 0, dynlist_sc_compare_entry, 0, 0 }, 0 }; AttributeName an[2]; dc.dc_ava = op->orc_ava; dc.dc_res = &rs->sr_err; o.o_callback = (slap_callback *) &dc; o.o_tag = LDAP_REQ_SEARCH; o.ors_limit = NULL; o.ors_tlimit = SLAP_NO_LIMIT; o.ors_slimit = SLAP_NO_LIMIT; o.ors_filterstr = *slap_filterstr_objectClass_pres; o.ors_filter = (Filter *) slap_filter_objectClass_pres; o.ors_scope = LDAP_SCOPE_BASE; o.ors_deref = LDAP_DEREF_NEVER; an[0].an_name = op->orc_ava->aa_desc->ad_cname; an[0].an_desc = op->orc_ava->aa_desc; BER_BVZERO( &an[1].an_name ); o.ors_attrs = an; o.ors_attrsonly = 0; o.o_acl_priv = ACL_COMPARE; o.o_bd = be; (void)be->be_search( &o, &r ); if ( o.o_dn.bv_val != op->o_dn.bv_val ) { slap_op_groups_free( &o ); } } release:; if ( e != NULL ) { overlay_entry_release_ov( &o, e, 0, on ); } return SLAP_CB_CONTINUE; }
static int substring_candidates( Operation *op, MDB_txn *rtxn, SubstringsAssertion *sub, ID *ids, ID *tmp ) { MDB_dbi dbi; int i; int rc; slap_mask_t mask; struct berval prefix = {0, NULL}; struct berval *keys = NULL; MatchingRule *mr; Debug( LDAP_DEBUG_TRACE, "=> mdb_substring_candidates (%s)\n", sub->sa_desc->ad_cname.bv_val, 0, 0 ); MDB_IDL_ALL( ids ); rc = mdb_index_param( op->o_bd, sub->sa_desc, LDAP_FILTER_SUBSTRINGS, &dbi, &mask, &prefix ); if ( rc == LDAP_INAPPROPRIATE_MATCHING ) { Debug( LDAP_DEBUG_ANY, "<= mdb_substring_candidates: (%s) not indexed\n", sub->sa_desc->ad_cname.bv_val, 0, 0 ); return 0; } if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "<= mdb_substring_candidates: (%s) " "index_param failed (%d)\n", sub->sa_desc->ad_cname.bv_val, rc, 0 ); return 0; } mr = sub->sa_desc->ad_type->sat_substr; if( !mr ) { return 0; } if( !mr->smr_filter ) { return 0; } rc = (mr->smr_filter)( LDAP_FILTER_SUBSTRINGS, mask, sub->sa_desc->ad_type->sat_syntax, mr, &prefix, sub, &keys, op->o_tmpmemctx ); if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "<= mdb_substring_candidates: (%s) " "MR filter failed (%d)\n", sub->sa_desc->ad_cname.bv_val, rc, 0 ); return 0; } if( keys == NULL ) { Debug( LDAP_DEBUG_TRACE, "<= mdb_substring_candidates: (0x%04lx) no keys (%s)\n", mask, sub->sa_desc->ad_cname.bv_val, 0 ); return 0; } for ( i= 0; keys[i].bv_val != NULL; i++ ) { rc = mdb_key_read( op->o_bd, rtxn, dbi, &keys[i], tmp, NULL, 0 ); if( rc == MDB_NOTFOUND ) { MDB_IDL_ZERO( ids ); rc = 0; break; } else if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "<= mdb_substring_candidates: (%s) " "key read failed (%d)\n", sub->sa_desc->ad_cname.bv_val, rc, 0 ); break; } if( MDB_IDL_IS_ZERO( tmp ) ) { Debug( LDAP_DEBUG_TRACE, "<= mdb_substring_candidates: (%s) NULL\n", sub->sa_desc->ad_cname.bv_val, 0, 0 ); MDB_IDL_ZERO( ids ); break; } if ( i == 0 ) { MDB_IDL_CPY( ids, tmp ); } else { mdb_idl_intersection( ids, tmp ); } if( MDB_IDL_IS_ZERO( ids ) ) break; } ber_bvarray_free_x( keys, op->o_tmpmemctx ); Debug( LDAP_DEBUG_TRACE, "<= mdb_substring_candidates: %ld, first=%ld, last=%ld\n", (long) ids[0], (long) MDB_IDL_FIRST(ids), (long) MDB_IDL_LAST(ids) ); return( rc ); }
static int pam_sess(nssov_info *ni,TFILE *fp,Operation *op,int action) { struct berval dn, uid, svc, tty, rhost, ruser; int32_t tmpint32; char dnc[1024]; char svcc[256]; char uidc[32]; char ttyc[32]; char rhostc[256]; char ruserc[32]; slap_callback cb = {0}; SlapReply rs = {REP_RESULT}; char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE]; struct berval timestamp, bv[2], *nbv; time_t stamp; Modifications mod; READ_STRING(fp,uidc); uid.bv_val = uidc; uid.bv_len = tmpint32; READ_STRING(fp,dnc); dn.bv_val = dnc; dn.bv_len = tmpint32; READ_STRING(fp,svcc); svc.bv_val = svcc; svc.bv_len = tmpint32; READ_STRING(fp,ttyc); tty.bv_val = ttyc; tty.bv_len = tmpint32; READ_STRING(fp,rhostc); rhost.bv_val = rhostc; rhost.bv_len = tmpint32; READ_STRING(fp,ruserc); ruser.bv_val = ruserc; ruser.bv_len = tmpint32; READ_INT32(fp,stamp); Debug(LDAP_DEBUG_TRACE,"nssov_pam_sess_%c(%s)\n", action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', dn.bv_val,0); if (!dn.bv_len || !ni->ni_pam_sessions) return 0; { int i, found=0; for (i=0; !BER_BVISNULL(&ni->ni_pam_sessions[i]); i++) { if (ni->ni_pam_sessions[i].bv_len != svc.bv_len) continue; if (!strcasecmp(ni->ni_pam_sessions[i].bv_val, svc.bv_val)) { found = 1; break; } } if (!found) return 0; } slap_op_time( &op->o_time, &op->o_tincr ); timestamp.bv_len = sizeof(timebuf); timestamp.bv_val = timebuf; if (action == NSLCD_ACTION_PAM_SESS_O ) stamp = op->o_time; slap_timestamp( &stamp, ×tamp ); bv[0].bv_len = timestamp.bv_len + global_host_bv.bv_len + svc.bv_len + tty.bv_len + ruser.bv_len + rhost.bv_len + STRLENOF(" (@)"); bv[0].bv_val = op->o_tmpalloc( bv[0].bv_len+1, op->o_tmpmemctx ); sprintf(bv[0].bv_val, "%s %s %s %s (%s@%s)", timestamp.bv_val, global_host_bv.bv_val, svc.bv_val, tty.bv_val, ruser.bv_val, rhost.bv_val); mod.sml_numvals = 1; mod.sml_values = bv; BER_BVZERO(&bv[1]); attr_normalize( ad_loginStatus, bv, &nbv, op->o_tmpmemctx ); mod.sml_nvalues = nbv; mod.sml_desc = ad_loginStatus; mod.sml_op = action == NSLCD_ACTION_PAM_SESS_O ? LDAP_MOD_ADD : LDAP_MOD_DELETE; mod.sml_flags = SLAP_MOD_INTERNAL; mod.sml_next = NULL; cb.sc_response = slap_null_cb; op->o_callback = &cb; op->o_tag = LDAP_REQ_MODIFY; op->o_dn = op->o_bd->be_rootdn; op->o_ndn = op->o_bd->be_rootndn; op->orm_modlist = &mod; op->orm_no_opattrs = 1; op->o_req_dn = dn; op->o_req_ndn = dn; op->o_bd->be_modify( op, &rs ); if ( mod.sml_next ) { slap_mods_free( mod.sml_next, 1 ); } ber_bvarray_free_x( nbv, op->o_tmpmemctx ); WRITE_INT32(fp,NSLCD_VERSION); WRITE_INT32(fp,action); WRITE_INT32(fp,NSLCD_RESULT_BEGIN); WRITE_INT32(fp,op->o_time); return 0; }