/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 1998-2008 The OpenLDAP Foundation.
+ * Copyright 1998-2009 The OpenLDAP Foundation.
* Portions Copyright 2008 Pierangelo Masarati.
* All rights reserved.
*
* DerefRes ::= SEQUENCE {
* derefAttr AttributeDescription,
* derefVal LDAPDN,
- * attrVals PartialAttributeList OPTIONAL }
+ * attrVals [0] PartialAttributeList OPTIONAL }
*
* If vals is empty, partialAttribute is omitted.
* If all vals in attrVals are empty, attrVals is omitted.
* 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
*
* 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]
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 );
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 )
{
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;
+ 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 );
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++;
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++;
}
}
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;
rc = ber_printf( ber, "{" /*}*/ );
for ( dr = drhead; dr != NULL; dr = dr->dr_next ) {
for ( i = 0; !BER_BVISNULL( &dr->dr_vals[ i ].dv_derefSpecVal ); i++ ) {
- int j;
+ int j, first = 1;
- rc = ber_printf( ber, "{OO{" /*}*/,
+ 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 ) {
+ rc = ber_printf( ber, "t{" /*}*/,
+ (LBER_CONSTRUCTED|LBER_CLASS_CONTEXT) );
+ first = 0;
+ }
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 );
}
}
- rc = ber_printf( ber, /*{*/ "}N}" );
+ if ( !first ) {
+ rc = ber_printf( ber, /*{{*/ "}N}" );
+ } else {
+ rc = ber_printf( ber, /*{*/ "}" );
+ }
}
}
rc = ber_printf( ber, /*{*/ "}" );
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 );
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
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY,
"deref_init: Failed to register control (%d)\n",
- rc, 0, 0 );
+ rc, 0, 0 );
return -1;
}