]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/slapi/slapi_overlay.c
Merge remote branch 'origin/mdb.master' into OPENLDAP_REL_ENG_2_4
[openldap] / servers / slapd / slapi / slapi_overlay.c
index 17de5516d9279538ed76c6f9c8d29e06c1c3553f..79796ffff296644108dfb3bc9912bd2531137492 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2001-2005 The OpenLDAP Foundation.
+ * Copyright 2001-2012 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 
 #include "slap.h"
 #include "slapi.h"
+#include "config.h"
 
 #ifdef LDAP_SLAPI
 
 static slap_overinst slapi;
+static int slapi_over_initialized = 0;
 
 static int slapi_over_response( Operation *op, SlapReply *rs );
 static int slapi_over_cleanup( Operation *op, SlapReply *rs );
 
 static Slapi_PBlock *
-slapi_over_pblock_new ( Operation *op )
+slapi_over_pblock_new( Operation *op, SlapReply *rs )
 {
        Slapi_PBlock            *pb;
 
        pb = slapi_pblock_new();
-       if ( pb == NULL ) {
-               return NULL;
-       }
-
-       pb->pop = op;
-       pb->pconn = op->o_conn;
-       pb->internal_op = 0;
+       pb->pb_op = op;
+       pb->pb_conn = op->o_conn;
+       pb->pb_rs = rs;
+       pb->pb_intop = 0;
 
-       PBLOCK_ASSERT_OP( pb, 0 );
+       PBLOCK_ASSERT_OP( pb, op->o_tag );
 
        return pb;
 }
 
 static int
