X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Foverlays%2Frefint.c;h=da9c7fdfe581930143c4220487a905cb128f662d;hb=59e9ff6243465640956b58ad1756a3ede53eca7c;hp=8aa501254a783bac0cb1953008f4a823f070b947;hpb=c2cb945c30c8f9597c54d41300c90bd404921a9c;p=openldap diff --git a/servers/slapd/overlays/refint.c b/servers/slapd/overlays/refint.c index 8aa501254a..da9c7fdfe5 100644 --- a/servers/slapd/overlays/refint.c +++ b/servers/slapd/overlays/refint.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2004-2014 The OpenLDAP Foundation. + * Copyright 2004-2018 The OpenLDAP Foundation. * Portions Copyright 2004 Symas Corporation. * All rights reserved. * @@ -74,6 +74,7 @@ typedef struct refint_q { BerValue oldndn; BerValue newdn; BerValue newndn; + int do_sub; } refint_q; typedef struct refint_data_s { @@ -86,9 +87,15 @@ typedef struct refint_data_s { struct re_s *qtask; refint_q *qhead; refint_q *qtail; + BackendDB *db; ldap_pvt_thread_mutex_t qmutex; } refint_data; +typedef struct refint_pre_s { + slap_overinst *on; + int do_sub; +} refint_pre; + #define RUNQ_INTERVAL 36000 /* a long time */ static MatchingRule *mr_dnSubtreeMatch; @@ -228,7 +235,7 @@ refint_cf_gen(ConfigArgs *c) } break; case SLAP_CONFIG_ADD: - /* fallthrough to LDAP_MOD_ADD */ + /* fallthru to LDAP_MOD_ADD */ case LDAP_MOD_ADD: switch ( c->type ) { case REFINT_ATTRS: @@ -357,6 +364,36 @@ refint_open( ber_dupbv( &id->refint_dn, &refint_dn ); ber_dupbv( &id->refint_ndn, &refint_ndn ); } + + /* + ** find the backend that matches our configured basedn; + ** make sure it exists and has search and modify methods; + ** + */ + + if ( on->on_info->oi_origdb != frontendDB ) { + BackendDB *db = select_backend(&id->dn, 1); + + if ( db ) { + BackendInfo *bi; + if ( db == be ) + bi = on->on_info->oi_orig; + else + bi = db->bd_info; + if ( !bi->bi_op_search || !bi->bi_op_modify ) { + Debug( LDAP_DEBUG_CONFIG, + "refint_response: backend missing search and/or modify\n", + 0, 0, 0 ); + return -1; + } + id->db = db; + } else { + Debug( LDAP_DEBUG_CONFIG, + "refint_response: no backend for our baseDN %s??\n", + id->dn.bv_val, 0, 0 ); + return -1; + } + } return(0); } @@ -433,6 +470,8 @@ refint_search_cb( na = NULL; + /* Are we doing subtree matching or simple equality? */ + if ( rq->do_sub ) { for(i = 0, b = a->a_nvals; b[i].bv_val; i++) { if(dnIsSuffix(&b[i], &rq->oldndn)) { is_exact = b[i].bv_len == rq->oldndn.bv_len; @@ -504,9 +543,24 @@ refint_search_cb( ber_bvarray_add_x( &na->new_nvals, &dn, op->o_tmpmemctx ); } } + } else { + /* entry has no children, just equality matching */ + is_exact = attr_valfind( a, + SLAP_MR_EQUALITY|SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH| + SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH, &rq->oldndn, &i, NULL ); + if ( is_exact == LDAP_SUCCESS ) { + na = op->o_tmpcalloc( 1, + sizeof( refint_attrs ), + op->o_tmpmemctx ); + na->next = ip->attrs; + ip->attrs = na; + na->attr = ia->attr; + na->ra_numvals = 1; + } + } /* Deleting/replacing all values and a nothing DN is configured? */ - if ( na && na->ra_numvals == i && !BER_BVISNULL(&dd->nothing) ) + if ( na && na->ra_numvals == a->a_numvals && !BER_BVISNULL(&dd->nothing) ) na->dont_empty = 1; Debug( LDAP_DEBUG_TRACE, "refint_search_cb: %s: %s (#%d)\n", @@ -729,11 +783,9 @@ refint_qtask( void *ctx, void *arg ) ftop.f_or = NULL; op->ors_filter = &ftop; for(ip = id->attrs; ip; ip = ip->next) { + /* this filter can be either EQUALITY or EXT */ fptr = op->o_tmpcalloc( sizeof(Filter) + sizeof(MatchingRuleAssertion), 1, op->o_tmpmemctx ); - /* Use (attr:dnSubtreeMatch:=value) to catch subtree rename - * and subtree delete where supported */ - fptr->f_choice = LDAP_FILTER_EXT; fptr->f_mra = (MatchingRuleAssertion *)(fptr+1); fptr->f_mr_rule = mr_dnSubtreeMatch; fptr->f_mr_rule_text = mr_dnSubtreeMatch->smr_bvoid; @@ -764,8 +816,15 @@ refint_qtask( void *ctx, void *arg ) if ( !rq ) break; - for (fptr = ftop.f_or; fptr; fptr = fptr->f_next ) + for (fptr = ftop.f_or; fptr; fptr = fptr->f_next ) { fptr->f_mr_value = rq->oldndn; + /* Use (attr:dnSubtreeMatch:=value) to catch subtree rename + * and subtree delete where supported */ + if (rq->do_sub) + fptr->f_choice = LDAP_FILTER_EXT; + else + fptr->f_choice = LDAP_FILTER_EQUALITY; + } filter2bv_x( op, op->ors_filter, &op->ors_filterstr ); @@ -875,60 +934,29 @@ refint_response( SlapReply *rs ) { - slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; - refint_data *id = on->on_bi.bi_private; + refint_pre *rp; + slap_overinst *on; + refint_data *id; BerValue pdn; - int ac; refint_q *rq; - BackendDB *db = NULL; refint_attrs *ip; + int ac; /* If the main op failed or is not a Delete or ModRdn, ignore it */ if (( op->o_tag != LDAP_REQ_DELETE && op->o_tag != LDAP_REQ_MODRDN ) || rs->sr_err != LDAP_SUCCESS ) return SLAP_CB_CONTINUE; - /* - ** validate (and count) the list of attrs; - ** - */ - - for(ip = id->attrs, ac = 0; ip; ip = ip->next, ac++); - if(!ac) { - Debug( LDAP_DEBUG_TRACE, - "refint_response called without any attributes\n", 0, 0, 0 ); - return SLAP_CB_CONTINUE; - } - - /* - ** find the backend that matches our configured basedn; - ** make sure it exists and has search and modify methods; - ** - */ - - if ( on->on_info->oi_origdb != frontendDB ) { - db = select_backend(&id->dn, 1); - - if ( db ) { - if ( !db->be_search || !db->be_modify ) { - Debug( LDAP_DEBUG_TRACE, - "refint_response: backend missing search and/or modify\n", - 0, 0, 0 ); - return SLAP_CB_CONTINUE; - } - } else { - Debug( LDAP_DEBUG_TRACE, - "refint_response: no backend for our baseDN %s??\n", - id->dn.bv_val, 0, 0 ); - return SLAP_CB_CONTINUE; - } - } + rp = op->o_callback->sc_private; + on = rp->on; + id = on->on_bi.bi_private; rq = ch_calloc( 1, sizeof( refint_q )); ber_dupbv( &rq->olddn, &op->o_req_dn ); ber_dupbv( &rq->oldndn, &op->o_req_ndn ); - rq->db = db; + rq->db = id->db; rq->rdata = id; + rq->do_sub = rp->do_sub; if ( op->o_tag == LDAP_REQ_MODRDN ) { if ( op->oq_modrdn.rs_newSup ) { @@ -977,6 +1005,47 @@ refint_response( return SLAP_CB_CONTINUE; } +/* Check if the target entry exists and has children. + * Do nothing if target doesn't exist. + */ +static int +refint_preop( + Operation *op, + SlapReply *rs +) +{ + slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; + refint_data *id = on->on_bi.bi_private; + Entry *e; + int rc; + + /* are any attrs configured? */ + if ( !id->attrs ) + return SLAP_CB_CONTINUE; + + rc = overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ); + if ( rc == LDAP_SUCCESS ) { + slap_callback *sc = op->o_tmpcalloc( 1, + sizeof(slap_callback)+sizeof(refint_pre), op->o_tmpmemctx ); + refint_pre *rp = (refint_pre *)(sc+1); + rp->on = on; + rp->do_sub = 1; /* assume there are children */ + if ( op->o_bd->be_has_subordinates ) { + int has = 0; + rc = op->o_bd->be_has_subordinates( op, e, &has ); + /* there definitely are not children */ + if ( rc == LDAP_SUCCESS && has == LDAP_COMPARE_FALSE ) + rp->do_sub = 0; + } + overlay_entry_release_ov( op, e, 0, on ); + sc->sc_response = refint_response; + sc->sc_private = rp; + sc->sc_next = op->o_callback; + op->o_callback = sc; + } + return SLAP_CB_CONTINUE; +} + /* ** init_module is last so the symbols resolve "for free" -- ** it expects to be called automagically during dynamic module initialization @@ -999,7 +1068,8 @@ int refint_initialize() { refint.on_bi.bi_db_destroy = refint_db_destroy; refint.on_bi.bi_db_open = refint_open; refint.on_bi.bi_db_close = refint_close; - refint.on_response = refint_response; + refint.on_bi.bi_op_delete = refint_preop; + refint.on_bi.bi_op_modrdn = refint_preop; refint.on_bi.bi_cf_ocs = refintocs; rc = config_register_schema ( refintcfg, refintocs );