]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/deref.c
Merge branch 'mdb.master' of ssh://git-master.openldap.org/~git/git/openldap
[openldap] / servers / slapd / overlays / deref.c
index 96b210aa4f072b07b93bba9173f7718a3378fef9..8dbebf42a106211754964016e3459a83cd8c36f2 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2008 The OpenLDAP Foundation.
+ * Copyright 1998-2011 The OpenLDAP Foundation.
  * Portions Copyright 2008 Pierangelo Masarati.
  * All rights reserved.
  *
@@ -64,7 +64,7 @@
  *  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]
@@ -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 );
@@ -198,7 +210,7 @@ deref_parseCtrl (
                        }
                }
 
-               if ( ds->ds_derefAttr->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) {
+               if ( !( ds->ds_derefAttr->ad_type->sat_syntax->ssyn_flags & SLAP_SYNTAX_DN )) {
                        if ( ctrl->ldctl_iscritical ) {
                                rs->sr_text = "Dereference control: derefAttr syntax not distinguishedName";
                                rs->sr_err = LDAP_PROTOCOL_ERROR;
@@ -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;
@@ -342,51 +414,38 @@ deref_response( Operation *op, SlapReply *rs )
                ber_init2( ber, &bv, LBER_USE_DER );
                ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
 
-#if 0
                rc = ber_printf( ber, "{" /*}*/ );
                for ( dr = drhead; dr != NULL; dr = dr->dr_next ) {
-                       rc = ber_printf( ber, "{{O{" /*}}}*/,
-                               &dr->dr_spec.ds_derefAttr->ad_cname );
-                       for ( i = 0; i < dr->dr_spec.ds_nattrs; i++ ) {
-                               rc = ber_printf( ber, "O",
-                                       &dr->dr_spec.ds_attributes[ i ]->ad_cname );
-                       }
-                       rc = ber_printf( ber, /*{{*/ "}}{" /*}*/ );
                        for ( i = 0; !BER_BVISNULL( &dr->dr_vals[ i ].dv_derefSpecVal ); i++ ) {
-                               int j;
+                               int j, first = 1;
 
-                               rc = ber_printf( ber, "{O{" /*}}*/ ,
-                                       &dr->dr_vals[ i ].dv_derefSpecVal );
-                               for ( j = 0; j < dr->dr_spec.ds_nattrs; j++ ) {
-                                       if ( dr->dr_vals[ i ].dv_attrVals[ j ] != NULL ) {
-                                               rc = ber_printf( ber, "[W]", dr->dr_vals[ i ].dv_attrVals[ j ] );
-                                       } else {
-                                               rc = ber_printf( ber, "b", 0 );
-                                       }
+                               if ( dr->dr_vals[ i ].dv_derefSpecVal.bv_val == &dummy ) {
+                                       continue;
                                }
-                               rc = ber_printf( ber, /*{{*/ "}}" );
-                       }
-                       rc = ber_printf( ber, /*{{*/ "}}" );
-               }
-               rc = ber_printf( ber, /*{*/ "}" );
-#endif
-
-               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;
 
-                               rc = ber_printf( ber, "{OO{" /*}*/,
+                               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, /*{*/ "}" );
@@ -407,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;
 
@@ -442,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
@@ -486,7 +517,7 @@ deref_op_search( Operation *op, SlapReply *rs )
 }
 
 int
-deref_initialize()
+deref_initialize(void)
 {
        int rc;
 
@@ -496,8 +527,8 @@ deref_initialize()
        if ( rc != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_ANY,
                        "deref_init: Failed to register control (%d)\n",
-               rc, 0, 0 );
-               return rc;
+                       rc, 0, 0 );
+               return -1;
        }
 
        deref.on_bi.bi_type = "deref";