-slapi_op_internal_p( Operation *op, slap_callback *cb )
+slapi_op_internal_p( Operation *op, SlapReply *rs, slap_callback *cb )
 {
        int                     internal_op = 0;
        Slapi_PBlock            *pb = NULL;
@@ -77,7 +76,7 @@ slapi_op_internal_p( Operation *op, slap_callback *cb )
 
        if ( cb != NULL ) {
                if ( pb == NULL ) {
-                       pb = slapi_over_pblock_new( op );
+                       pb = slapi_over_pblock_new( op, rs );
                }
 
                cb->sc_response = slapi_over_response;
@@ -99,12 +98,14 @@ slapi_over_compute_output(
 {
        Attribute               **a;
        AttributeDescription    *desc;
-       SlapReply               *rs = (SlapReply *)c->cac_private;
+       SlapReply               *rs;
 
        if ( c == NULL || attribute == NULL || entry == NULL ) {
                return 0;
        }
 
+       rs = (SlapReply *)c->cac_private;
+
        assert( rs->sr_entry == entry );
 
        desc = attribute->a_desc;
@@ -145,11 +146,11 @@ slapi_over_aux_operational( Operation *op, SlapReply *rs )
        computed_attr_context    ctx;
        AttributeName           *anp;
 
-       if ( slapi_op_internal_p( op, NULL ) ) {
+       if ( slapi_op_internal_p( op, rs, NULL ) ) {
                return SLAP_CB_CONTINUE;
        }
 
-       ctx.cac_pb = slapi_over_pblock_new( op );
+       ctx.cac_pb = slapi_over_pblock_new( op, rs );
        ctx.cac_op = op;
        ctx.cac_private = rs;
 
@@ -179,6 +180,29 @@ slapi_over_aux_operational( Operation *op, SlapReply *rs )
        return SLAP_CB_CONTINUE;
 }
 
+/*
+ * We need this function to call frontendDB (global) plugins before
+ * database plugins, if we are invoked by a slap_callback.
+ */
+static int
+slapi_over_call_plugins( Slapi_PBlock *pb, int type )
+{
+       int                     rc = 1; /* means no plugins called */
+       Operation               *op;
+
+       PBLOCK_ASSERT_OP( pb, 0 );
+       op = pb->pb_op;
+
+       if ( !be_match( op->o_bd, frontendDB ) ) {
+               rc = slapi_int_call_plugins( frontendDB, type, pb );
+       }
+       if ( rc >= 0 ) {
+               rc = slapi_int_call_plugins( op->o_bd, type, pb );
+       }
+
+       return rc;
+}
+
 static int
 slapi_over_search( Operation *op, SlapReply *rs, int type )
 {
@@ -188,9 +212,9 @@ slapi_over_search( Operation *op, SlapReply *rs, int type )
        assert( rs->sr_type == REP_SEARCH || rs->sr_type == REP_SEARCHREF );
 
        /* create a new pblock to not trample on result controls */
-       pb = slapi_over_pblock_new( op );
+       pb = slapi_over_pblock_new( op, rs );
 
-       rc = slapi_int_call_plugins( op->o_bd, type, pb );
+       rc = slapi_over_call_plugins( pb, type );
        if ( rc >= 0 ) /* 1 means no plugins called */
                rc = SLAP_CB_CONTINUE;
        else
@@ -209,9 +233,9 @@ slapi_over_result( Operation *op, SlapReply *rs, int type )
 {
        Slapi_PBlock            *pb = SLAPI_OPERATION_PBLOCK( op );
 
-       assert( rs->sr_type == REP_RESULT );
+       assert( rs->sr_type == REP_RESULT || rs->sr_type == REP_SASL || rs->sr_type == REP_EXTENDED );
 
-       slapi_int_call_plugins( op->o_bd, type, pb );
+       slapi_over_call_plugins( pb, type );
 
        return SLAP_CB_CONTINUE;
 }
@@ -257,7 +281,8 @@ slapi_op_bind_callback( Operation *op, SlapReply *rs, int prc )
                                op->o_log_prefix,
                                BER_BVISNULL( &op->o_conn->c_dn )
                                        ? "<empty>" : op->o_conn->c_dn.bv_val,
-                               op->orb_tmp_mech.bv_val, 0, 0 );
+                               BER_BVISNULL( &op->orb_mech )
+                                       ? "<empty>" : op->orb_mech.bv_val, 0, 0 );
 
                        return -1;
                }
@@ -279,7 +304,8 @@ slapi_op_search_callback( Operation *op, SlapReply *rs, int prc )
 
        rs->sr_err = LDAP_SUCCESS;
 
-       if ( slapi_int_call_plugins( op->o_bd, SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN, pb ) == 0 ) {
+       if ( pb->pb_intop == 0 && 
+            slapi_int_call_plugins( op->o_bd, SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN, pb ) == 0 ) {
                /*
                 * The plugin can set the SLAPI_SEARCH_FILTER.
                 * SLAPI_SEARCH_STRFILER is not normative.
@@ -301,29 +327,29 @@ struct slapi_op_info {
        {
                SLAPI_PLUGIN_PRE_BIND_FN,
                SLAPI_PLUGIN_POST_BIND_FN,
-               0,
-               0,
+               SLAPI_PLUGIN_INTERNAL_PRE_BIND_FN,
+               SLAPI_PLUGIN_INTERNAL_POST_BIND_FN,
                slapi_op_bind_callback
        },
        {
                SLAPI_PLUGIN_PRE_UNBIND_FN,
                SLAPI_PLUGIN_POST_UNBIND_FN,
-               0,
-               0,
+               SLAPI_PLUGIN_INTERNAL_PRE_UNBIND_FN,
+               SLAPI_PLUGIN_INTERNAL_POST_UNBIND_FN,
                NULL
        },
        {
                SLAPI_PLUGIN_PRE_SEARCH_FN,
                SLAPI_PLUGIN_POST_SEARCH_FN,
-               0,
-               0,
+               SLAPI_PLUGIN_INTERNAL_PRE_SEARCH_FN,
+               SLAPI_PLUGIN_INTERNAL_POST_SEARCH_FN,
                slapi_op_search_callback
        },
        {
                SLAPI_PLUGIN_PRE_COMPARE_FN,
                SLAPI_PLUGIN_POST_COMPARE_FN,
-               0,
-               0,
+               SLAPI_PLUGIN_INTERNAL_PRE_COMPARE_FN,
+               SLAPI_PLUGIN_INTERNAL_POST_COMPARE_FN,
                NULL
        },
        {
@@ -357,8 +383,8 @@ struct slapi_op_info {
        {
                SLAPI_PLUGIN_PRE_ABANDON_FN,
                SLAPI_PLUGIN_POST_ABANDON_FN,
-               0,
-               0,
+               SLAPI_PLUGIN_INTERNAL_PRE_ABANDON_FN,
+               SLAPI_PLUGIN_INTERNAL_POST_ABANDON_FN,
                NULL
        },
        {
@@ -383,7 +409,7 @@ slapi_tag2op( ber_tag_t tag )
                op = op_add;
                break;
        case LDAP_REQ_DELETE:
-               op = op_compare;
+               op = op_delete;
                break;
        case LDAP_REQ_MODRDN:
                op = op_modrdn;
@@ -442,6 +468,7 @@ slapi_over_merge_controls( Operation *op, SlapReply *rs )
                        ctrls[n_slapi_ctrls + i] = rs->sr_ctrls[i];
                }
        }
+       ctrls[n_slapi_ctrls + n_rs_ctrls] = NULL;
 
        rs->sr_ctrls = ctrls;
 
@@ -456,7 +483,7 @@ slapi_over_unmerge_controls( Operation *op, SlapReply *rs )
 
        slapi_pblock_get( pb, SLAPI_X_OLD_RESCONTROLS, (void **)&rs_ctrls );
 
-       if ( rs->sr_ctrls == NULL || rs->sr_ctrls == rs_ctrls ) {
+       if ( rs_ctrls == NULL || rs->sr_ctrls == rs_ctrls ) {
                /* no copying done */
                return LDAP_SUCCESS;
        }
@@ -473,9 +500,11 @@ slapi_over_response( Operation *op, SlapReply *rs )
        Slapi_PBlock            *pb = SLAPI_OPERATION_PBLOCK( op );
        int                     rc = SLAP_CB_CONTINUE;
 
-       if ( pb->internal_op == 0 ) {
+       if ( pb->pb_intop == 0 ) {
                switch ( rs->sr_type ) {
                case REP_RESULT:
+               case REP_SASL:
+               case REP_EXTENDED:
                        rc = slapi_over_result( op, rs, SLAPI_PLUGIN_PRE_RESULT_FN );
                        break;
                case REP_SEARCH:
@@ -502,9 +531,11 @@ slapi_over_cleanup( Operation *op, SlapReply *rs )
 
        slapi_over_unmerge_controls( op, rs );
 
-       if ( pb->internal_op == 0 ) {
+       if ( pb->pb_intop == 0 ) {
                switch ( rs->sr_type ) {
                case REP_RESULT:
+               case REP_SASL:
+               case REP_EXTENDED:
                        rc = slapi_over_result( op, rs, SLAPI_PLUGIN_POST_RESULT_FN );
                        break;
                case REP_SEARCH:
@@ -533,6 +564,7 @@ slapi_op_func( Operation *op, SlapReply *rs )
        slap_callback           cb;
        int                     internal_op;
        int                     preop_type, postop_type;
+       BackendDB               *be;
 
        if ( !slapi_plugins_used )
                return SLAP_CB_CONTINUE;
@@ -555,7 +587,7 @@ slapi_op_func( Operation *op, SlapReply *rs )
                return SLAP_CB_CONTINUE;
        }
 
-       internal_op = slapi_op_internal_p( op, &cb );
+       internal_op = slapi_op_internal_p( op, rs, &cb );
 
        if ( internal_op ) {
                preop_type = opinfo->soi_internal_preop;
@@ -567,13 +599,17 @@ slapi_op_func( Operation *op, SlapReply *rs )
 
        if ( preop_type == 0 ) {
                /* no SLAPI plugin types for this operation */
+               pb = NULL;
                rc = SLAP_CB_CONTINUE;
                goto cleanup;
        }
 
        pb = SLAPI_OPERATION_PBLOCK( op );
 
-       rc = slapi_int_call_plugins( op->o_bd, preop_type, pb );
+       /* cache backend so we call correct postop plugins */
+       be = pb->pb_op->o_bd;
+
+       rc = slapi_int_call_plugins( be, preop_type, pb );
 
        /*
         * soi_callback is responsible for examining the result code
@@ -613,7 +649,7 @@ slapi_op_func( Operation *op, SlapReply *rs )
        /*
         * Call postoperation plugins
         */
-       slapi_int_call_plugins( op->o_bd, postop_type, pb );
+       slapi_int_call_plugins( be, postop_type, pb );
 
 cleanup:
        if ( !internal_op ) {
@@ -640,7 +676,7 @@ slapi_over_extended( Operation *op, SlapReply *rs )
                return SLAP_CB_CONTINUE;
        }
 
-       internal_op = slapi_op_internal_p( op, &cb );
+       internal_op = slapi_op_internal_p( op, rs, &cb );
        if ( internal_op ) {
                return SLAP_CB_CONTINUE;
        }
@@ -649,11 +685,10 @@ slapi_over_extended( Operation *op, SlapReply *rs )
 
        rc = (*callback)( pb );
        if ( rc == SLAPI_PLUGIN_EXTENDED_SENT_RESULT ) {
-               slapi_pblock_destroy( pb );
-               return rc;
+               goto cleanup;
        } else if ( rc == SLAPI_PLUGIN_EXTENDED_NOT_HANDLED ) {
-               slapi_pblock_destroy( pb );
-               return SLAP_CB_CONTINUE;
+               rc = SLAP_CB_CONTINUE;
+               goto cleanup;
        }
 
        assert( rs->sr_rspoid != NULL );
@@ -667,9 +702,13 @@ slapi_over_extended( Operation *op, SlapReply *rs )
        if ( rs->sr_rspdata != NULL )
                ber_bvfree( rs->sr_rspdata );
 
+       rc = rs->sr_err;
+
+cleanup:
        slapi_pblock_destroy( pb );
+       op->o_callback = cb.sc_next;
 
-       return rs->sr_err;
+       return rc;
 }
 
 static int
@@ -686,8 +725,9 @@ slapi_over_access_allowed(
        Slapi_PBlock            *pb;
        slap_callback           cb;
        int                     internal_op;
+       SlapReply               rs = { REP_RESULT };
 
-       internal_op = slapi_op_internal_p( op, &cb );
+       internal_op = slapi_op_internal_p( op, &rs, &cb );
 
        cb.sc_response = NULL;
        cb.sc_cleanup = NULL;
@@ -699,10 +739,11 @@ slapi_over_access_allowed(
                rc = SLAP_CB_CONTINUE;
        }
 
-       op->o_callback = cb.sc_next;
-
-       if ( !internal_op )
+       if ( !internal_op ) {
                slapi_pblock_destroy( pb );
+       }
+
+       op->o_callback = cb.sc_next;
 
        return rc;
 }
@@ -721,8 +762,9 @@ slapi_over_acl_group(
        Slapi_PBlock            *pb;
        BackendDB               *be = op->o_bd;
        GroupAssertion          *g;
+       SlapReply               rs = { REP_RESULT };
 
-       op->o_bd = select_backend( gr_ndn, 0, 0 );
+       op->o_bd = select_backend( gr_ndn, 0 );
 
        for ( g = op->o_groups; g; g = g->ga_next ) {
                if ( g->ga_be != op->o_bd || g->ga_oc != group_oc ||
@@ -749,7 +791,7 @@ slapi_over_acl_group(
                int                     internal_op;
                slap_callback           cb;
 
-               internal_op = slapi_op_internal_p( op, &cb );
+               internal_op = slapi_op_internal_p( op, &rs, &cb );
 
                cb.sc_response = NULL;
                cb.sc_cleanup = NULL;
@@ -761,11 +803,16 @@ slapi_over_acl_group(
                slapi_pblock_set( pb, SLAPI_X_GROUP_ATTRIBUTE,    (void *)group_at->ad_cname.bv_val );
                slapi_pblock_set( pb, SLAPI_X_GROUP_TARGET_ENTRY, (void *)target );
 
-               rc = slapi_int_call_plugins( op->o_bd, SLAPI_X_PLUGIN_PRE_GROUP_FN, pb );
+               rc = slapi_over_call_plugins( pb, SLAPI_X_PLUGIN_PRE_GROUP_FN );
                if ( rc >= 0 ) /* 1 means no plugins called */
                        rc = SLAP_CB_CONTINUE;
                else
-                       rc = pb->rs.sr_err;
+                       rc = pb->pb_rs->sr_err;
+
+               slapi_pblock_delete_param( pb, SLAPI_X_GROUP_ENTRY );
+               slapi_pblock_delete_param( pb, SLAPI_X_GROUP_OPERATION_DN );
+               slapi_pblock_delete_param( pb, SLAPI_X_GROUP_ATTRIBUTE );
+               slapi_pblock_delete_param( pb, SLAPI_X_GROUP_TARGET_ENTRY );
 
                if ( !internal_op )
                        slapi_pblock_destroy( pb );
@@ -773,6 +820,8 @@ slapi_over_acl_group(
                if ( e != target ) {
                        be_entry_release_r( op, e );
                }
+
+               op->o_callback = cb.sc_next;
        } else {
                rc = LDAP_NO_SUCH_OBJECT; /* return SLAP_CB_CONTINUE for correctness? */
        }
@@ -799,8 +848,42 @@ done:
        return rc;
 }
 
-int
-slapi_int_overlay_init()
+static int
+slapi_over_db_open(
+       BackendDB       *be,
+       ConfigReply     *cr )
+{
+       Slapi_PBlock            *pb;
+       int                     rc;
+
+       pb = slapi_pblock_new();
+
+       rc = slapi_int_call_plugins( be, SLAPI_PLUGIN_START_FN, pb );
+
+       slapi_pblock_destroy( pb );
+
+       return rc;
+}
+
+static int
+slapi_over_db_close(
+       BackendDB       *be,
+       ConfigReply     *cr )
+{
+       Slapi_PBlock            *pb;
+       int                     rc;
+
+       pb = slapi_pblock_new();
+
+       rc = slapi_int_call_plugins( be, SLAPI_PLUGIN_CLOSE_FN, pb );
+
+       slapi_pblock_destroy( pb );
+
+       return rc;
+}
+
+static int
+slapi_over_init()
 {
        memset( &slapi, 0, sizeof(slapi) );
 
@@ -817,6 +900,9 @@ slapi_int_overlay_init()
        slapi.on_bi.bi_op_abandon       = slapi_op_func;
        slapi.on_bi.bi_op_cancel        = slapi_op_func;
 
+       slapi.on_bi.bi_db_open          = slapi_over_db_open;
+       slapi.on_bi.bi_db_close         = slapi_over_db_close;
+
        slapi.on_bi.bi_extended         = slapi_over_extended;
        slapi.on_bi.bi_access_allowed   = slapi_over_access_allowed;
        slapi.on_bi.bi_operational      = slapi_over_aux_operational;
@@ -825,4 +911,36 @@ slapi_int_overlay_init()
        return overlay_register( &slapi );
 }
 
+int slapi_over_is_inst( BackendDB *be )
+{
+       return overlay_is_inst( be, SLAPI_OVERLAY_NAME );
+}
+
+int slapi_over_config( BackendDB *be, ConfigReply *cr )
+{
+       if ( slapi_over_initialized == 0 ) {
+               int rc;
+
+               /* do global initializaiton */
+               ldap_pvt_thread_mutex_init( &slapi_hn_mutex );
+               ldap_pvt_thread_mutex_init( &slapi_time_mutex );
+               ldap_pvt_thread_mutex_init( &slapi_printmessage_mutex );
+
+               if ( slapi_log_file == NULL )
+                       slapi_log_file = slapi_ch_strdup( LDAP_RUNDIR LDAP_DIRSEP "errors" );
+
+               rc = slapi_int_init_object_extensions();
+               if ( rc != 0 )
+                       return rc;
+
+               rc = slapi_over_init();
+               if ( rc != 0 )
+                       return rc;
+
+               slapi_over_initialized = 1;
+       }
+
+       return overlay_config( be, SLAPI_OVERLAY_NAME, -1, NULL, cr );
+}
+
 #endif /* LDAP_SLAPI */