+static int adremap_refsearch(
+ Operation *op,
+ SlapReply *rs
+)
+{
+ if (rs->sr_type == REP_SEARCH) {
+ slap_callback *sc = op->o_callback;
+ struct berval *dn = sc->sc_private;
+ ber_dupbv_x(dn, &rs->sr_entry->e_nname, op->o_tmpmemctx);
+ }
+ return LDAP_SUCCESS;
+}
+
+static int adremap_filter(
+ Operation *op,
+ adremap_info *ai
+)
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ Filter *f = op->ors_filter;
+ adremap_dnv *ad;
+
+ /* Do we need to munge the filter? First see if it's of
+ * the form (&(objectClass=<mapgrp>)...)
+ */
+ if (f->f_choice == LDAP_FILTER_AND && f->f_and &&
+ f->f_and->f_choice == LDAP_FILTER_EQUALITY &&
+ f->f_and->f_av_desc == slap_schema.si_ad_objectClass) {
+ struct berval bv = f->f_and->f_av_value;
+ for (ad = ai->ai_dnv; ad; ad = ad->ad_next) {
+ if (!ber_bvstrcasecmp( &bv, &ad->ad_mapgrp->soc_cname )) {
+ /* Now check to see if next element is (<newattr>=foo) */
+ Filter *fn = f->f_and->f_next;
+ if (fn && fn->f_choice == LDAP_FILTER_EQUALITY &&
+ fn->f_av_desc == ad->ad_newattr) {
+ Filter fr[3], *fnew;
+ AttributeAssertion aa[2];
+ Operation op2;
+ slap_callback cb = {0};
+ SlapReply rs = {REP_RESULT};
+ struct berval dn = BER_BVNULL;
+
+ /* It's a match, setup a search with filter
+ * (&(objectclass=<refgrp>)(<deref>=foo))
+ */
+ fr[0].f_choice = LDAP_FILTER_AND;
+ fr[0].f_and = &fr[1];
+
+ fr[1].f_choice = LDAP_FILTER_EQUALITY;
+ fr[1].f_ava = &aa[0];
+ fr[1].f_av_desc = slap_schema.si_ad_objectClass;
+ fr[1].f_av_value = ad->ad_refgrp->soc_cname;
+ fr[1].f_next = &fr[2];
+
+ fr[2].f_choice = LDAP_FILTER_EQUALITY;
+ fr[2].f_ava = &aa[1];
+ fr[2].f_av_desc = ad->ad_deref;
+ fr[2].f_av_value = fn->f_av_value;
+ fr[2].f_next = NULL;
+
+ /* Search with this filter to retrieve target DN */
+ op2 = *op;
+ op2.o_callback = &cb;
+ cb.sc_response = adremap_refsearch;
+ cb.sc_private = &dn;
+ op2.o_req_dn = ad->ad_refbase;
+ op2.o_req_ndn = ad->ad_refbase;
+ op2.ors_filter = fr;
+ filter2bv_x(op, fr, &op2.ors_filterstr);
+ op2.ors_deref = LDAP_DEREF_NEVER;
+ op2.ors_slimit = 1;
+ op2.ors_tlimit = SLAP_NO_LIMIT;
+ op2.ors_attrs = slap_anlist_no_attrs;
+ op2.ors_attrsonly = 1;
+ op2.o_bd->bd_info = (BackendInfo *)on->on_info;
+ op2.o_bd->be_search(&op2, &rs);
+ op2.o_bd->bd_info = (BackendInfo *)on;
+ op->o_tmpfree(op2.ors_filterstr.bv_val, op->o_tmpmemctx);
+
+ if (!dn.bv_len) /* no match was found */
+ return 0;
+
+ /* Build a new filter of form
+ * (&(objectclass=<group>)(<dnattr>=foo-DN)...)
+ */
+ f = op->o_tmpalloc(sizeof(Filter), op->o_tmpmemctx);
+ f->f_choice = LDAP_FILTER_AND;
+ fnew = f;
+
+ f->f_and = op->o_tmpalloc(sizeof(Filter), op->o_tmpmemctx);
+ f = f->f_and;
+ f->f_choice = LDAP_FILTER_EQUALITY;
+ f->f_ava = op->o_tmpalloc(sizeof(AttributeAssertion), op->o_tmpmemctx);
+ f->f_av_desc = slap_schema.si_ad_objectClass;
+ ber_dupbv_x(&f->f_av_value, &ad->ad_group->soc_cname, op->o_tmpmemctx);
+
+ f->f_next = op->o_tmpalloc(sizeof(Filter), op->o_tmpmemctx);
+ f = f->f_next;
+ f->f_choice = LDAP_FILTER_EQUALITY;
+ f->f_ava = op->o_tmpalloc(sizeof(AttributeAssertion), op->o_tmpmemctx);
+ f->f_av_desc = ad->ad_dnattr;
+ f->f_av_value = dn;
+ f->f_next = fn->f_next;
+
+ fn->f_next = NULL;
+ filter_free_x(op, op->ors_filter, 1);
+ op->o_tmpfree(op->ors_filterstr.bv_val, op->o_tmpmemctx);
+ op->ors_filter = fnew;
+ filter2bv_x(op, op->ors_filter, &op->ors_filterstr);
+ return 1;
+ }
+ }
+ }
+ }
+ return 0; /* didn't match anything */
+}
+