]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/translucent.c
ITS#7178 fix uninit'd op->ors_deref
[openldap] / servers / slapd / overlays / translucent.c
index a5b4e6a80b5a12391619b4dbfa9993a74a2bb60e..4f38b92f226405dc47d4a1b23e75f9ce310daec8 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2004-2008 The OpenLDAP Foundation.
+ * Copyright 2004-2012 The OpenLDAP Foundation.
  * Portions Copyright 2005 Symas Corporation.
  * All rights reserved.
  *
@@ -95,14 +95,6 @@ static ConfigTable translucentcfg[] = {
        { NULL, NULL, 0, 0, 0, ARG_IGNORED }
 };
 
-static ConfigTable transdummy[] = {
-       { "", "", 0, 0, 0, ARG_IGNORED,
-               NULL, "( OLcfgGlAt:13 NAME 'olcDatabase' "
-                       "DESC 'The backend type for a database instance' "
-                       "SUP olcBackend SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL, NULL },
-       { NULL, NULL, 0, 0, 0, ARG_IGNORED }
-};
-
 static ConfigOCs translucentocs[] = {
        { "( OLcfgOvOc:14.1 "
          "NAME 'olcTranslucentConfig' "
@@ -115,7 +107,7 @@ static ConfigOCs translucentocs[] = {
        { "( OLcfgOvOc:14.2 "
          "NAME 'olcTranslucentDatabase' "
          "DESC 'Translucent target database configuration' "
-         "AUXILIARY )", Cft_Misc, transdummy, translucent_ldadd },
+         "AUXILIARY )", Cft_Misc, olcDatabaseDummy, translucent_ldadd },
        { NULL, 0, NULL }
 };
 /* for translucent_init() */
@@ -166,8 +158,9 @@ translucent_cfadd( Operation *op, SlapReply *rs, Entry *e, ConfigArgs *ca )
 
        /* FIXME: should not hardcode "olcDatabase" here */
        bv.bv_len = snprintf( ca->cr_msg, sizeof( ca->cr_msg ),
-               "olcDatabase=%s", ov->db.bd_info->bi_type );
-       if ( bv.bv_len < 0 || bv.bv_len >= sizeof( ca->cr_msg ) ) {
+               "olcDatabase=" SLAP_X_ORDERED_FMT "%s",
+               0, ov->db.bd_info->bi_type );
+       if ( bv.bv_len >= sizeof( ca->cr_msg ) ) {
                return -1;
        }
        bv.bv_val = ca->cr_msg;
@@ -213,6 +206,7 @@ translucent_cf_gen( ConfigArgs *c )
                        ch_free( (*an)[i].an_name.bv_val );
                        do {
                                (*an)[i] = (*an)[i+1];
+                               i++;
                        } while ( !BER_BVISNULL( &(*an)[i].an_name ));
                }
                return 0;
@@ -289,22 +283,6 @@ void glue_parent(Operation *op) {
        return;
 }
 
-/*
-** dup_bervarray()
-**     copy a BerVarray;
-*/
-
-BerVarray dup_bervarray(BerVarray b) {
-       int i, len;
-       BerVarray nb;
-       for(len = 0; b[len].bv_val; len++);
-       nb = ch_malloc((len+1) * sizeof(BerValue));
-       for(i = 0; i < len; i++) ber_dupbv(&nb[i], &b[i]);
-       nb[len].bv_val = NULL;
-       nb[len].bv_len = 0;
-       return(nb);
-}
-
 /*
 ** free_attr_chain()
 **     free only the Attribute*, not the contents;
@@ -440,6 +418,7 @@ static int translucent_modify(Operation *op, SlapReply *rs) {
 
        db = op->o_bd;
        op->o_bd = &ov->db;
+       ov->db.be_acl = op->o_bd->be_acl;
        rc = ov->db.bd_info->bi_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &re);
        if(rc != LDAP_SUCCESS || re == NULL ) {
                send_ldap_error((op), rs, LDAP_NO_SUCH_OBJECT,
@@ -607,7 +586,7 @@ static int translucent_compare(Operation *op, SlapReply *rs) {
        slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
        translucent_info *ov = on->on_bi.bi_private;
        AttributeAssertion *ava = op->orc_ava;
-       Entry *e;
+       Entry *e = NULL;
        BackendDB *db;
        int rc;
 
@@ -637,6 +616,7 @@ static int translucent_compare(Operation *op, SlapReply *rs) {
 */
        db = op->o_bd;
        op->o_bd = &ov->db;
+       ov->db.be_acl = op->o_bd->be_acl;
        rc = ov->db.bd_info->bi_op_compare(op, rs);
        op->o_bd = db;
 
@@ -649,7 +629,6 @@ static int translucent_pwmod(Operation *op, SlapReply *rs) {
 
        slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
        translucent_info *ov = on->on_bi.bi_private;
-       const struct berval bv_exop_pwmod = BER_BVC(LDAP_EXOP_MODIFY_PASSWD);
        Entry *e = NULL, *re = NULL;
        BackendDB *db;
        int rc = 0;
@@ -669,6 +648,7 @@ static int translucent_pwmod(Operation *op, SlapReply *rs) {
 */
        db = op->o_bd;
        op->o_bd = &ov->db;
+       ov->db.be_acl = op->o_bd->be_acl;
        rc = ov->db.bd_info->bi_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &re);
        if(rc != LDAP_SUCCESS || re == NULL ) {
                send_ldap_error((op), rs, LDAP_NO_SUCH_OBJECT,
@@ -743,8 +723,6 @@ static int translucent_pwmod(Operation *op, SlapReply *rs) {
 }
 
 static int translucent_exop(Operation *op, SlapReply *rs) {
-       SlapReply nrs = { REP_RESULT };
-
        slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
        translucent_info *ov = on->on_bi.bi_private;
        const struct berval bv_exop_pwmod = BER_BVC(LDAP_EXOP_MODIFY_PASSWD);
@@ -790,6 +768,8 @@ typedef struct trans_ctx {
        Filter *orig;
        Avlnode *list;
        int step;
+       int slimit;
+       AttributeName *attrs;
 } trans_ctx;
 
 static int translucent_search_cb(Operation *op, SlapReply *rs) {
@@ -814,6 +794,13 @@ static int translucent_search_cb(Operation *op, SlapReply *rs) {
        Debug(LDAP_DEBUG_TRACE, "==> translucent_search_cb: %s\n",
                rs->sr_entry->e_name.bv_val, 0, 0);
 
+       op->ors_slimit = tc->slimit + ( tc->slimit > 0 ? 1 : 0 );
+       if ( op->ors_attrs == slap_anlist_all_attributes ) {
+               op->ors_attrs = tc->attrs;
+               rs->sr_attrs = tc->attrs;
+               rs->sr_attr_flags = slap_attr_flags( rs->sr_attrs );
+       }
+
        on = tc->on;
        ov = on->on_bi.bi_private;
 
@@ -827,18 +814,16 @@ static int translucent_search_cb(Operation *op, SlapReply *rs) {
                if ( tc->step & USE_LIST ) {
                        re = tavl_delete( &tc->list, le, entry_dn_cmp );
                        if ( re ) {
-                               if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
-                                       rs->sr_flags ^= REP_ENTRY_MUSTRELEASE;
-                                       be_entry_release_r( op, rs->sr_entry );
-                               }
-                               if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) {
-                                       rs->sr_flags ^= REP_ENTRY_MUSTBEFREED;
-                                       entry_free( rs->sr_entry );
-                               }
+                               rs_flush_entry( op, rs, on );
                                rc = test_filter( op, re, tc->orig );
                                if ( rc == LDAP_COMPARE_TRUE ) {
                                        rs->sr_flags |= REP_ENTRY_MUSTBEFREED;
                                        rs->sr_entry = re;
+
+                                       if ( tc->slimit >= 0 && rs->sr_nentries >= tc->slimit ) {
+                                               return LDAP_SIZELIMIT_EXCEEDED;
+                                       }
+
                                        return SLAP_CB_CONTINUE;
                                } else {
                                        entry_free( re );
@@ -858,17 +843,11 @@ static int translucent_search_cb(Operation *op, SlapReply *rs) {
        } else {
        /* Else we have remote, get local */
                op->o_bd = tc->db;
+               le = NULL;
                rc = overlay_entry_get_ov(op, &rs->sr_entry->e_nname, NULL, NULL, 0, &le, on);
                if ( rc == LDAP_SUCCESS && le ) {
                        re = entry_dup( rs->sr_entry );
-                       if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
-                               rs->sr_flags ^= REP_ENTRY_MUSTRELEASE;
-                               be_entry_release_r( op, rs->sr_entry );
-                       }
-                       if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) {
-                               rs->sr_flags ^= REP_ENTRY_MUSTBEFREED;
-                               entry_free( rs->sr_entry );
-                       }
+                       rs_flush_entry( op, rs, on );
                } else {
                        le = NULL;
                }
@@ -888,12 +867,16 @@ static int translucent_search_cb(Operation *op, SlapReply *rs) {
                for(ax = le->e_attrs; ax; ax = ax->a_next) {
                        for(a = re->e_attrs; a; a = a->a_next) {
                                if(a->a_desc == ax->a_desc) {
+                                       test_f = 1;
                                        if(a->a_vals != a->a_nvals)
                                                ber_bvarray_free(a->a_nvals);
                                        ber_bvarray_free(a->a_vals);
-                                       a->a_vals = dup_bervarray(ax->a_vals);
-                                       a->a_nvals = (ax->a_vals == ax->a_nvals) ?
-                                               a->a_vals : dup_bervarray(ax->a_nvals);
+                                       ber_bvarray_dup_x( &a->a_vals, ax->a_vals, NULL );
+                                       if ( ax->a_vals == ax->a_nvals ) {
+                                               a->a_nvals = a->a_vals;
+                                       } else {
+                                               ber_bvarray_dup_x( &a->a_nvals, ax->a_nvals, NULL );
+                                       }
                                        break;
                                }
                        }
@@ -904,14 +887,7 @@ static int translucent_search_cb(Operation *op, SlapReply *rs) {
                }
                /* Dispose of local entry */
                if ( tc->step & LCL_SIDE ) {
-                       if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
-                               rs->sr_flags ^= REP_ENTRY_MUSTRELEASE;
-                               be_entry_release_r( op, rs->sr_entry );
-                       }
-                       if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) {
-                               rs->sr_flags ^= REP_ENTRY_MUSTBEFREED;
-                               entry_free( rs->sr_entry );
-                       }
+                       rs_flush_entry(op, rs, on);
                } else {
                        overlay_entry_release_ov(op, le, 0, on);
                }
@@ -968,6 +944,11 @@ static int translucent_search_cb(Operation *op, SlapReply *rs) {
        }
 
        op->o_bd = db;
+
+       if ( rc == SLAP_CB_CONTINUE && tc->slimit >= 0 && rs->sr_nentries >= tc->slimit ) {
+               return LDAP_SIZELIMIT_EXCEEDED;
+       }
+
        return rc;
 }
 
@@ -1104,16 +1085,22 @@ static int translucent_search(Operation *op, SlapReply *rs) {
        cb.sc_private = &tc;
        cb.sc_next = op->o_callback;
 
+       ov->db.be_acl = op->o_bd->be_acl;
        tc.db = op->o_bd;
        tc.on = on;
        tc.orig = op->ors_filter;
        tc.list = NULL;
        tc.step = 0;
+       tc.slimit = op->ors_slimit;
+       tc.attrs = NULL;
        fbv = op->ors_filterstr;
 
        op->o_callback = &cb;
 
        if ( fr || !fl ) {
+               tc.attrs = op->ors_attrs;
+               op->ors_slimit = SLAP_NO_LIMIT;
+               op->ors_attrs = slap_anlist_all_attributes;
                op->o_bd = &ov->db;
                tc.step |= RMT_SIDE;
                if ( fl ) {
@@ -1122,6 +1109,7 @@ static int translucent_search(Operation *op, SlapReply *rs) {
                        filter2bv_x( op, fr, &op->ors_filterstr );
                }
                rc = ov->db.bd_info->bi_op_search(op, rs);
+               op->ors_attrs = tc.attrs;
                op->o_bd = tc.db;
                if ( fl ) {
                        op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
@@ -1137,6 +1125,9 @@ static int translucent_search(Operation *op, SlapReply *rs) {
        op->ors_filterstr = fbv;
        op->ors_filter = tc.orig;
        op->o_callback = cb.sc_next;
+       rs->sr_attrs = op->ors_attrs;
+       rs->sr_attr_flags = slap_attr_flags( rs->sr_attrs );
+
        /* Send out anything remaining on the list and finish */
        if ( tc.step & USE_LIST ) {
                if ( tc.list ) {
@@ -1145,22 +1136,25 @@ static int translucent_search(Operation *op, SlapReply *rs) {
                        av = tavl_end( tc.list, TAVL_DIR_LEFT );
                        while ( av ) {
                                rs->sr_entry = av->avl_data;
-                               rc = test_filter( op, rs->sr_entry, op->ors_filter );
-                               if ( rc == LDAP_COMPARE_TRUE ) {
+                               if ( rc == LDAP_SUCCESS && LDAP_COMPARE_TRUE ==
+                                       test_filter( op, rs->sr_entry, op->ors_filter ))
+                               {
                                        rs->sr_flags = REP_ENTRY_MUSTBEFREED;
                                        rc = send_search_entry( op, rs );
-                                       if ( rc ) break;
                                } else {
                                        entry_free( rs->sr_entry );
                                }
                                av = tavl_next( av, TAVL_DIR_RIGHT );
                        }
                        tavl_free( tc.list, NULL );
+                       rs->sr_flags = 0;
                        rs->sr_entry = NULL;
                }
                send_ldap_result( op, rs );
        }
 
+       op->ors_slimit = tc.slimit;
+
        /* Free in reverse order */
        if ( fl )
                trans_filter_free( op, fl );
@@ -1201,6 +1195,7 @@ static int translucent_bind(Operation *op, SlapReply *rs) {
 
        db = op->o_bd;
        op->o_bd = &ov->db;
+       ov->db.be_acl = op->o_bd->be_acl;
        rc = ov->db.bd_info->bi_op_bind(op, rs);
        op->o_bd = db;
 
@@ -1276,7 +1271,6 @@ static int translucent_db_init(BackendDB *be, ConfigReply *cr) {
        on->on_bi.bi_private = ov;
        ov->db = *be;
        ov->db.be_private = NULL;
-       ov->db.be_pcl_mutexp = &ov->db.be_pcl_mutex;
        ov->defer_db_open = 1;
 
        if ( !backend_db_init( "ldap", &ov->db, -1, NULL )) {
@@ -1366,6 +1360,7 @@ translucent_db_destroy( BackendDB *be, ConfigReply *cr )
                        backend_stopdown_one( &ov->db );
                }
 
+               ldap_pvt_thread_mutex_destroy( &ov->db.be_pcl_mutex );
                ch_free(ov);
                on->on_bi.bi_private = NULL;
        }