static int collect_response( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; collect_info *ci = on->on_bi.bi_private; /* If we've been configured and the current response is * a search entry */ if ( ci && rs->sr_type == REP_SEARCH ) { int rc; op->o_bd->bd_info = (BackendInfo *)on->on_info; for (; ci; ci=ci->ci_next ) { int idx=0; /* Is this entry an ancestor of this collectinfo ? */ if (!dnIsSuffix(&rs->sr_entry->e_nname, &ci->ci_dn)) { /* collectinfo does not match */ continue; } /* Is this entry the same as the template DN ? */ if ( dn_match(&rs->sr_entry->e_nname, &ci->ci_dn)) { /* dont apply change to parent */ continue; } /* The current entry may live in a cache, so * don't modify it directly. Make a copy and * work with that instead. */ rs_entry2modifiable( op, rs, on ); /* Loop for each attribute in this collectinfo */ for(idx=0; idx<ci->ci_ad_num; idx++) { BerVarray vals = NULL; /* Extract the values of the desired attribute from * the ancestor entry */ rc = backend_attribute( op, NULL, &ci->ci_dn, ci->ci_ad[idx], &vals, ACL_READ ); /* If there are any values, merge them into the * current search result */ if ( vals ) { attr_merge( rs->sr_entry, ci->ci_ad[idx], vals, NULL ); ber_bvarray_free_x( vals, op->o_tmpmemctx ); } } } } /* Default is to just fall through to the normal processing */ return SLAP_CB_CONTINUE; }
static int usn_operational( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; usn_info_t *ui = (usn_info_t *)on->on_bi.bi_private; if ( rs->sr_entry && dn_match( &rs->sr_entry->e_nname, op->o_bd->be_nsuffix )) { if ( SLAP_OPATTRS( rs->sr_attr_flags ) || ad_inlist( ad_usnChanged, rs->sr_attrs )) { Attribute *a, **ap = NULL; char intbuf[64]; struct berval bv; int my_usn; for ( a=rs->sr_entry->e_attrs; a; a=a->a_next ) { if ( a->a_desc == ad_usnChanged ) break; } if ( !a ) { for ( ap = &rs->sr_operational_attrs; *ap; ap=&(*ap)->a_next ); a = attr_alloc( ad_usnChanged ); *ap = a; } if ( !ap ) { if ( rs_entry2modifiable( op,rs, on )) { a = attr_find( rs->sr_entry->e_attrs, ad_usnChanged ); } ber_bvarray_free( a->a_vals ); a->a_vals = NULL; a->a_numvals = 0; } ldap_pvt_thread_mutex_lock( &ui->ui_mutex ); my_usn = ui->ui_current; ldap_pvt_thread_mutex_unlock( &ui->ui_mutex ); bv.bv_len = snprintf( intbuf, sizeof(intbuf), "%d", my_usn ); bv.bv_val = intbuf; attr_valadd( a, &bv, NULL, 1 ); } } return SLAP_CB_CONTINUE; }
static int valsort_response( Operation *op, SlapReply *rs ) { slap_overinst *on; valsort_info *vi; Attribute *a; /* If this is not a search response, or it is a syncrepl response, * or the valsort control wants raw results, pass thru unmodified. */ if ( rs->sr_type != REP_SEARCH || ( _SCM(op->o_sync) > SLAP_CONTROL_IGNORED ) || ( op->o_ctrlflag[valsort_cid] & SLAP_CONTROL_DATA0)) return SLAP_CB_CONTINUE; on = (slap_overinst *) op->o_bd->bd_info; vi = on->on_bi.bi_private; /* And we must have something configured */ if ( !vi ) return SLAP_CB_CONTINUE; /* Find a rule whose baseDN matches this entry */ for (; vi; vi = vi->vi_next ) { int i, n; if ( !dnIsSuffix( &rs->sr_entry->e_nname, &vi->vi_dn )) continue; /* Find attr that this rule affects */ a = attr_find( rs->sr_entry->e_attrs, vi->vi_ad ); if ( !a ) continue; if ( rs_entry2modifiable( op, rs, on )) { a = attr_find( rs->sr_entry->e_attrs, vi->vi_ad ); } n = a->a_numvals; if ( vi->vi_sort & VALSORT_WEIGHTED ) { int j, gotnvals; long *index = op->o_tmpalloc( n * sizeof(long), op->o_tmpmemctx ); gotnvals = (a->a_vals != a->a_nvals ); for (i=0; i<n; i++) { char *ptr = ber_bvchr( &a->a_nvals[i], '{' ); char *end = NULL; if ( !ptr ) { Debug(LDAP_DEBUG_TRACE, "weights missing from attr %s " "in entry %s\n", vi->vi_ad->ad_cname.bv_val, rs->sr_entry->e_name.bv_val, 0 ); break; } index[i] = strtol( ptr+1, &end, 0 ); if ( *end != '}' ) { Debug(LDAP_DEBUG_TRACE, "weights misformatted " "in entry %s\n", rs->sr_entry->e_name.bv_val, 0, 0 ); break; } /* Strip out weights */ ptr = a->a_nvals[i].bv_val; end++; for (; *end;) *ptr++ = *end++; *ptr = '\0'; a->a_nvals[i].bv_len = ptr - a->a_nvals[i].bv_val; if ( a->a_vals != a->a_nvals ) { ptr = a->a_vals[i].bv_val; end = ber_bvchr( &a->a_vals[i], '}' ); assert( end != NULL ); end++; for (; *end;) *ptr++ = *end++; *ptr = '\0'; a->a_vals[i].bv_len = ptr - a->a_vals[i].bv_val; } } /* An attr was missing weights here, ignore it */ if ( i<n ) { op->o_tmpfree( index, op->o_tmpmemctx ); continue; } /* Insertion sort */ for ( i=1; i<n; i++) { long idx = index[i]; struct berval tmp = a->a_vals[i], ntmp; if ( gotnvals ) ntmp = a->a_nvals[i]; j = i; while (( j>0 ) && (index[j-1] > idx )) { index[j] = index[j-1]; a->a_vals[j] = a->a_vals[j-1]; if ( gotnvals ) a->a_nvals[j] = a->a_nvals[j-1]; j--; } index[j] = idx; a->a_vals[j] = tmp; if ( gotnvals ) a->a_nvals[j] = ntmp; } /* Check for secondary sort */ if ( vi->vi_sort ^ VALSORT_WEIGHTED ) { for ( i=0; i<n;) { for (j=i+1; j<n; j++) { if (index[i] != index[j]) break; } if( j-i > 1 ) do_sort( op, a, i, j-i, vi->vi_sort ); i = j; } } op->o_tmpfree( index, op->o_tmpmemctx ); } else { do_sort( op, a, 0, n, vi->vi_sort ); } } return SLAP_CB_CONTINUE; }
static int dupent_response_entry( Operation *op, SlapReply *rs ) { dupent_cb_t *dc = (dupent_cb_t *)op->o_callback->sc_private; int nattrs = 0; valnum_t *valnum = NULL; Attribute **app, *ap_list = NULL; int i, c; Entry *e = NULL; int rc; assert( rs->sr_type == REP_SEARCH ); for ( i = 0; i < dc->dc_ds->ds_nattrs; i++ ) { Attribute *ap; ap = attr_find( rs->sr_entry->e_attrs, dc->dc_ds->ds_an[ i ].an_desc ); if ( ap && ap->a_numvals > 1 ) { nattrs++; } } if ( dc->dc_ds->ds_flags & SLAP_USERATTRS_YES ) { Attribute *ap; for ( ap = rs->sr_entry->e_attrs; ap != NULL; ap = ap->a_next ) { if ( !is_at_operational( ap->a_desc->ad_type ) && ap->a_numvals > 1 ) { nattrs++; } } } if ( !nattrs ) { return SLAP_CB_CONTINUE; } rs_entry2modifiable( op, rs, dc->dc_on ); rs->sr_flags &= ~(REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED); e = rs->sr_entry; valnum = op->o_tmpcalloc( sizeof(valnum_t), nattrs, op->o_tmpmemctx ); for ( c = 0, i = 0; i < dc->dc_ds->ds_nattrs; i++ ) { for ( app = &e->e_attrs; *app != NULL; app = &(*app)->a_next ) { if ( (*app)->a_desc == dc->dc_ds->ds_an[ i ].an_desc ) { break; } } if ( *app != NULL && (*app)->a_numvals > 1 ) { assert( c < nattrs ); dupent_attr_prepare( dc->dc_ds, e, valnum, nattrs, c, app, &ap_list ); c++; } } if ( dc->dc_ds->ds_flags & SLAP_USERATTRS_YES ) { for ( app = &e->e_attrs; *app != NULL; app = &(*app)->a_next ) { if ( !is_at_operational( (*app)->a_desc->ad_type ) && (*app)->a_numvals > 1 ) { assert( c < nattrs ); dupent_attr_prepare( dc->dc_ds, e, valnum, nattrs, c, app, &ap_list ); c++; } } } for ( app = &e->e_attrs; *app != NULL; app = &(*app)->a_next ) /* goto tail */ ; *app = &valnum[0].a; /* NOTE: since send_search_entry() does not honor the * REP_CTRLS_MUSTBEFREED flag set by slap_add_ctrls(), * the control could be added here once for all (ITS#6629) */ dc->dc_skip = 1; rc = dupent_response_entry_1level( op, rs, e, valnum, nattrs, 0 ); dc->dc_skip = 0; *app = ap_list; entry_free( e ); op->o_tmpfree( valnum, op->o_tmpmemctx ); return rc; }
static int cloak_search_response_cb( Operation *op, SlapReply *rs ) { slap_callback *sc; cloak_info_t *ci; Entry *e = NULL; Entry *me = NULL; assert( op && op->o_callback && rs ); if ( rs->sr_type != REP_SEARCH || !rs->sr_entry ) { return ( SLAP_CB_CONTINUE ); } sc = op->o_callback; e = rs->sr_entry; /* * First perform a quick scan for an attribute to cloak */ for ( ci = (cloak_info_t *)sc->sc_private; ci; ci = ci->ci_next ) { Attribute *a; if ( ci->ci_oc != NULL && !is_entry_objectclass_or_sub( e, ci->ci_oc ) ) continue; for ( a = e->e_attrs; a; a = a->a_next ) if ( a->a_desc == ci->ci_ad ) break; if ( a != NULL ) break; } /* * Nothing found to cloak */ if ( ci == NULL ) return ( SLAP_CB_CONTINUE ); /* * We are now committed to cloak an attribute. */ rs_entry2modifiable( op, rs, (slap_overinst *) op->o_bd->bd_info ); me = rs->sr_entry; for ( ci = (cloak_info_t *)sc->sc_private; ci; ci = ci->ci_next ) { Attribute *a; Attribute *pa; for ( pa = NULL, a = me->e_attrs; a; pa = a, a = a->a_next ) { if ( a->a_desc != ci->ci_ad ) continue; Debug( LDAP_DEBUG_TRACE, "cloak_search_response_cb: cloak %s\n", a->a_desc->ad_cname.bv_val, 0, 0 ); if ( pa != NULL ) pa->a_next = a->a_next; else me->e_attrs = a->a_next; attr_clean( a ); } } return ( SLAP_CB_CONTINUE ); }