X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Foverlays%2Fderef.c;h=d3e29921f1b05e9580ce1cb55d23902e712f3f63;hb=3dadeb3efe31c72dacc2e0e11ee25c271dffe44d;hp=b6d0b0b637167c43df5284d4ff794060eaaf13e0;hpb=6bedf74c413578805aa47db913ea24d1a0806192;p=openldap diff --git a/servers/slapd/overlays/deref.c b/servers/slapd/overlays/deref.c index b6d0b0b637..d3e29921f1 100644 --- a/servers/slapd/overlays/deref.c +++ b/servers/slapd/overlays/deref.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2008 The OpenLDAP Foundation. + * Copyright 1998-2010 The OpenLDAP Foundation. * Portions Copyright 2008 Pierangelo Masarati. * All rights reserved. * @@ -80,11 +80,11 @@ * 2.1.2. Response * * { { memberOf, "cn=abartlet,cn=users,dc=abartlet,dc=net", - * { GUID, [ "0bc11d00-e431-40a0-8767-344a320142fa" ], - * SID, [ "S-1-2-3-2345" ] } }, + * { { GUID, [ "0bc11d00-e431-40a0-8767-344a320142fa" ] }, + * { SID, [ "S-1-2-3-2345" ] } } }, * { memberOf, "cn=ando,cn=users,dc=sys-net,dc=it", - * { GUID, [ "0bc11d00-e431-40a0-8767-344a320142fb" ], - * SID, [ "S-1-2-3-2346" ] } } } + * { { GUID, [ "0bc11d00-e431-40a0-8767-344a320142fb" ] }, + * { SID, [ "S-1-2-3-2346" ] } } } } * * 2.2. Example * @@ -95,8 +95,20 @@ * 2.2.2. Response * * { { member, "cn=ando,cn=users,dc=sys-net,dc=it", - * { cn, [ "ando", "Pierangelo Masarati" ], - * uid, [ "ando" ] } } } + * { { cn, [ "ando", "Pierangelo Masarati" ] }, + * { uid, [ "ando" ] } } }, + * { member, "dc=sys-net,dc=it" } } + * + * + * 3. Security considerations + * + * The control result must not disclose information the client's + * identity could not have accessed directly by performing the related + * search operations. The presence of a derefVal in the control + * response does not imply neither the existence of nor any access + * privilege to the corresponding entry. It is merely a consequence + * of the read access the client's identity has on the corresponding + * attribute's value. */ #define o_deref o_ctrlflag[deref_cid] @@ -180,7 +192,7 @@ deref_parseCtrl ( ds = (DerefSpec *)op->o_tmpcalloc( 1, sizeof(DerefSpec) + sizeof(AttributeDescription *)*(cnt + 1), op->o_tmpmemctx ); - ds->ds_attributes = (AttributeDescription **)&ds[1]; + ds->ds_attributes = (AttributeDescription **)&ds[ 1 ]; ds->ds_nattrs = cnt; rc = slap_bv2ad( &derefAttr, &ds->ds_derefAttr, &text ); @@ -250,6 +262,20 @@ justcleanup:; return rs->sr_err; } +static int +deref_cleanup( Operation *op, SlapReply *rs ) +{ + if ( rs->sr_type == REP_RESULT || rs->sr_err == SLAPD_ABANDON ) { + op->o_tmpfree( op->o_callback, op->o_tmpmemctx ); + op->o_callback = NULL; + + op->o_tmpfree( op->o_ctrlderef, op->o_tmpmemctx ); + op->o_ctrlderef = NULL; + } + + return SLAP_CB_CONTINUE; +} + static int deref_response( Operation *op, SlapReply *rs ) { @@ -261,21 +287,33 @@ deref_response( Operation *op, SlapReply *rs ) deref_cb_t *dc = (deref_cb_t *)op->o_callback->sc_private; DerefSpec *ds; DerefRes *dr, *drhead = NULL, **drp = &drhead; - BackendInfo *bi = op->o_bd->bd_info; struct berval bv = BER_BVNULL; int nDerefRes = 0, nDerefVals = 0, nAttrs = 0, nVals = 0; struct berval ctrlval; - LDAPControl *ctrl, **ctrlsp; + LDAPControl *ctrl, *ctrlsp[2]; + AccessControlState acl_state = ACL_STATE_INIT; + static char dummy = '\0'; + Entry *ebase; int i; - op->o_bd->bd_info = (BackendInfo *)dc->dc_on->on_info; + rc = overlay_entry_get_ov( op, &rs->sr_entry->e_nname, NULL, NULL, 0, &ebase, dc->dc_on ); + if ( rc != LDAP_SUCCESS || ebase == NULL ) { + return SLAP_CB_CONTINUE; + } + for ( ds = dc->dc_ds; ds; ds = ds->ds_next ) { - Attribute *a = attr_find( rs->sr_entry->e_attrs, ds->ds_derefAttr ); + Attribute *a = attr_find( ebase->e_attrs, ds->ds_derefAttr ); if ( a != NULL ) { DerefVal *dv; BerVarray *bva; + if ( !access_allowed( op, rs->sr_entry, a->a_desc, + NULL, ACL_READ, &acl_state ) ) + { + continue; + } + dr = op->o_tmpcalloc( 1, sizeof( DerefRes ) + ( sizeof( DerefVal ) + sizeof( BerVarray * ) * ds->ds_nattrs ) * ( a->a_numvals + 1 ), op->o_tmpmemctx ); @@ -293,8 +331,16 @@ deref_response( Operation *op, SlapReply *rs ) dv[ i ].dv_attrVals = bva; bva += ds->ds_nattrs; - dv[i].dv_derefSpecVal = a->a_vals[ i ]; - bv.bv_len += dv[i].dv_derefSpecVal.bv_len; + + if ( !access_allowed( op, rs->sr_entry, a->a_desc, + &a->a_nvals[ i ], ACL_READ, &acl_state ) ) + { + dv[ i ].dv_derefSpecVal.bv_val = &dummy; + continue; + } + + ber_dupbv_x( &dv[ i ].dv_derefSpecVal, &a->a_vals[ i ], op->o_tmpmemctx ); + bv.bv_len += dv[ i ].dv_derefSpecVal.bv_len; nVals++; nDerefVals++; @@ -302,19 +348,45 @@ deref_response( Operation *op, SlapReply *rs ) if ( rc == LDAP_SUCCESS && e != NULL ) { int j; - for ( j = 0; j < ds->ds_nattrs; j++ ) { - Attribute *aa = attr_find( e->e_attrs, ds->ds_attributes[ j ] ); - if ( aa != NULL ) { - int k; + if ( access_allowed( op, e, slap_schema.si_ad_entry, + NULL, ACL_READ, NULL ) ) + { + for ( j = 0; j < ds->ds_nattrs; j++ ) { + Attribute *aa; - dv[i].dv_attrVals[ j ] = aa->a_vals; + if ( !access_allowed( op, e, ds->ds_attributes[ j ], NULL, + ACL_READ, &acl_state ) ) + { + continue; + } - bv.bv_len += ds->ds_attributes[ j ]->ad_cname.bv_len; - for ( k = 0; !BER_BVISNULL( &aa->a_vals[ k ] ); k++ ) { - bv.bv_len += aa->a_vals[ k ].bv_len; - nVals++; + aa = attr_find( e->e_attrs, ds->ds_attributes[ j ] ); + if ( aa != NULL ) { + unsigned k, h, last = aa->a_numvals; + + ber_bvarray_dup_x( &dv[ i ].dv_attrVals[ j ], + aa->a_vals, op->o_tmpmemctx ); + + bv.bv_len += ds->ds_attributes[ j ]->ad_cname.bv_len; + + for ( k = 0, h = 0; k < aa->a_numvals; k++ ) { + if ( !access_allowed( op, e, + aa->a_desc, + &aa->a_nvals[ k ], + ACL_READ, &acl_state ) ) + { + op->o_tmpfree( dv[ i ].dv_attrVals[ j ][ h ].bv_val, + op->o_tmpmemctx ); + dv[ i ].dv_attrVals[ j ][ h ] = dv[ i ].dv_attrVals[ j ][ --last ]; + BER_BVZERO( &dv[ i ].dv_attrVals[ j ][ last ] ); + continue; + } + bv.bv_len += dv[ i ].dv_attrVals[ j ][ h ].bv_len; + nVals++; + h++; + } + nAttrs++; } - nAttrs++; } } @@ -326,7 +398,7 @@ deref_response( Operation *op, SlapReply *rs ) drp = &dr->dr_next; } } - op->o_bd->bd_info = bi; + overlay_entry_release_ov( op, ebase, 0, dc->dc_on ); if ( drhead == NULL ) { return SLAP_CB_CONTINUE; @@ -347,9 +419,14 @@ deref_response( Operation *op, SlapReply *rs ) for ( i = 0; !BER_BVISNULL( &dr->dr_vals[ i ].dv_derefSpecVal ); i++ ) { int j, first = 1; + if ( dr->dr_vals[ i ].dv_derefSpecVal.bv_val == &dummy ) { + continue; + } + rc = ber_printf( ber, "{OO" /*}*/, &dr->dr_spec.ds_derefAttr->ad_cname, &dr->dr_vals[ i ].dv_derefSpecVal ); + op->o_tmpfree( dr->dr_vals[ i ].dv_derefSpecVal.bv_val, op->o_tmpmemctx ); for ( j = 0; j < dr->dr_spec.ds_nattrs; j++ ) { if ( dr->dr_vals[ i ].dv_attrVals[ j ] != NULL ) { if ( first ) { @@ -360,6 +437,8 @@ deref_response( Operation *op, SlapReply *rs ) rc = ber_printf( ber, "{O[W]}", &dr->dr_spec.ds_attributes[ j ]->ad_cname, dr->dr_vals[ i ].dv_attrVals[ j ] ); + op->o_tmpfree( dr->dr_vals[ i ].dv_attrVals[ j ], + op->o_tmpmemctx ); } } if ( !first ) { @@ -387,31 +466,14 @@ deref_response( Operation *op, SlapReply *rs ) ctrl->ldctl_oid = LDAP_CONTROL_X_DEREF; ctrl->ldctl_iscritical = 0; ctrl->ldctl_value.bv_len = ctrlval.bv_len; - lutil_strncopy( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len ); + AC_MEMCPY( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len ); ctrl->ldctl_value.bv_val[ ctrl->ldctl_value.bv_len ] = '\0'; ber_free_buf( ber ); - i = 0; - if ( rs->sr_ctrls ) { - for ( ; rs->sr_ctrls[ i ] != NULL; i++ ) - /* count'em */ ; - } - i += 2; - ctrlsp = op->o_tmpcalloc( i, sizeof(LDAPControl *), op->o_tmpmemctx ); - i = 0; - if ( rs->sr_ctrls != NULL ) { - for ( ; rs->sr_ctrls[ i ] != NULL; i++ ) { - ctrlsp[ i ] = rs->sr_ctrls[ i ]; - } - } - ctrlsp[ i++ ] = ctrl; - ctrlsp[ i++ ] = NULL; - if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) { - op->o_tmpfree( rs->sr_ctrls, op->o_tmpmemctx ); - } - rs->sr_ctrls = ctrlsp; - rs->sr_flags |= REP_CTRLS_MUSTBEFREED; + ctrlsp[0] = ctrl; + ctrlsp[1] = NULL; + slap_add_ctrls( op, rs, ctrlsp ); rc = SLAP_CB_CONTINUE; @@ -422,23 +484,12 @@ cleanup:; op->o_tmpfree( drhead, op->o_tmpmemctx ); drhead = drnext; } - } - - return rc; -} -static int -deref_cleanup( Operation *op, SlapReply *rs ) -{ - if ( rs->sr_type == REP_RESULT || rs->sr_err == SLAPD_ABANDON ) { - op->o_tmpfree( op->o_callback, op->o_tmpmemctx ); - op->o_callback = NULL; - - op->o_tmpfree( op->o_ctrlderef, op->o_tmpmemctx ); - op->o_ctrlderef = NULL; + } else if ( rs->sr_type == REP_RESULT ) { + rc = deref_cleanup( op, rs ); } - return SLAP_CB_CONTINUE; + return rc; } static int @@ -476,7 +527,7 @@ deref_initialize(void) if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "deref_init: Failed to register control (%d)\n", - rc, 0, 0 ); + rc, 0, 0 ); return -1; }