From f0ebc1d8500d7576ebd38dfd25fe885d57df2dfa Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mareynol@redhat.com>
Date: Wed, 15 Feb 2012 16:33:06 -0500
Subject: [PATCH] Ticket #111 - ability to control behavior of modifyTimestamp/modifiersName

Bug Description:  Currently, the modifiersname/creatorsname is set to the plugin name,
                  if the plugin performed the add or modification.  There is no way to
                  track the original bind dn that trigger the update.

Fix Description:  Added a new config setting(nsslapd-plugin-binddn-tracking) that will
                  update a set of new operational attributes:

                      internalModifiersname & internalCreatorsname

                  These attributes will store the plugin dn that made the update, while
                  modifiersname/creatorsname will now be the bind dn that initiated the
                  operation.

https://fedorahosted.org/389/ticket/111
---
 ldap/schema/01core389.ldif                      |    2 +
 ldap/servers/plugins/automember/automember.c    |   16 ++--
 ldap/servers/plugins/dna/dna.c                  |  107 ++++++++++++-----------
 ldap/servers/plugins/linkedattrs/fixup_task.c   |   22 +++--
 ldap/servers/plugins/linkedattrs/linked_attrs.c |   36 ++++----
 ldap/servers/plugins/linkedattrs/linked_attrs.h |    1 +
 ldap/servers/plugins/memberof/memberof.c        |   51 +++++++----
 ldap/servers/plugins/mep/mep.c                  |   24 +++---
 ldap/servers/plugins/referint/referint.c        |   41 ++++++---
 ldap/servers/slapd/add.c                        |   41 ++++++++-
 ldap/servers/slapd/config.c                     |   17 ++++-
 ldap/servers/slapd/libglobs.c                   |   17 ++++
 ldap/servers/slapd/modify.c                     |   20 ++++-
 ldap/servers/slapd/modrdn.c                     |   12 ++-
 ldap/servers/slapd/opshared.c                   |   23 +++++-
 ldap/servers/slapd/pblock.c                     |   73 ++++++++++++++--
 ldap/servers/slapd/plugin_internal_op.c         |   17 +++-
 ldap/servers/slapd/proto-slap.h                 |    2 +
 ldap/servers/slapd/slap.h                       |    3 +
 ldap/servers/slapd/slapi-plugin.h               |   14 +++
 20 files changed, 381 insertions(+), 158 deletions(-)

diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif
index cf30ab0..a4d71e0 100644
--- a/ldap/schema/01core389.ldif
+++ b/ldap/schema/01core389.ldif
@@ -128,6 +128,8 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2091 NAME 'nsslapd-suffix' DESC 'Netscap
 attributeTypes: ( 2.16.840.1.113730.3.1.2092 NAME 'nsslapd-ldapiautodnsuffix' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'Netscape' )
 attributeTypes: ( 2.16.840.1.113730.3.1.2095 NAME 'connection' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' )
 attributeTypes: ( 2.16.840.1.113730.3.1.2096 NAME 'entryusn' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation X-ORIGIN 'Netscape' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2113 NAME 'internalModifiersName' DESC 'plugin dn' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12  SINGLE-VALUE NO-USER-MODIFICATION  USAGE directoryOperation  X-ORIGIN '389 Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2114 NAME 'internalCreatorsName' DESC 'plugin dn' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12  SINGLE-VALUE NO-USER-MODIFICATION  USAGE directoryOperation  X-ORIGIN '389 Directory Server' )
 attributeTypes: ( 2.16.840.1.113730.3.1.2111 NAME 'tombstoneNumSubordinates'
   DESC 'count of immediate subordinates for tombstone entries'
   EQUALITY integerMatch
diff --git a/ldap/servers/plugins/automember/automember.c b/ldap/servers/plugins/automember/automember.c
index 92d5ae6..06f27bd 100644
--- a/ldap/servers/plugins/automember/automember.c
+++ b/ldap/servers/plugins/automember/automember.c
@@ -103,8 +103,8 @@ static struct automemberRegexRule *automember_parse_regex_rule(char *rule_string
 static void automember_free_regex_rule(struct automemberRegexRule *rule);
 static int automember_parse_grouping_attr(char *value, char **grouping_attr,
     char **grouping_value);
-static void automember_update_membership(struct configEntry *config, Slapi_Entry *e, void *txn);
-static void automember_add_member_value(Slapi_Entry *member_e, const char *group_dn,
+static void automember_update_membership(Slapi_PBlock *pb, struct configEntry *config, Slapi_Entry *e, void *txn);
+static void automember_add_member_value(Slapi_PBlock *pb, Slapi_Entry *member_e, const char *group_dn,
     char *grouping_attr, char *grouping_value, void *txn);
 
 /*
@@ -1347,7 +1347,7 @@ automember_parse_grouping_attr(char *value, char **grouping_attr, char **groupin
  * the rules in config, then performs the updates.
  */
 static void
-automember_update_membership(struct configEntry *config, Slapi_Entry *e, void *txn)
+automember_update_membership(Slapi_PBlock *pb, struct configEntry *config, Slapi_Entry *e, void *txn)
 {
     PRCList *rule = NULL;
     struct automemberRegexRule *curr_rule = NULL;
@@ -1500,14 +1500,14 @@ automember_update_membership(struct configEntry *config, Slapi_Entry *e, void *t
     if (PR_CLIST_IS_EMPTY(&targets)) {
         /* Add to each default group. */
         for (i = 0; config->default_groups && config->default_groups[i]; i++) {
-            automember_add_member_value(e, config->default_groups[i],
+            automember_add_member_value(pb, e, config->default_groups[i],
                                         config->grouping_attr, config->grouping_value, txn);
         }
     } else {
         /* Update the target groups. */
         dnitem = (struct automemberDNListItem *)PR_LIST_HEAD(&targets);
         while ((PRCList *)dnitem != &targets) {
-            automember_add_member_value(e, slapi_sdn_get_dn(dnitem->dn),
+            automember_add_member_value(pb, e, slapi_sdn_get_dn(dnitem->dn),
                                         config->grouping_attr, config->grouping_value, txn);
             dnitem = (struct automemberDNListItem *)PR_NEXT_LINK((PRCList *)dnitem);
         }
@@ -1535,10 +1535,10 @@ automember_update_membership(struct configEntry *config, Slapi_Entry *e, void *t
  * Adds a member entry to a group.
  */
 static void
-automember_add_member_value(Slapi_Entry *member_e, const char *group_dn,
+automember_add_member_value(Slapi_PBlock *pb, Slapi_Entry *member_e, const char *group_dn,
                             char *grouping_attr, char *grouping_value, void *txn)
 {
-    Slapi_PBlock *mod_pb = slapi_pblock_new();
+    Slapi_PBlock *mod_pb = slapi_pblock_new_by_pb(pb);
     int result = LDAP_SUCCESS;
     LDAPMod mod;
     LDAPMod *mods[2];
@@ -1826,7 +1826,7 @@ automember_add_post_op(Slapi_PBlock *pb)
                 if (slapi_dn_issuffix(slapi_sdn_get_dn(sdn), config->scope) &&
                     (slapi_filter_test_simple(e, config->filter) == 0)) {
                     /* Find out what membership changes are needed and make them. */
-                    automember_update_membership(config, e, txn);
+                    automember_update_membership(pb, config, e, txn);
                 }
 
                 list = PR_NEXT_LINK(list);
diff --git a/ldap/servers/plugins/dna/dna.c b/ldap/servers/plugins/dna/dna.c
index a422055..fedfa50 100644
--- a/ldap/servers/plugins/dna/dna.c
+++ b/ldap/servers/plugins/dna/dna.c
@@ -216,7 +216,7 @@ static int dna_exop_init(Slapi_PBlock * pb);
  * Local operation functions
  *
  */
-static int dna_load_plugin_config();
+static int dna_load_plugin_config(Slapi_PBlock *pb);
 static int dna_parse_config_entry(Slapi_Entry * e, int apply);
 static void dna_delete_config();
 static void dna_free_config_entry(struct configEntry ** entry);
@@ -230,26 +230,26 @@ static int dna_load_host_port();
 static char *dna_get_dn(Slapi_PBlock * pb);
 static Slapi_DN *dna_get_sdn(Slapi_PBlock * pb);
 static int dna_dn_is_config(char *dn);
-static int dna_get_next_value(struct configEntry * config_entry,
+static int dna_get_next_value(Slapi_PBlock *pb, struct configEntry * config_entry,
                               char **next_value_ret, void *txn);
 static int dna_first_free_value(struct configEntry *config_entry,
                                 PRUint64 *newval, void *txn);
-static int dna_fix_maxval(struct configEntry *config_entry, void *txn);
-static void dna_notice_allocation(struct configEntry *config_entry,
+static int dna_fix_maxval(Slapi_PBlock *pb, struct configEntry *config_entry, void *txn);
+static void dna_notice_allocation(Slapi_PBlock *pb, struct configEntry *config_entry,
                                   PRUint64 new, PRUint64 last, int fix, void *txn);
-static int dna_update_shared_config(struct configEntry * config_entry, void *txn);
+static int dna_update_shared_config(Slapi_PBlock *pb, struct configEntry * config_entry, void *txn);
 static void dna_update_config_event(time_t event_time, void *arg);
 static int dna_get_shared_servers(struct configEntry *config_entry, PRCList **servers, void *txn);
 static void dna_free_shared_server(struct dnaServer **server);
 static void dna_delete_shared_servers(PRCList **servers);
-static int dna_release_range(char *range_dn, PRUint64 *lower, PRUint64 *upper);
+static int dna_release_range(Slapi_PBlock *pb, char *range_dn, PRUint64 *lower, PRUint64 *upper);
 static int dna_request_range(struct configEntry *config_entry,
                              struct dnaServer *server,
                              PRUint64 *lower, PRUint64 *upper);
 static struct berval *dna_create_range_request(char *range_dn);
-static int dna_update_next_range(struct configEntry *config_entry,
+static int dna_update_next_range(Slapi_PBlock *pb, struct configEntry *config_entry,
                                  PRUint64 lower, PRUint64 upper, void *txn);
-static int dna_activate_next_range(struct configEntry *config_entry, void *txn);
+static int dna_activate_next_range(Slapi_PBlock *pb, struct configEntry *config_entry, void *txn);
 static int dna_is_replica_bind_dn(char *range_dn, char *bind_dn);
 static int dna_get_replica_bind_creds(char *range_dn, struct dnaServer *server,
                                       char **bind_dn, char **bind_passwd,
@@ -589,7 +589,7 @@ dna_start(Slapi_PBlock * pb)
         slapi_ch_calloc(1, sizeof(struct configEntry));
     PR_INIT_CLIST(dna_global_config);
 
-    if (dna_load_plugin_config() != DNA_SUCCESS) {
+    if (dna_load_plugin_config(pb) != DNA_SUCCESS) {
         slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
                         "dna_start: unable to load plug-in configuration\n");
         return DNA_FAILURE;
@@ -657,7 +657,7 @@ done:
  * ------ cn=etc etc
  */
 static int
-dna_load_plugin_config()
+dna_load_plugin_config(Slapi_PBlock *pb)
 {
     int status = DNA_SUCCESS;
     int result;
@@ -665,13 +665,14 @@ dna_load_plugin_config()
     time_t now;
     Slapi_PBlock *search_pb;
     Slapi_Entry **entries = NULL;
+    char *dn = NULL;
 
     slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
                     "--> dna_load_plugin_config\n");
 
     dna_write_lock();
     dna_delete_config();
-
+    slapi_pblock_get(pb, SLAPI_REQUESTOR_DN, &dn);
     search_pb = slapi_pblock_new();
 
     slapi_search_internal_set_pb(search_pb, getPluginDN(),
@@ -704,8 +705,9 @@ dna_load_plugin_config()
      * performing the operation at this point when
      * starting up  would cause the change to not
      * get changelogged. */
+
     time(&now);
-    slapi_eq_once(dna_update_config_event, NULL, now + 30);
+    slapi_eq_once(dna_update_config_event, (void *)slapi_ch_strdup(dn), now + 30);
 
   cleanup:
     slapi_free_search_results_internal(search_pb);
@@ -1269,9 +1271,10 @@ dna_load_host_port()
 static void
 dna_update_config_event(time_t event_time, void *arg)
 {
-    Slapi_PBlock *pb = NULL;
+    Slapi_PBlock *pb;
     struct configEntry *config_entry = NULL;
     PRCList *list = NULL;
+    char *binddn = (char *)arg;
 
     /* Get read lock to prevent config changes */
     dna_read_lock();
@@ -1288,9 +1291,11 @@ dna_update_config_event(time_t event_time, void *arg)
 
         /* Create the pblock.  We'll reuse this for all
          * shared config updates. */
-        if ((pb = slapi_pblock_new()) == NULL)
+        if ((pb = slapi_pblock_new_by_pb(NULL)) == NULL)
             goto bail;
 
+        slapi_pblock_set(pb, SLAPI_REQUESTOR_DN, binddn);
+
         while (list != dna_global_config) {
             config_entry = (struct configEntry *) list;
 
@@ -1308,7 +1313,7 @@ dna_update_config_event(time_t event_time, void *arg)
                 slapi_delete_internal_pb(pb);
 
                 /* Now force the entry to be recreated */
-                dna_update_shared_config(config_entry, NULL);
+                dna_update_shared_config(pb, config_entry, NULL);
 
                 slapi_unlock_mutex(config_entry->lock);
                 slapi_pblock_init(pb);
@@ -1320,6 +1325,7 @@ dna_update_config_event(time_t event_time, void *arg)
 
 bail:
     dna_unlock();
+    slapi_ch_free((void **)&binddn);
     slapi_pblock_destroy(pb);
 }
 
@@ -1336,7 +1342,7 @@ bail:
  * The lock for configEntry should be obtained
  * before calling this function.
  */
-static int dna_fix_maxval(struct configEntry *config_entry, void *txn)
+static int dna_fix_maxval(Slapi_PBlock *pb, struct configEntry *config_entry, void *txn)
 {
     PRCList *servers = NULL;
     PRCList *server = NULL;
@@ -1351,7 +1357,7 @@ static int dna_fix_maxval(struct configEntry *config_entry, void *txn)
     /* If we already have a next range we only need
      * to activate it. */
     if (config_entry->next_range_lower != 0) {
-        ret = dna_activate_next_range(config_entry, txn);
+        ret = dna_activate_next_range(pb, config_entry, txn);
         if (ret != 0) {
             slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
                             "dna_fix_maxval: Unable to activate the "
@@ -1375,7 +1381,7 @@ static int dna_fix_maxval(struct configEntry *config_entry, void *txn)
                 } else {
                     /* Someone provided us with a new range. Attempt 
                      * to update the config. */
-                    if ((ret = dna_update_next_range(config_entry, lower, upper, txn)) == 0) {
+                    if ((ret = dna_update_next_range(pb, config_entry, lower, upper, txn)) == 0) {
                         break;
                     }
                 }
@@ -1406,7 +1412,7 @@ bail:
  * The lock for configEntry should be obtained before calling
  * this function. */
 static void
-dna_notice_allocation(struct configEntry *config_entry, PRUint64 new,
+dna_notice_allocation(Slapi_PBlock *pb, struct configEntry *config_entry, PRUint64 new,
                       PRUint64 last, int fix, void *txn)
 {
     /* update our cached config entry */
@@ -1421,7 +1427,7 @@ dna_notice_allocation(struct configEntry *config_entry, PRUint64 new,
          * new active range. */
         if (config_entry->next_range_lower != 0) {
             /* Make the next range active */
-            if (dna_activate_next_range(config_entry, txn) != 0) {
+            if (dna_activate_next_range(pb, config_entry, txn) != 0) {
                 slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
                                 "dna_notice_allocation: Unable to activate "
                                 "the next range for range %s.\n", config_entry->dn);
@@ -1429,7 +1435,7 @@ dna_notice_allocation(struct configEntry *config_entry, PRUint64 new,
         } else {
             config_entry->remaining = 0;
             /* update the shared configuration */
-            dna_update_shared_config(config_entry, txn);
+            dna_update_shared_config(pb, config_entry, txn);
         }
     } else {
         if (config_entry->next_range_lower != 0) {
@@ -1442,7 +1448,7 @@ dna_notice_allocation(struct configEntry *config_entry, PRUint64 new,
         }
 
         /* update the shared configuration */
-        dna_update_shared_config(config_entry, txn);
+        dna_update_shared_config(pb, config_entry, txn);
     }
 
     /* Check if we passed the threshold and try to fix maxval if so.  We
@@ -1454,7 +1460,7 @@ dna_notice_allocation(struct configEntry *config_entry, PRUint64 new,
                         config_entry->threshold, config_entry->dn, config_entry->remaining);
         /* Only attempt to fix maxval if the fix flag is set. */
         if (fix != 0) {
-            dna_fix_maxval(config_entry, txn);
+            dna_fix_maxval(pb, config_entry, txn);
         }
     }
 
@@ -2053,7 +2059,7 @@ cleanup:
  * Perform ldap operationally atomic increment
  * Return the next value to be assigned
  */
-static int dna_get_next_value(struct configEntry *config_entry,
+static int dna_get_next_value(Slapi_PBlock *origpb, struct configEntry *config_entry,
                               char **next_value_ret, void *txn)
 {
     Slapi_PBlock *pb = NULL;
@@ -2079,7 +2085,7 @@ static int dna_get_next_value(struct configEntry *config_entry,
         /* check if we overflowed the configured range */
         if (setval > config_entry->maxval) {
             /* try for a new range or fail */
-            ret = dna_fix_maxval(config_entry, txn);
+            ret = dna_fix_maxval(pb, config_entry, txn);
             if (LDAP_SUCCESS != ret) {
                 slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
                                 "dna_get_next_value: no more values available!!\n");
@@ -2115,7 +2121,7 @@ static int dna_get_next_value(struct configEntry *config_entry,
         mods[0] = &mod_replace;
         mods[1] = 0;
 
-        pb = slapi_pblock_new();
+        pb = slapi_pblock_new_by_pb(origpb);
         if (NULL == pb) {
             ret = LDAP_OPERATIONS_ERROR;
             goto done;
@@ -2139,7 +2145,7 @@ static int dna_get_next_value(struct configEntry *config_entry,
         }
 
         /* update our cached config */
-        dna_notice_allocation(config_entry, nextval, setval, 1, txn);
+        dna_notice_allocation(pb, config_entry, nextval, setval, 1, txn);
     }
 
   done:
@@ -2165,7 +2171,7 @@ static int dna_get_next_value(struct configEntry *config_entry,
  * before calling this function.
  * */
 static int
-dna_update_shared_config(struct configEntry * config_entry, void *txn)
+dna_update_shared_config(Slapi_PBlock *origpb, struct configEntry * config_entry, void *txn)
 {
     int ret = LDAP_SUCCESS;
 
@@ -2191,7 +2197,7 @@ dna_update_shared_config(struct configEntry * config_entry, void *txn)
         mods[0] = &mod_replace;
         mods[1] = 0;
 
-        pb = slapi_pblock_new();
+        pb = slapi_pblock_new_by_pb(origpb);
         if (NULL == pb) {
             ret = LDAP_OPERATIONS_ERROR;
         } else {
@@ -2240,7 +2246,6 @@ dna_update_shared_config(struct configEntry * config_entry, void *txn)
             }
 
             slapi_pblock_destroy(pb);
-            pb = NULL;
         }
     }
 
@@ -2257,7 +2262,7 @@ dna_update_shared_config(struct configEntry * config_entry, void *txn)
  * before calling this function.
  */
 static int
-dna_update_next_range(struct configEntry *config_entry,
+dna_update_next_range(Slapi_PBlock *origpb, struct configEntry *config_entry,
                       PRUint64 lower, PRUint64 upper, void *txn)
 {
     Slapi_PBlock *pb = NULL;
@@ -2281,7 +2286,7 @@ dna_update_next_range(struct configEntry *config_entry,
     mods[0] = &mod_replace;
     mods[1] = 0;
 
-    pb = slapi_pblock_new();
+    pb = slapi_pblock_new_by_pb(origpb);
     if (NULL == pb) {
         ret = LDAP_OPERATIONS_ERROR;
         goto bail;
@@ -2295,7 +2300,6 @@ dna_update_next_range(struct configEntry *config_entry,
     slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
 
     slapi_pblock_destroy(pb);
-    pb = NULL;
 
     if (ret != LDAP_SUCCESS) {
         slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
@@ -2305,7 +2309,7 @@ dna_update_next_range(struct configEntry *config_entry,
         /* update the cached config and the shared config */
         config_entry->next_range_lower = lower;
         config_entry->next_range_upper = upper;
-        dna_notice_allocation(config_entry, 0, 0, 0, txn);
+        dna_notice_allocation(pb, config_entry, 0, 0, 0, txn);
     }
 
 bail:
@@ -2322,9 +2326,9 @@ bail:
  * be obtained before calling this function.
  */
 static int
-dna_activate_next_range(struct configEntry *config_entry, void *txn)
+dna_activate_next_range(Slapi_PBlock *pb, struct configEntry *config_entry, void *txn)
 {
-    Slapi_PBlock *pb = NULL;
+    Slapi_PBlock *mod_pb = NULL;
     LDAPMod mod_maxval;
     LDAPMod mod_nextval;
     LDAPMod mod_nextrange;
@@ -2363,21 +2367,20 @@ dna_activate_next_range(struct configEntry *config_entry, void *txn)
     mods[3] = 0;
 
     /* Update the config entry first */
-    pb = slapi_pblock_new();
-    if (NULL == pb) {
+    mod_pb = slapi_pblock_new_by_pb(pb);
+    if (NULL == mod_pb) {
         ret = LDAP_OPERATIONS_ERROR;
         goto bail;
     }
 
-    slapi_modify_internal_set_pb(pb, config_entry->dn,
+    slapi_modify_internal_set_pb(mod_pb, config_entry->dn,
                                  mods, 0, 0, getPluginID(), 0);
-    slapi_pblock_set(pb, SLAPI_TXN, txn);
-    slapi_modify_internal_pb(pb);
+    slapi_pblock_set(mod_pb, SLAPI_TXN, txn);
+    slapi_modify_internal_pb(mod_pb);
 
-    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
+    slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
 
-    slapi_pblock_destroy(pb);
-    pb = NULL;
+    slapi_pblock_destroy(mod_pb);
 
     if (ret != LDAP_SUCCESS) {
         slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
@@ -2392,7 +2395,7 @@ dna_activate_next_range(struct configEntry *config_entry, void *txn)
         config_entry->remaining = ((config_entry->maxval - config_entry->nextval + 1) /
                                     config_entry->interval);
         /* update the shared configuration */
-        dna_update_shared_config(config_entry, txn);
+        dna_update_shared_config(pb, config_entry, txn);
     }
 
 bail:
@@ -3102,7 +3105,7 @@ static int dna_pre_op(Slapi_PBlock * pb, int modtype)
                 int len;
 
                 /* create the value to add */
-                ret = dna_get_next_value(config_entry, &value, txn);
+                ret = dna_get_next_value(pb, config_entry, &value, txn);
                 if (DNA_SUCCESS != ret) {
                     errstr = slapi_ch_smprintf("Allocation of a new value for range"
                                                " %s failed! Unable to proceed.",
@@ -3226,7 +3229,7 @@ static int dna_config_check_post_op(Slapi_PBlock * pb)
 
     if ((dn = dna_get_dn(pb))) {
         if (dna_dn_is_config(dn))
-            dna_load_plugin_config();
+            dna_load_plugin_config(pb);
     }
 
     slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
@@ -3299,7 +3302,7 @@ static int dna_extend_exop(Slapi_PBlock *pb)
 
     /* See if we have the req. range configured.
      * If so, we need to see if we have range to provide. */
-    ret = dna_release_range(shared_dn, &lower, &upper);
+    ret = dna_release_range(pb, shared_dn, &lower, &upper);
 
     if (ret == LDAP_SUCCESS) {
         /* We have range to give away, so construct
@@ -3371,7 +3374,7 @@ static int dna_extend_exop(Slapi_PBlock *pb)
  * for the range specified by range_dn.
  */
 static int
-dna_release_range(char *range_dn, PRUint64 *lower, PRUint64 *upper)
+dna_release_range(Slapi_PBlock *origpb, char *range_dn, PRUint64 *lower, PRUint64 *upper)
 {
     int ret = 0;
     int match = 0;
@@ -3474,7 +3477,7 @@ dna_release_range(char *range_dn, PRUint64 *lower, PRUint64 *upper)
                 *lower = *upper - release + 1;
 
                 /* Try to set the new next range in the config */
-                ret = dna_update_next_range(config_entry, config_entry->next_range_lower,
+                ret = dna_update_next_range(pb, config_entry, config_entry->next_range_lower,
                                             *lower - 1, NULL);
             } else {
                 /* We release up to half of our remaining values,
@@ -3504,7 +3507,7 @@ dna_release_range(char *range_dn, PRUint64 *lower, PRUint64 *upper)
                 mods[0] = &mod_replace;
                 mods[1] = 0;
 
-                pb = slapi_pblock_new();
+                pb = slapi_pblock_new_by_pb(origpb);
                 if (NULL == pb) {
                     ret = LDAP_OPERATIONS_ERROR;
                     goto bail;
@@ -3522,7 +3525,7 @@ dna_release_range(char *range_dn, PRUint64 *lower, PRUint64 *upper)
                 if (ret == LDAP_SUCCESS) {
                     /* Adjust maxval in our cached config and shared config */
                     config_entry->maxval = *lower - 1;
-                    dna_notice_allocation(config_entry, config_entry->nextval, 0, 0, NULL);
+                    dna_notice_allocation(pb, config_entry, config_entry->nextval, 0, 0, NULL);
                 }
             }
 
diff --git a/ldap/servers/plugins/linkedattrs/fixup_task.c b/ldap/servers/plugins/linkedattrs/fixup_task.c
index c1af2f2..4b82002 100644
--- a/ldap/servers/plugins/linkedattrs/fixup_task.c
+++ b/ldap/servers/plugins/linkedattrs/fixup_task.c
@@ -48,7 +48,7 @@
  */
 static void linked_attrs_fixup_task_destructor(Slapi_Task *task);
 static void linked_attrs_fixup_task_thread(void *arg);
-static void linked_attrs_fixup_links(struct configEntry *config, void *txn);
+static void linked_attrs_fixup_links(Slapi_PBlock *pb, struct configEntry *config, void *txn);
 static int linked_attrs_remove_backlinks_callback(Slapi_Entry *e, void *callback_data);
 static int linked_attrs_add_backlinks_callback(Slapi_Entry *e, void *callback_data);
 static const char *fetch_attr(Slapi_Entry *e, const char *attrname,
@@ -91,6 +91,7 @@ linked_attrs_fixup_task_add(Slapi_PBlock *pb, Slapi_Entry *e,
 	if (linkdn) {
 	    mytaskdata->linkdn = slapi_dn_normalize(slapi_ch_strdup(linkdn));
 	}
+	mytaskdata->pb = pb;
 
 	/* allocate new task now */
 	task = slapi_new_task(slapi_entry_get_ndn(e));
@@ -139,10 +140,12 @@ linked_attrs_fixup_task_thread(void *arg)
 	Slapi_Task *task = (Slapi_Task *)arg;
 	task_data *td = NULL;
 	PRCList *main_config = NULL;
+	Slapi_PBlock *pb;
 	int found_config = 0;
 
 	/* Fetch our task data from the task */
 	td = (task_data *)slapi_task_get_data(task);
+	pb = slapi_pblock_new_by_pb(td->pb);
 
 	/* Log started message. */
 	slapi_task_begin(task, 1);
@@ -170,7 +173,7 @@ linked_attrs_fixup_task_thread(void *arg)
                     slapi_log_error(SLAPI_LOG_FATAL, LINK_PLUGIN_SUBSYSTEM,
                          "Fixing up linked attribute pair (%s)\n", config_entry->dn);
 
-                    linked_attrs_fixup_links(config_entry, NULL);
+                    linked_attrs_fixup_links(pb, config_entry, NULL);
                     break;
                 }
             } else {
@@ -180,7 +183,7 @@ linked_attrs_fixup_task_thread(void *arg)
                 slapi_log_error(SLAPI_LOG_FATAL, LINK_PLUGIN_SUBSYSTEM,
                        "Fixing up linked attribute pair (%s)\n", config_entry->dn);
 
-                linked_attrs_fixup_links(config_entry, NULL);
+                linked_attrs_fixup_links(pb, config_entry, NULL);
             }
 
             list = PR_NEXT_LINK(list);
@@ -205,24 +208,27 @@ linked_attrs_fixup_task_thread(void *arg)
 
 	/* this will queue the destruction of the task */
 	slapi_task_finish(task, rc);
+	slapi_pblock_destroy(pb);
 }
 
 struct fixup_cb_data {
     char *attrtype;
     void *txn;
     struct configEntry *config;
+    Slapi_PBlock *pb;
 };
 
 static void 
-linked_attrs_fixup_links(struct configEntry *config, void *txn)
+linked_attrs_fixup_links(Slapi_PBlock *origpb, struct configEntry *config, void *txn)
 {
-    Slapi_PBlock *pb = slapi_pblock_new();
+    Slapi_PBlock *pb = slapi_pblock_new_by_pb(origpb);
     char *del_filter = NULL;
     char *add_filter = NULL;
-    struct fixup_cb_data cb_data = {NULL, NULL, NULL};
+    struct fixup_cb_data cb_data = {NULL, NULL, NULL, NULL};
 
     del_filter = slapi_ch_smprintf("%s=*", config->managedtype);
     add_filter = slapi_ch_smprintf("%s=*", config->linktype);
+    cb_data.pb = pb;
 
     /* Lock the attribute pair. */
     slapi_lock_mutex(config->lock);
@@ -309,7 +315,7 @@ linked_attrs_remove_backlinks_callback(Slapi_Entry *e, void *callback_data)
     Slapi_DN *sdn = slapi_entry_get_sdn(e);
     struct fixup_cb_data *cb_data = (struct fixup_cb_data *)callback_data;
     char *type = cb_data->attrtype;
-    Slapi_PBlock *pb = slapi_pblock_new();
+    Slapi_PBlock *pb = slapi_pblock_new_by_pb(cb_data->pb);
     char *val[1];
     LDAPMod mod;
     LDAPMod *mods[2];
@@ -346,7 +352,7 @@ linked_attrs_add_backlinks_callback(Slapi_Entry *e, void *callback_data)
     char *linkdn = slapi_entry_get_dn(e);
     struct fixup_cb_data *cb_data = (struct fixup_cb_data *)callback_data;
     struct configEntry *config = cb_data->config;
-    Slapi_PBlock *pb = slapi_pblock_new();
+    Slapi_PBlock *pb = slapi_pblock_new_by_pb(cb_data->pb);
     int i = 0;
     char **targets = NULL;
     char *val[2];
diff --git a/ldap/servers/plugins/linkedattrs/linked_attrs.c b/ldap/servers/plugins/linkedattrs/linked_attrs.c
index c00c896..63cae9f 100644
--- a/ldap/servers/plugins/linkedattrs/linked_attrs.c
+++ b/ldap/servers/plugins/linkedattrs/linked_attrs.c
@@ -106,13 +106,13 @@ static int linked_attrs_config_exists_reverse(struct configEntry *entry);
 static int linked_attrs_oktodo(Slapi_PBlock *pb);
 void linked_attrs_load_array(Slapi_Value **array, Slapi_Attr *attr);
 int linked_attrs_compare(const void *a, const void *b);
-static void linked_attrs_add_backpointers(char *linkdn, struct configEntry *config,
+static void linked_attrs_add_backpointers(Slapi_PBlock *pb, char *linkdn, struct configEntry *config,
     Slapi_Mod *smod, void *txn);
 static void linked_attrs_del_backpointers(Slapi_PBlock *pb, char *linkdn,
     struct configEntry *config, Slapi_Mod *smod);
 static void linked_attrs_replace_backpointers(Slapi_PBlock *pb, char *linkdn,
     struct configEntry *config, Slapi_Mod *smod);
-static void linked_attrs_mod_backpointers(char *linkdn, char *type, char *scope,
+static void linked_attrs_mod_backpointers(Slapi_PBlock *pb, char *linkdn, char *type, char *scope,
     int modop, Slapi_ValueSet *targetvals, void *txn);
 
 /*
@@ -557,7 +557,7 @@ linked_attrs_parse_config_entry(Slapi_Entry * e, int apply)
                             "linked_attrs_parse_config_entry: The %s config "
                             "setting must be set to an attribute with the "
                             "Distinguished Name syntax for linked attribute "
-                            "pair \"%s\".\n", LINK_LINK_TYPE, entry->dn);
+                            "pair \"%s\" attribute \"%s\".\n", LINK_LINK_TYPE, entry->dn, value);
         }
     } else {
         slapi_log_error(SLAPI_LOG_FATAL, LINK_PLUGIN_SUBSYSTEM,
@@ -1254,13 +1254,13 @@ linked_attrs_compare(const void *a, const void *b)
  * by the values in smod.
  */
 static void
-linked_attrs_add_backpointers(char *linkdn, struct configEntry *config,
+linked_attrs_add_backpointers(Slapi_PBlock *origpb, char *linkdn, struct configEntry *config,
     Slapi_Mod *smod, void *txn)
 {
     Slapi_ValueSet *vals = slapi_valueset_new();
 
     slapi_valueset_set_from_smod(vals, smod);
-    linked_attrs_mod_backpointers(linkdn, config->managedtype, config->scope,
+    linked_attrs_mod_backpointers(origpb, linkdn, config->managedtype, config->scope,
                                   LDAP_MOD_ADD, vals, txn);
 
     slapi_valueset_free(vals);
@@ -1295,7 +1295,7 @@ linked_attrs_del_backpointers(Slapi_PBlock *pb, char *linkdn,
     }
 
     slapi_pblock_get(pb, SLAPI_TXN, &txn);
-    linked_attrs_mod_backpointers(linkdn, config->managedtype, config->scope,
+    linked_attrs_mod_backpointers(pb,linkdn, config->managedtype, config->scope,
                                   LDAP_MOD_DELETE, vals, txn);
 
     slapi_valueset_free(vals);
@@ -1414,13 +1414,13 @@ linked_attrs_replace_backpointers(Slapi_PBlock *pb, char *linkdn,
 
         /* Perform the actual updates to the target entries. */
         if (delvals) {
-            linked_attrs_mod_backpointers(linkdn, config->managedtype,
+            linked_attrs_mod_backpointers(pb, linkdn, config->managedtype,
                                           config->scope, LDAP_MOD_DELETE, delvals, txn);
             slapi_valueset_free(delvals);
         }
 
         if (addvals) {
-            linked_attrs_mod_backpointers(linkdn, config->managedtype,
+            linked_attrs_mod_backpointers(pb, linkdn, config->managedtype,
                                           config->scope, LDAP_MOD_ADD, addvals, txn);
             slapi_valueset_free(addvals);
         }
@@ -1436,12 +1436,12 @@ linked_attrs_replace_backpointers(Slapi_PBlock *pb, char *linkdn,
  * Performs backpointer management.
  */
 static void
-linked_attrs_mod_backpointers(char *linkdn, char *type,
+linked_attrs_mod_backpointers(Slapi_PBlock *origpb, char *linkdn, char *type,
     char *scope, int modop, Slapi_ValueSet *targetvals, void *txn)
 {
     char *val[2];
     int i = 0;
-    Slapi_PBlock *mod_pb = slapi_pblock_new();
+    Slapi_PBlock *mod_pb = slapi_pblock_new_by_pb(origpb);
     LDAPMod mod;
     LDAPMod *mods[2];
     Slapi_Value *targetval = NULL;
@@ -1684,7 +1684,7 @@ linked_attrs_mod_post_op(Slapi_PBlock *pb)
                 case LDAP_MOD_ADD:
                     /* Find the entries pointed to by the new
                      * values and add the backpointers. */
-                    linked_attrs_add_backpointers(dn, config, smod, txn);
+                    linked_attrs_add_backpointers(pb, dn, config, smod, txn);
                     break;
                 case LDAP_MOD_DELETE:
                     /* Find the entries pointed to by the deleted
@@ -1779,7 +1779,7 @@ linked_attrs_add_post_op(Slapi_PBlock *pb)
 
                 slapi_lock_mutex(config->lock);
 
-                linked_attrs_mod_backpointers(dn, config->managedtype,
+                linked_attrs_mod_backpointers(pb, dn, config->managedtype,
                                               config->scope, LDAP_MOD_ADD, vals, txn);
 
                 slapi_unlock_mutex(config->lock);
@@ -1860,7 +1860,7 @@ linked_attrs_del_post_op(Slapi_PBlock *pb)
 
                 slapi_lock_mutex(config->lock);
 
-                linked_attrs_mod_backpointers(dn, config->managedtype,
+                linked_attrs_mod_backpointers(pb, dn, config->managedtype,
                                               config->scope, LDAP_MOD_DELETE, vals, txn);
 
                 slapi_unlock_mutex(config->lock);
@@ -1889,7 +1889,7 @@ linked_attrs_del_post_op(Slapi_PBlock *pb)
                         slapi_lock_mutex(config->lock);
 
                         /* Delete forward link value. */
-                        linked_attrs_mod_backpointers(dn, config->linktype,
+                        linked_attrs_mod_backpointers(pb, dn, config->linktype,
                                                       config->scope, LDAP_MOD_DELETE, vals, txn);
 
                         slapi_unlock_mutex(config->lock);
@@ -1990,7 +1990,7 @@ linked_attrs_modrdn_post_op(Slapi_PBlock *pb)
             slapi_lock_mutex(config->lock);
 
             /* Delete old dn value. */
-            linked_attrs_mod_backpointers(old_dn, config->managedtype,
+            linked_attrs_mod_backpointers(pb, old_dn, config->managedtype,
                                           config->scope, LDAP_MOD_DELETE, vals, txn);
 
             slapi_unlock_mutex(config->lock);
@@ -2013,7 +2013,7 @@ linked_attrs_modrdn_post_op(Slapi_PBlock *pb)
             slapi_lock_mutex(config->lock);
 
             /* Add new dn value. */
-            linked_attrs_mod_backpointers(new_dn, config->managedtype,
+            linked_attrs_mod_backpointers(pb, new_dn, config->managedtype,
                                           config->scope, LDAP_MOD_ADD, vals, txn);
 
             slapi_unlock_mutex(config->lock);
@@ -2042,11 +2042,11 @@ linked_attrs_modrdn_post_op(Slapi_PBlock *pb)
                     slapi_lock_mutex(config->lock);
 
                     /* Delete old dn value. */
-                    linked_attrs_mod_backpointers(old_dn, config->linktype,
+                    linked_attrs_mod_backpointers(pb, old_dn, config->linktype,
                                                   config->scope, LDAP_MOD_DELETE, vals, txn);
 
                     /* Add new dn value. */
-                    linked_attrs_mod_backpointers(new_dn, config->linktype,
+                    linked_attrs_mod_backpointers(pb, new_dn, config->linktype,
                                                   config->scope, LDAP_MOD_ADD, vals, txn);
 
                     slapi_unlock_mutex(config->lock);
diff --git a/ldap/servers/plugins/linkedattrs/linked_attrs.h b/ldap/servers/plugins/linkedattrs/linked_attrs.h
index 137e317..89318e1 100644
--- a/ldap/servers/plugins/linkedattrs/linked_attrs.h
+++ b/ldap/servers/plugins/linkedattrs/linked_attrs.h
@@ -100,6 +100,7 @@ struct configIndex {
 typedef struct _task_data
 {
     char *linkdn;
+    Slapi_PBlock *pb;
 } task_data;
 
 
diff --git a/ldap/servers/plugins/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c
index 5100b1a..6699e22 100644
--- a/ldap/servers/plugins/memberof/memberof.c
+++ b/ldap/servers/plugins/memberof/memberof.c
@@ -92,6 +92,7 @@ typedef struct _memberof_get_groups_data
         MemberOfConfig *config;
         Slapi_Value *memberdn_val;
         Slapi_ValueSet **groupvals;
+        Slapi_PBlock *pb;
         void *txn;
 } memberof_get_groups_data;
 
@@ -148,7 +149,7 @@ static int memberof_call_foreach_dn(Slapi_PBlock *pb, char *dn,
 static int memberof_is_direct_member(MemberOfConfig *config, Slapi_Value *groupdn,
 	Slapi_Value *memberdn, void *txn);
 static int memberof_is_grouping_attr(char *type, MemberOfConfig *config);
-static Slapi_ValueSet *memberof_get_groups(MemberOfConfig *config, char *memberdn, void *txn);
+static Slapi_ValueSet *memberof_get_groups(Slapi_PBlock *pb, MemberOfConfig *config, char *memberdn, void *txn);
 static int memberof_get_groups_r(MemberOfConfig *config, char *memberdn,
 	memberof_get_groups_data *data, void *txn);
 static int memberof_get_groups_callback(Slapi_Entry *e, void *callback_data);
@@ -169,7 +170,7 @@ static void memberof_task_destructor(Slapi_Task *task);
 static const char *fetch_attr(Slapi_Entry *e, const char *attrname,
                                               const char *default_val);
 static void memberof_fixup_task_thread(void *arg);
-static int memberof_fix_memberof(MemberOfConfig *config, char *dn, char *filter_str, void *txn);
+static int memberof_fix_memberof(Slapi_PBlock *pb, MemberOfConfig *config, char *dn, char *filter_str, void *txn);
 static int memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data);
 
 
@@ -448,6 +449,7 @@ int memberof_postop_del(Slapi_PBlock *pb)
 
 typedef struct _memberof_del_dn_data
 {
+	Slapi_PBlock *pb;
 	char *dn;
 	char *type;
 	void *txn;
@@ -465,7 +467,7 @@ memberof_del_dn_from_groups(Slapi_PBlock *pb, MemberOfConfig *config, char *dn,
 	 * same grouping attribute. */
 	for (i = 0; config->groupattrs[i]; i++)
 	{
-		memberof_del_dn_data data = {dn, config->groupattrs[i], txn};
+		memberof_del_dn_data data = {pb, dn, config->groupattrs[i], txn};
 
 		groupattrs[0] = config->groupattrs[i];
 
@@ -482,7 +484,7 @@ int memberof_del_dn_type_callback(Slapi_Entry *e, void *callback_data)
 	char *val[2];
 	Slapi_PBlock *mod_pb = 0;
 
-	mod_pb = slapi_pblock_new();
+	mod_pb = slapi_pblock_new_by_pb(((memberof_del_dn_data *)callback_data)->pb);
 
 	mods[0] = &mod;
 	mods[1] = 0;
@@ -521,7 +523,7 @@ int memberof_call_foreach_dn(Slapi_PBlock *pb, char *dn,
 	char **types, plugin_search_entry_callback callback, void *callback_data, void *txn)
 {
 	int rc = 0;
-	Slapi_PBlock *search_pb = slapi_pblock_new();
+	Slapi_PBlock *search_pb = slapi_pblock_new_by_pb(pb);
 	Slapi_Backend *be = 0;
 	Slapi_DN *sdn = 0;
 	Slapi_DN *base_sdn = 0;
@@ -693,6 +695,7 @@ int memberof_postop_modrdn(Slapi_PBlock *pb)
 
 typedef struct _replace_dn_data
 {
+	Slapi_PBlock *pb;
 	char *pre_dn;
 	char *post_dn;
 	char *type;
@@ -714,7 +717,7 @@ memberof_replace_dn_from_groups(Slapi_PBlock *pb, MemberOfConfig *config,
 	 * using the same grouping attribute. */
 	for (i = 0; config->groupattrs[i]; i++)
 	{
-		replace_dn_data data = {pre_dn, post_dn, config->groupattrs[i], txn};
+		replace_dn_data data = {pb, pre_dn, post_dn, config->groupattrs[i], txn};
 
 		groupattrs[0] = config->groupattrs[i];
 
@@ -734,7 +737,7 @@ int memberof_replace_dn_type_callback(Slapi_Entry *e, void *callback_data)
 	char *addval[2];
 	Slapi_PBlock *mod_pb = 0;
 
-	mod_pb = slapi_pblock_new();
+	mod_pb = slapi_pblock_new_by_pb(((replace_dn_data *)callback_data)->pb);
 
 	mods[0] = &delmod;
 	mods[1] = &addmod;
@@ -1091,6 +1094,7 @@ int memberof_modop_one_r(Slapi_PBlock *pb, MemberOfConfig *config, int mod_op,
 }
 
 struct fix_memberof_callback_data {
+	Slapi_PBlock *pb;
 	MemberOfConfig *config;
 	void *txn;
 };
@@ -1309,11 +1313,11 @@ int memberof_modop_one_replace_r(Slapi_PBlock *pb, MemberOfConfig *config,
 		if(LDAP_MOD_DELETE == mod_op || LDAP_MOD_ADD == mod_op)
 		{
 			/* find parent groups and replace our member attr */
-			struct fix_memberof_callback_data cb_data = {config, txn};
+			struct fix_memberof_callback_data cb_data = {pb, config, txn};
 			memberof_fix_memberof_callback(e, &cb_data);
 		} else {
 			/* single entry - do mod */
-			mod_pb = slapi_pblock_new();
+			mod_pb = slapi_pblock_new_by_pb(pb);
 
 			mods[0] = &mod;
 			if(LDAP_MOD_REPLACE == mod_op)
@@ -1641,11 +1645,11 @@ int memberof_moddn_attr_list(Slapi_PBlock *pb, MemberOfConfig *config,
  * A Slapi_ValueSet* is returned.  It is up to the caller to
  * free it.
  */
-Slapi_ValueSet *memberof_get_groups(MemberOfConfig *config, char *memberdn, void *txn)
+Slapi_ValueSet *memberof_get_groups(Slapi_PBlock *pb, MemberOfConfig *config, char *memberdn, void *txn)
 {
 	Slapi_Value *memberdn_val = slapi_value_new_string(memberdn);
 	Slapi_ValueSet *groupvals = slapi_valueset_new();
-	memberof_get_groups_data data = {config, memberdn_val, &groupvals, txn};
+	memberof_get_groups_data data = {config, memberdn_val, &groupvals, pb, txn};
 
 	memberof_get_groups_r(config, memberdn, &data, txn);
 
@@ -1658,7 +1662,7 @@ int memberof_get_groups_r(MemberOfConfig *config, char *memberdn, memberof_get_g
 {
 	/* Search for any grouping attributes that point to memberdn.
 	 * For each match, add it to the list, recurse and do same search */
-	return memberof_call_foreach_dn(NULL, memberdn, config->groupattrs,
+	return memberof_call_foreach_dn(data->pb, memberdn, config->groupattrs,
 		memberof_get_groups_callback, data, txn);
 }
 
@@ -2224,6 +2228,7 @@ typedef struct _task_data
 {
 	char *dn;
 	char *filter_str;
+	char *binddn;
 } task_data;
 
 void memberof_fixup_task_thread(void *arg)
@@ -2231,11 +2236,14 @@ void memberof_fixup_task_thread(void *arg)
 	MemberOfConfig configCopy = {0, 0, 0, 0};
 	Slapi_Task *task = (Slapi_Task *)arg;
 	task_data *td = NULL;
+	Slapi_PBlock *pb = slapi_pblock_new_by_pb(NULL);
 	int rc = 0;
 
 	/* Fetch our task data from the task */
 	td = (task_data *)slapi_task_get_data(task);
 
+	/* construct our pblock for plugin bind tracking */
+	slapi_pblock_set(pb, SLAPI_REQUESTOR_DN, td->binddn);
 	slapi_task_begin(task, 1);
 	slapi_task_log_notice(task, "Memberof task starts (arg: %s) ...\n", 
 								td->filter_str);
@@ -2252,7 +2260,7 @@ void memberof_fixup_task_thread(void *arg)
 	memberof_lock();
 
 	/* do real work */
-	rc = memberof_fix_memberof(&configCopy, td->dn, td->filter_str, NULL /* no txn? */);
+	rc = memberof_fix_memberof(pb, &configCopy, td->dn, td->filter_str, NULL /* no txn? */);
  
 	/* release the memberOf operation lock */
 	memberof_unlock();
@@ -2262,6 +2270,7 @@ void memberof_fixup_task_thread(void *arg)
 	slapi_task_log_notice(task, "Memberof task finished.");
 	slapi_task_log_status(task, "Memberof task finished.");
 	slapi_task_inc_progress(task);
+	slapi_pblock_destroy(pb);
 
 	/* this will queue the destruction of the task */
 	slapi_task_finish(task, rc);
@@ -2330,6 +2339,9 @@ int memberof_task_add(Slapi_PBlock *pb, Slapi_Entry *e,
 	mytaskdata->dn = slapi_ch_strdup(dn);
 	mytaskdata->filter_str = slapi_ch_strdup(filter);
 
+	slapi_pblock_get(pb,SLAPI_REQUESTOR_DN, &dn);
+	mytaskdata->binddn = slapi_ch_strdup(dn);
+
 	/* allocate new task now */
 	task = slapi_new_task(slapi_entry_get_ndn(e));
 
@@ -2366,17 +2378,18 @@ memberof_task_destructor(Slapi_Task *task)
 		if (mydata) {
 			slapi_ch_free_string(&mydata->dn);
 			slapi_ch_free_string(&mydata->filter_str);
+			slapi_ch_free_string(&mydata->binddn);
 			/* Need to cast to avoid a compiler warning */
 			slapi_ch_free((void **)&mydata);
 		}
 	}
 }
 
-int memberof_fix_memberof(MemberOfConfig *config, char *dn, char *filter_str, void *txn)
+int memberof_fix_memberof(Slapi_PBlock *pb, MemberOfConfig *config, char *dn, char *filter_str, void *txn)
 {
 	int rc = 0;
-	struct fix_memberof_callback_data cb_data = {config, txn};
-	Slapi_PBlock *search_pb = slapi_pblock_new();
+	struct fix_memberof_callback_data cb_data = {pb, config, txn};
+	Slapi_PBlock *search_pb = slapi_pblock_new_by_pb(pb);
 
 	slapi_search_internal_set_pb(search_pb, dn,
 		LDAP_SCOPE_SUBTREE, filter_str, 0, 0,
@@ -2409,17 +2422,17 @@ int memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data)
 	Slapi_DN *sdn = slapi_entry_get_sdn(e);
 	struct fix_memberof_callback_data *cb_data = (struct fix_memberof_callback_data *)callback_data;
 	MemberOfConfig *config = cb_data->config;
-	memberof_del_dn_data del_data = {0, config->memberof_attr, cb_data->txn};
+	memberof_del_dn_data del_data = {cb_data->pb, 0, config->memberof_attr, cb_data->txn};
 	Slapi_ValueSet *groups = 0;
 
 	/* get a list of all of the groups this user belongs to */
-	groups = memberof_get_groups(config, dn, cb_data->txn);
+	groups = memberof_get_groups(cb_data->pb, config, dn, cb_data->txn);
 
 	/* If we found some groups, replace the existing memberOf attribute
 	 * with the found values.  */
 	if (groups && slapi_valueset_count(groups))
 	{
-		Slapi_PBlock *mod_pb = slapi_pblock_new();
+		Slapi_PBlock *mod_pb = slapi_pblock_new_by_pb(cb_data->pb);
 		Slapi_Value *val = 0;
 		Slapi_Mod *smod;
 		LDAPMod **mods = (LDAPMod **) slapi_ch_malloc(2 * sizeof(LDAPMod *));
diff --git a/ldap/servers/plugins/mep/mep.c b/ldap/servers/plugins/mep/mep.c
index 303d9b3..6161c16 100644
--- a/ldap/servers/plugins/mep/mep.c
+++ b/ldap/servers/plugins/mep/mep.c
@@ -107,9 +107,9 @@ static int mep_oktodo(Slapi_PBlock *pb);
 static int mep_isrepl(Slapi_PBlock *pb);
 static Slapi_Entry *mep_create_managed_entry(struct configEntry *config,
     Slapi_Entry *origin);
-static void mep_add_managed_entry(struct configEntry *config,
+static void mep_add_managed_entry(Slapi_PBlock *pb, struct configEntry *config,
     Slapi_Entry *origin, void *txn);
-static void mep_rename_managed_entry(Slapi_Entry *origin,
+static void mep_rename_managed_entry(Slapi_PBlock *pb, Slapi_Entry *origin,
     Slapi_DN *new_dn, Slapi_DN *old_dn, void *txn);
 static Slapi_Mods *mep_get_mapped_mods(struct configEntry *config,
     Slapi_Entry *origin, char **mapped_dn);
@@ -1422,12 +1422,12 @@ mep_create_managed_entry(struct configEntry *config, Slapi_Entry *origin)
  * newly created managed entry.
  */
 static void
-mep_add_managed_entry(struct configEntry *config,
+mep_add_managed_entry(Slapi_PBlock *pb, struct configEntry *config,
     Slapi_Entry *origin, void *txn)
 {
     Slapi_Entry *managed_entry = NULL;
     char *managed_dn = NULL;
-    Slapi_PBlock *mod_pb = slapi_pblock_new();
+    Slapi_PBlock *mod_pb = slapi_pblock_new_by_pb(pb);
     int result = LDAP_SUCCESS;
 
     /* Create the managed entry */
@@ -1523,11 +1523,11 @@ mep_add_managed_entry(struct configEntry *config,
  * origin entry.
  */
 static void
-mep_rename_managed_entry(Slapi_Entry *origin,
+mep_rename_managed_entry(Slapi_PBlock *pb, Slapi_Entry *origin,
                          Slapi_DN *new_dn, Slapi_DN *old_dn, void *txn)
 {
     Slapi_RDN *srdn = slapi_rdn_new();
-    Slapi_PBlock *mep_pb = slapi_pblock_new();
+    Slapi_PBlock *mep_pb = slapi_pblock_new_by_pb(pb);
     LDAPMod mod;
     LDAPMod *mods[2];
     char *vals[2];
@@ -2392,7 +2392,7 @@ mep_mod_post_op(Slapi_PBlock *pb)
                 smods = mep_get_mapped_mods(config, e, &mapped_dn);
                 if (smods) {
                     /* Clear out the pblock for reuse. */
-                    mep_pb = slapi_pblock_new();
+                    mep_pb = slapi_pblock_new_by_pb(pb);
 
                     /* Perform the modify operation. */
                     slapi_log_error(SLAPI_LOG_PLUGIN, MEP_PLUGIN_SUBSYSTEM,
@@ -2423,7 +2423,7 @@ mep_mod_post_op(Slapi_PBlock *pb)
                     managed_sdn = slapi_sdn_new_normdn_byref(managed_dn);
 
                     if (slapi_sdn_compare(managed_sdn, mapped_sdn) != 0) {
-                        mep_rename_managed_entry(e, mapped_sdn, managed_sdn, txn);
+                        mep_rename_managed_entry(pb, e, mapped_sdn, managed_sdn, txn);
                     }
 
                     slapi_sdn_free(&mapped_sdn);
@@ -2499,7 +2499,7 @@ mep_add_post_op(Slapi_PBlock *pb)
 
         mep_find_config(e, &config);
         if (config) {
-            mep_add_managed_entry(config, e, txn);
+            mep_add_managed_entry(pb, config, e, txn);
         }
 
         mep_config_unlock();
@@ -2646,7 +2646,7 @@ mep_modrdn_post_op(Slapi_PBlock *pb)
         LDAPMod *mods[3];
         char *vals[2];
         int result = LDAP_SUCCESS;
-        Slapi_PBlock *mep_pb = slapi_pblock_new();
+        Slapi_PBlock *mep_pb = slapi_pblock_new_by_pb(pb);
         Slapi_Entry *new_managed_entry = NULL;
         Slapi_DN *managed_sdn = NULL;
         Slapi_Mods *smods = NULL;
@@ -2775,7 +2775,7 @@ mep_modrdn_post_op(Slapi_PBlock *pb)
                                     "entry \"%s\".\n ", managed_dn,
                                     slapi_entry_get_dn(new_managed_entry),
                                     slapi_sdn_get_dn(old_sdn));
-                    mep_rename_managed_entry(post_e,
+                    mep_rename_managed_entry(pb, post_e,
                                     slapi_entry_get_sdn(new_managed_entry),
                                     managed_sdn, txn);
                 }
@@ -2838,7 +2838,7 @@ bailmod:
 
         mep_find_config(post_e, &config);
         if (config) {
-            mep_add_managed_entry(config, post_e, txn);
+            mep_add_managed_entry(pb, config, post_e, txn);
         }
 
         mep_config_unlock();
diff --git a/ldap/servers/plugins/referint/referint.c b/ldap/servers/plugins/referint/referint.c
index 195ff2b..775da59 100644
--- a/ldap/servers/plugins/referint/referint.c
+++ b/ldap/servers/plugins/referint/referint.c
@@ -77,10 +77,10 @@ int referint_postop_del( Slapi_PBlock *pb );
 int referint_postop_modrdn( Slapi_PBlock *pb ); 
 int referint_postop_start( Slapi_PBlock *pb);
 int referint_postop_close( Slapi_PBlock *pb);
-int update_integrity(char **argv, Slapi_DN *sDN, char *newrDN, Slapi_DN *newsuperior, int logChanges, void *txn);
+int update_integrity(Slapi_PBlock *pb, char **argv, Slapi_DN *sDN, char *newrDN, Slapi_DN *newsuperior, int logChanges, void *txn);
 void referint_thread_func(void *arg);
 int  GetNextLine(char *dest, int size_dest, PRFileDesc *stream);
-void writeintegritylog(char *logfilename, Slapi_DN *sdn, char *newrdn, Slapi_DN *newsuperior);
+void writeintegritylog(Slapi_PBlock *pb, char *logfilename, Slapi_DN *sdn, char *newrdn, Slapi_DN *newsuperior);
 int my_fgetc(PRFileDesc *stream);
 
 /* global thread control stuff */
@@ -215,10 +215,10 @@ referint_postop_del( Slapi_PBlock *pb )
 		}else if(delay == 0){
 		  /* no delay */
  		  /* call function to update references to entry */
-		  rc = update_integrity(argv, sdn, NULL, NULL, logChanges, txn);
+		  rc = update_integrity(pb, argv, sdn, NULL, NULL, logChanges, txn);
 		}else{
 		  /* write the entry to integrity log */
-		  writeintegritylog(argv[1], sdn, NULL, NULL);
+		  writeintegritylog(pb, argv[1], sdn, NULL, NULL);
 		  rc = 0;
 		}
 	} else {
@@ -300,11 +300,11 @@ referint_postop_modrdn( Slapi_PBlock *pb )
 	}else if(delay == 0){
 	  /* no delay */
 	  /* call function to update references to entry */
-	  rc = update_integrity(argv, sdn, newrdn,
+	  rc = update_integrity(pb, argv, sdn, newrdn,
 	                        newsuperior, logChanges, txn);
 	}else{
 	  /* write the entry to integrity log */
-	  writeintegritylog(argv[1], sdn, newrdn, newsuperior);
+	  writeintegritylog(pb, argv[1], sdn, newrdn, newsuperior);
 	  rc = 0;
 	}
 
@@ -674,12 +674,12 @@ bail:
 }
 
 int
-update_integrity(char **argv, Slapi_DN *origSDN,
+update_integrity(Slapi_PBlock *pb, char **argv, Slapi_DN *origSDN,
                  char *newrDN, Slapi_DN *newsuperior, 
                  int logChanges, void *txn)
 {
     Slapi_PBlock *search_result_pb = NULL;
-    Slapi_PBlock *mod_pb = slapi_pblock_new();
+    Slapi_PBlock *mod_pb = slapi_pblock_new_by_pb(pb);
     Slapi_Entry  **search_entries = NULL;
     int search_result;
     Slapi_DN *sdn = NULL;
@@ -912,8 +912,10 @@ referint_thread_func(void *arg)
 	Slapi_DN *sdn = NULL;
     char *tmprdn;
     Slapi_DN *tmpsuperior = NULL;
+    Slapi_DN *binddn = NULL;
     int logChanges=0;
 	char * iter = NULL;
+	Slapi_PBlock *pb = slapi_pblock_new_by_pb(NULL);
 
     if(plugin_argv == NULL){
       slapi_log_error( SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM,
@@ -972,6 +974,7 @@ referint_thread_func(void *arg)
 	while( GetNextLine(thisline, MAX_LINE, prfd) ){
 	    ptoken = ldap_utf8strtok_r(thisline, delimiter, &iter);
 		sdn = slapi_sdn_new_normdn_byref(ptoken);
+		slapi_pblock_init(pb);
 
 	    ptoken = ldap_utf8strtok_r (NULL, delimiter, &iter);
 	    if(!strcasecmp(ptoken, "NULL")) {
@@ -986,8 +989,16 @@ referint_thread_func(void *arg)
 	    } else {
 	        tmpsuperior = slapi_sdn_new_normdn_byref(ptoken);
 	    }
+
+	    /* this should be the bind DN that performed the original delete */
+	    ptoken = ldap_utf8strtok_r (NULL, delimiter, &iter);
+	    if (!strcasecmp(ptoken, "NULL")) {
+	        binddn = NULL;
+	    } else {
+	    	slapi_pblock_set(pb, SLAPI_REQUESTOR_DN, ptoken);
+	    }
       
-	    update_integrity(plugin_argv, sdn, tmprdn,
+	    update_integrity(pb, plugin_argv, sdn, tmprdn,
 	                     tmpsuperior, logChanges, NULL);
       
 	    slapi_sdn_free(&sdn);
@@ -1025,7 +1036,7 @@ referint_thread_func(void *arg)
 		PR_DestroyCondVar(keeprunning_cv);
 	}
 
-
+	slapi_pblock_destroy(pb);
 }
 
 int my_fgetc(PRFileDesc *stream)
@@ -1105,11 +1116,12 @@ GetNextLine(char *dest, int size_dest, PRFileDesc *stream) {
 }
 
 void
-writeintegritylog(char *logfilename, Slapi_DN *sdn, 
+writeintegritylog(Slapi_PBlock *pb, char *logfilename, Slapi_DN *sdn,
                   char *newrdn, Slapi_DN *newsuperior)
 {
     PRFileDesc *prfd;
     char buffer[MAX_LINE];
+    char *dn = NULL;
     int len_to_write = 0;
     int rc;
     /* write this record to the file */
@@ -1161,11 +1173,12 @@ writeintegritylog(char *logfilename, Slapi_DN *sdn,
                          " line length exceeded. It will not be able"
                          " to update references to this entry.\n");
     }else{
-       PR_snprintf(buffer, MAX_LINE, "%s\t%s\t%s\t\n", 
+       slapi_pblock_get(pb, SLAPI_REQUESTOR_DN, &dn);
+       PR_snprintf(buffer, MAX_LINE, "%s\t%s\t%s\t%s\t\n",
 				   slapi_sdn_get_dn(sdn),
 				   (newrdn != NULL) ? newrdn : "NULL",
-				   (newsuperior != NULL) ? slapi_sdn_get_dn(newsuperior) :
-				                           "NULL");
+				   (newsuperior != NULL) ? slapi_sdn_get_dn(newsuperior) : "NULL",
+				   dn );
         if (PR_Write(prfd,buffer,strlen(buffer)) < 0){
            slapi_log_error(SLAPI_LOG_FATAL,REFERINT_PLUGIN_SUBSYSTEM,
 	       " writeintegritylog: PR_Write failed : The disk"
diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c
index 0304578..434901e 100644
--- a/ldap/servers/slapd/add.c
+++ b/ldap/servers/slapd/add.c
@@ -73,7 +73,7 @@
 /* Forward declarations */
 static int add_internal_pb (Slapi_PBlock *pb);
 static void op_shared_add (Slapi_PBlock *pb);
-static int add_created_attrs(Operation *op, Slapi_Entry *e);
+static int add_created_attrs(Slapi_PBlock *pb, Slapi_Entry *e);
 static int check_rdn_for_created_attrs(Slapi_Entry *e);
 static void handle_fast_add(Slapi_PBlock *pb, Slapi_Entry *entry);
 static int add_uniqueid (Slapi_Entry *e);
@@ -390,8 +390,15 @@ void slapi_add_entry_internal_set_pb (Slapi_PBlock *pb, Slapi_Entry *e, LDAPCont
 		return;
 	}
 
-	op = internal_operation_new(SLAPI_OPERATION_ADD,operation_flags);
-	slapi_pblock_set(pb, SLAPI_OPERATION, op);
+	/* if the operation is not NULL, then it was already set */
+	if(pb->pb_op == NULL){
+		op = internal_operation_new(SLAPI_OPERATION_ADD,operation_flags);
+		slapi_pblock_set(pb, SLAPI_OPERATION, op);
+	} else {
+		/* we still want to set the flags & type though */
+		operation_set_flag(pb->pb_op, operation_flags);
+		operation_set_type(pb->pb_op, SLAPI_OPERATION_ADD);
+	}
 	slapi_pblock_set(pb, SLAPI_ADD_ENTRY, e);
 	slapi_pblock_set(pb, SLAPI_CONTROLS_ARG, controls);
 	slapi_pblock_set(pb, SLAPI_PLUGIN_IDENTITY, plugin_identity);
@@ -632,7 +639,7 @@ static void op_shared_add (Slapi_PBlock *pb)
 		/* can get lastmod only after backend is selected */
 		slapi_pblock_get(pb, SLAPI_BE_LASTMOD, &lastmod);
 
-		if (lastmod && add_created_attrs(operation, e) != 0)
+		if (lastmod && add_created_attrs(pb, e) != 0)
 		{
 			send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
 				"cannot insert computed attributes", 0, NULL);
@@ -738,19 +745,43 @@ done:
 }
 
 static int 
-add_created_attrs(Operation *op, Slapi_Entry *e)
+add_created_attrs(Slapi_PBlock *pb, Slapi_Entry *e)
 {
 	char   buf[20];
 	struct berval	bv;
 	struct berval	*bvals[2];
 	time_t		curtime;
 	struct tm	ltm;
+	Operation    *op;
+	char *plugin_dn = NULL;
+	struct slapdplugin *plugin = NULL;
+	struct slapi_componentid *cid = NULL;
+	slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
 
 	LDAPDebug(LDAP_DEBUG_TRACE, "add_created_attrs\n", 0, 0, 0);
 
+	slapi_pblock_get(pb, SLAPI_OPERATION, &op);
 	bvals[0] = &bv;
 	bvals[1] = NULL;
 	
+	if(slapdFrontendConfig->plugin_track && !slapi_sdn_isempty(&op->o_sdn)){
+		/* write the bind dn and plugin name to the new attributes  */
+		slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &cid);
+		if (cid)
+			plugin=(struct slapdplugin *) cid->sci_plugin;
+		if(plugin)
+			plugin_dn = plugin_get_dn(plugin);
+		if(plugin_dn){
+			bv.bv_val = plugin_dn;
+			bv.bv_len = strlen(bv.bv_val);
+		} else {
+			bv.bv_val = (char*)slapi_sdn_get_dn(&op->o_sdn);
+			bv.bv_len = strlen(bv.bv_val);
+		}
+		slapi_entry_attr_replace(e, "internalCreatorsName", bvals);
+		slapi_entry_attr_replace(e, "internalModifiersName", bvals);
+	}
+
 	if (slapi_sdn_isempty(&op->o_sdn)) {
 		bv.bv_val = "";
 		bv.bv_len = strlen(bv.bv_val);
diff --git a/ldap/servers/slapd/config.c b/ldap/servers/slapd/config.c
index f1df7ba..d97a575 100644
--- a/ldap/servers/slapd/config.c
+++ b/ldap/servers/slapd/config.c
@@ -241,13 +241,14 @@ slapd_bootstrap_config(const char *configdir)
 			char schemacheck[BUFSIZ];
 			char syntaxcheck[BUFSIZ];
 			char syntaxlogging[BUFSIZ];
+			char plugintracking[BUFSIZ];
 			char dn_validate_strict[BUFSIZ];
 			Slapi_DN plug_dn;
 
 			workpath[0] = loglevel[0] = maxdescriptors[0] = '\0';
 			val[0] = logenabled[0] = schemacheck[0] = syntaxcheck[0] = '\0';
 			syntaxlogging[0] = _localuser[0] = '\0';
-			dn_validate_strict[0] = '\0';
+			plugintracking [0] = dn_validate_strict[0] = '\0';
 
 			/* Convert LDIF to entry structures */
 			slapi_sdn_init_ndn_byref(&plug_dn, PLUGIN_BASE_DN);
@@ -464,6 +465,20 @@ slapd_bootstrap_config(const char *configdir)
 					}
 				}
 
+				/* see if we need to enable plugin binddn tracking */
+				if (!plugintracking[0] &&
+					entry_has_attr_and_value(e, CONFIG_PLUGIN_BINDDN_TRACKING_ATTRIBUTE,
+											 plugintracking, sizeof(plugintracking)))
+				{
+					if (config_set_plugin_tracking(CONFIG_PLUGIN_BINDDN_TRACKING_ATTRIBUTE,
+							plugintracking, errorbuf, CONFIG_APPLY)
+								!= LDAP_SUCCESS)
+					{
+						LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
+								CONFIG_PLUGIN_BINDDN_TRACKING_ATTRIBUTE, errorbuf);
+					}
+				}
+
 				/* see if we need to enable syntax checking */
 				if (!syntaxcheck[0] &&
 				    entry_has_attr_and_value(e, CONFIG_SYNTAXCHECK_ATTRIBUTE,
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index aafbd7e..b6c0c1f 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -532,6 +532,9 @@ static struct config_get_and_set {
 	{CONFIG_RESULT_TWEAK_ATTRIBUTE, config_set_result_tweak,
 		NULL, 0,
 		(void**)&global_slapdFrontendConfig.result_tweak, CONFIG_ON_OFF, NULL},
+	{CONFIG_PLUGIN_BINDDN_TRACKING_ATTRIBUTE, config_set_plugin_tracking,
+		NULL, 0,
+		(void**)&global_slapdFrontendConfig.plugin_track, CONFIG_ON_OFF, NULL},
 	{CONFIG_ATTRIBUTE_NAME_EXCEPTION_ATTRIBUTE, config_set_attrname_exceptions,
 		NULL, 0,
 		(void**)&global_slapdFrontendConfig.attrname_exceptions, CONFIG_ON_OFF, NULL},
@@ -957,6 +960,7 @@ FrontendConfig_init () {
   cfg->anon_limits_dn = slapi_ch_strdup("");
   cfg->schemacheck = LDAP_ON;
   cfg->syntaxcheck = LDAP_OFF;
+  cfg->plugin_track = LDAP_OFF;
   cfg->syntaxlogging = LDAP_OFF;
   cfg->dn_validate_strict = LDAP_OFF;
   cfg->ds4_compatible_schema = LDAP_OFF;
@@ -2466,6 +2470,19 @@ config_set_result_tweak( const char *attrname, char *value, char *errorbuf, int
   return retVal;
 }
 
+int
+config_set_plugin_tracking( const char *attrname, char *value, char *errorbuf, int apply ) {
+  int retVal = LDAP_SUCCESS;
+  slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+  retVal = config_set_onoff ( attrname,
+							  value,
+							  &(slapdFrontendConfig->plugin_track),
+							  errorbuf,
+							  apply);
+
+  return retVal;
+}
 
 int
 config_set_security( const char *attrname, char *value, char *errorbuf, int apply ) {
diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c
index c346a6a..869eb27 100644
--- a/ldap/servers/slapd/modify.c
+++ b/ldap/servers/slapd/modify.c
@@ -489,8 +489,14 @@ slapi_modify_internal_set_pb (Slapi_PBlock *pb, const char *dn,
 		return;
 	}
 
-	op= internal_operation_new(SLAPI_OPERATION_MODIFY,operation_flags);
-	slapi_pblock_set(pb, SLAPI_OPERATION, op);       
+	/* if we're tracking the plugin bind dn, then just set the type/flags */
+	if(pb->plugin_tracking){
+		operation_set_flag(pb->pb_op, operation_flags);
+		operation_set_type(pb->pb_op, SLAPI_OPERATION_MODIFY);
+	} else {
+		op = internal_operation_new(SLAPI_OPERATION_MODIFY,operation_flags);
+		slapi_pblock_set(pb, SLAPI_OPERATION, op);
+	}
 	slapi_pblock_set(pb, SLAPI_ORIGINAL_TARGET, (void*)dn);
 	slapi_pblock_set(pb, SLAPI_MODIFY_MODS, mods);
 	slapi_pblock_set(pb, SLAPI_CONTROLS_ARG, controls);
@@ -518,8 +524,14 @@ slapi_modify_internal_set_pb_ext(Slapi_PBlock *pb, const Slapi_DN *sdn,
 		return;
 	}
 
-	op= internal_operation_new(SLAPI_OPERATION_MODIFY,operation_flags);
-	slapi_pblock_set(pb, SLAPI_OPERATION, op);       
+	/* if we're tracking the plugin bind dn, then just set the type/flags */
+	if(pb->plugin_tracking){
+		operation_set_flag(pb->pb_op, operation_flags);
+		operation_set_type(pb->pb_op, SLAPI_OPERATION_MODIFY);
+	} else {
+		op = internal_operation_new(SLAPI_OPERATION_MODIFY,operation_flags);
+		slapi_pblock_set(pb, SLAPI_OPERATION, op);
+	}
 	slapi_pblock_set(pb, SLAPI_ORIGINAL_TARGET, (void *)slapi_sdn_get_dn(sdn));
 	slapi_pblock_set(pb, SLAPI_TARGET_SDN, (void *)sdn);
 	slapi_pblock_set(pb, SLAPI_MODIFY_MODS, mods);
diff --git a/ldap/servers/slapd/modrdn.c b/ldap/servers/slapd/modrdn.c
index a7bb1a6..7cd88ce 100644
--- a/ldap/servers/slapd/modrdn.c
+++ b/ldap/servers/slapd/modrdn.c
@@ -252,7 +252,7 @@ do_modrdn( Slapi_PBlock *pb )
 	}
 
 	LDAPDebug( LDAP_DEBUG_ARGS,
-			   "do_moddn: dn (%s) newrdn (%s) deloldrdn (%d)\n", dn, newrdn,
+			   "do_modrdn: dn (%s) newrdn (%s) deloldrdn (%d)\n", dn, newrdn,
 			   deloldrdn );
 
 	slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &pb->pb_op->o_isroot );
@@ -359,8 +359,14 @@ slapi_rename_internal_set_pb_ext(Slapi_PBlock *pb,
         return;
     }
 
-    op = internal_operation_new(SLAPI_OPERATION_MODRDN,operation_flags); 
-    slapi_pblock_set(pb, SLAPI_OPERATION, op); 
+    /* if we're tracking the plugin bind dn, then just set the type/flags */
+    if(pb->plugin_tracking){
+    	operation_set_flag(pb->pb_op, operation_flags);
+    	operation_set_type(pb->pb_op, SLAPI_OPERATION_MODRDN);
+    } else {
+        op = internal_operation_new(SLAPI_OPERATION_MODRDN,operation_flags);
+    	slapi_pblock_set(pb, SLAPI_OPERATION, op);
+    }
     slapi_pblock_set(pb, SLAPI_ORIGINAL_TARGET, 
                      (void*)slapi_sdn_get_dn(olddn));
     slapi_pblock_set(pb, SLAPI_MODRDN_TARGET_SDN, (void*)olddn);
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
index ff17cd9..12f7fdf 100644
--- a/ldap/servers/slapd/opshared.c
+++ b/ldap/servers/slapd/opshared.c
@@ -136,19 +136,40 @@ do_ps_service(Slapi_Entry *e, Slapi_Entry *eprev, ber_int_t chgtype, ber_int_t c
 void modify_update_last_modified_attr(Slapi_PBlock *pb, Slapi_Mods *smods)
 {
     char        buf[20];
+    char        *plugin_dn = NULL;
     struct berval    bv;
     struct berval    *bvals[2];
     time_t        curtime;
     struct tm    utm;
     Operation    *op;
+    struct slapdplugin *plugin = NULL;
+    struct slapi_componentid *cid = NULL;
+    slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
 
     LDAPDebug(LDAP_DEBUG_TRACE, "modify_update_last_modified_attr\n", 0, 0, 0);
 
     slapi_pblock_get(pb, SLAPI_OPERATION, &op);
-
     bvals[0] = &bv;
     bvals[1] = NULL;
 
+    if(slapdFrontendConfig->plugin_track && !slapi_sdn_isempty(&op->o_sdn)){
+    	/* write to the new attribute the bind dn and plugin name */
+    	slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &cid);
+    	if (cid)
+    		plugin=(struct slapdplugin *) cid->sci_plugin;
+    	if(plugin)
+    		plugin_dn = plugin_get_dn (plugin);
+    	if(plugin_dn){
+    		bv.bv_val = plugin_dn;
+    		bv.bv_len = strlen(bv.bv_val);
+    	} else {
+            bv.bv_val = (char*)slapi_sdn_get_dn(&op->o_sdn);
+            bv.bv_len = strlen(bv.bv_val);
+    	}
+    	slapi_mods_add_modbvps(smods, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES,
+    	                           "internalModifiersName", bvals);
+    }
+
     /* fill in modifiersname */
     if (slapi_sdn_isempty(&op->o_sdn)) {
         bv.bv_val = "";
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index 6b3de8e..f3df0f6 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -96,13 +96,50 @@ slapi_pblock_new()
 	return pb;
 }
 
+/* Use for internal operations by plugins, where we need to track the bind dn */
+Slapi_PBlock *
+slapi_pblock_new_by_pb(Slapi_PBlock *origpb)
+{
+	Slapi_PBlock	*pb;
+
+	pb = (Slapi_PBlock *) slapi_ch_calloc( 1, sizeof(Slapi_PBlock) );
+	pb->pb_op = operation_new(OP_FLAG_INTERNAL);
+	pb->plugin_tracking = 1;
+
+	if(origpb == NULL){
+		return pb;
+	}
+
+	if(origpb->pb_op != NULL){
+		slapi_sdn_set_normdn_byval((&pb->pb_op->o_sdn), slapi_sdn_get_dn(&origpb->pb_op->o_sdn));
+	} else {
+		/* No operation?  Have to use the plugin name */
+		if(origpb->pb_plugin->plg_name){
+			slapi_sdn_set_normdn_byval((&pb->pb_op->o_sdn), origpb->pb_plugin->plg_name);
+		}
+	}
+
+	return pb;
+}
+
 void
 slapi_pblock_init( Slapi_PBlock *pb )
 {
+	Slapi_Operation *op;
+
 	if(pb!=NULL)
 	{
-		pblock_done(pb);
-		pblock_init(pb);
+		if(pb->plugin_tracking){
+			/* preserve the op, and then reset everything */
+			op = pb->pb_op;
+			pblock_done_by_pb(pb);
+			pblock_init(pb);
+			pb->pb_op = op;
+			pb->plugin_tracking = 1;
+		} else {
+			pblock_done(pb);
+			pblock_init(pb);
+		}
 	}
 }
 
@@ -118,6 +155,14 @@ pblock_done( Slapi_PBlock *pb )
 }
 
 void
+pblock_done_by_pb( Slapi_PBlock *pb )
+{
+	/* don't free the operation because we still want to use it */
+	slapi_ch_free((void**)&(pb->pb_vattr_context));
+	slapi_ch_free((void**)&(pb->pb_result_text));
+}
+
+void
 slapi_pblock_destroy( Slapi_PBlock* pb )
 {
 	if(pb!=NULL)
@@ -2068,14 +2113,26 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value )
 		pblock->pb_plugin->plg_desc = *((Slapi_PluginDesc *)value);
 		break;
 	case SLAPI_PLUGIN_INTOP_RESULT:
-	        pblock->pb_internal_op_result = *((int *) value);
-     	        break;
+		pblock->pb_internal_op_result = *((int *) value);
+		break;
 	case SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES:
-	        pblock->pb_plugin_internal_search_op_entries = (Slapi_Entry **) value;
-	        break;
+		pblock->pb_plugin_internal_search_op_entries = (Slapi_Entry **) value;
+		break;
 	case SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS:
-	        pblock->pb_plugin_internal_search_op_referrals = (char **) value;
-	        break;	
+		pblock->pb_plugin_internal_search_op_referrals = (char **) value;
+		break;
+	case SLAPI_REQUESTOR_DN:
+		if(pblock->pb_op == NULL){
+			return (-1);
+		}
+		slapi_sdn_set_dn_byval((&pblock->pb_op->o_sdn),(char *)value);
+		break;
+	case SLAPI_REQUESTOR_SDN:
+		if(pblock->pb_op == NULL){
+			return (-1);
+		}
+		slapi_sdn_set_dn_byval((&pblock->pb_op->o_sdn),slapi_sdn_get_dn((Slapi_DN *)value));
+		break;
 	/* database plugin functions */
 	case SLAPI_PLUGIN_DB_BIND_FN:
 		if ( pblock->pb_plugin->plg_type != SLAPI_PLUGIN_DATABASE ) {
diff --git a/ldap/servers/slapd/plugin_internal_op.c b/ldap/servers/slapd/plugin_internal_op.c
index 9654780..1ac2447 100644
--- a/ldap/servers/slapd/plugin_internal_op.c
+++ b/ldap/servers/slapd/plugin_internal_op.c
@@ -854,7 +854,8 @@ void set_config_params (Slapi_PBlock *pb)
 	Slapi_Operation *operation;
 	struct slapdplugin *plugin = NULL;
 	char *dn;
-        struct slapi_componentid * cid=NULL;
+	struct slapi_componentid * cid=NULL;
+	slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
 
 	slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &cid);
  	if (cid)
@@ -870,10 +871,16 @@ void set_config_params (Slapi_PBlock *pb)
 		operation_clear_flag(operation, OP_FLAG_ACTION_LOG_AUDIT | OP_FLAG_ACTION_LOG_CHANGES);
 	}
 	
-	/* set name to be used for creator's and modifiers attributes */
-	dn = plugin_get_dn (plugin);
-	if (dn)
-		slapi_sdn_init_dn_passin(&operation->o_sdn, dn);
+	/*
+	 *  if we are not tracking the bind dn, then use the plugin name as the
+	 *  modifiersname, otherwise, we have already set the op dn as the bind dn
+	 */
+	if(!slapdFrontendConfig->plugin_track || slapi_sdn_isempty(&operation->o_sdn)){
+		/* set name to be used for creator's and modifiers attributes */
+		dn = plugin_get_dn (plugin);
+		if (dn)
+			slapi_sdn_init_dn_passin(&operation->o_sdn, dn);
+	}
 }
 
 /* set parameters common for all internal operations */
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index e60d1a8..6b868f5 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -289,6 +289,7 @@ int config_set_readonly( const char *attrname, char *value, 	char *errorbuf, int
 int config_set_schemacheck( const char *attrname, char *value, char *errorbuf, int apply );
 int config_set_syntaxcheck( const char *attrname, char *value, char *errorbuf, int apply );
 int config_set_syntaxlogging( const char *attrname, char *value, char *errorbuf, int apply );
+int config_set_plugin_tracking( const char *attrname, char *value, char *errorbuf, int apply );
 int config_set_dn_validate_strict( const char *attrname, char *value, char *errorbuf, int apply );
 int config_set_ds4_compatible_schema( const char *attrname, char *value, char *errorbuf, int apply );
 int config_set_schema_ignore_trailing_spaces( const char *attrname, char *value, char *errorbuf, int apply );
@@ -1082,6 +1083,7 @@ void do_unbind( Slapi_PBlock *pb );
 void pblock_init( Slapi_PBlock *pb );
 void pblock_init_common( Slapi_PBlock *pb, Slapi_Backend *be, Connection *conn, Operation *op );
 void pblock_done( Slapi_PBlock *pb );
+void pblock_done_by_pb( Slapi_PBlock *pb );
 void bind_credentials_set( Connection *conn,
                 char *authtype, char *normdn,
                 char *extauthtype, char *externaldn, CERTCertificate *clientcert , Slapi_Entry * binded);
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index b855ff0..3e63f11 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1501,6 +1501,7 @@ typedef struct slapi_pblock {
 	int		pb_config_lineno;
 	int		pb_config_argc;
 	char		**pb_config_argv;
+	int		plugin_tracking;
 
 	/* [pre|post]add arguments */
 	struct slapi_entry	*pb_target_entry; /* JCM - Duplicated */
@@ -1953,6 +1954,7 @@ typedef struct _slapdEntryPoints {
 #define CONFIG_ERRORLOG_LIST_ATTRIBUTE "nsslapd-errorlog-list"
 #define CONFIG_AUDITLOG_LIST_ATTRIBUTE "nsslapd-auditlog-list"
 #define CONFIG_REWRITE_RFC1274_ATTRIBUTE "nsslapd-rewrite-rfc1274"
+#define CONFIG_PLUGIN_BINDDN_TRACKING_ATTRIBUTE "nsslapd-plugin-binddn-tracking"
 
 #define CONFIG_CONFIG_ATTRIBUTE "nsslapd-config"
 #define CONFIG_INSTDIR_ATTRIBUTE "nsslapd-instancedir"
@@ -2078,6 +2080,7 @@ typedef struct _slapdFrontendConfig {
   char **backendconfig;
   char **include;
   char **plugin;
+  int plugin_track;
   struct pw_scheme *pw_storagescheme;
 
   int pwpolicy_local;
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 36683a4..cd9fcab 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -607,6 +607,19 @@ typedef void (*TaskCallbackFn)(Slapi_Task *task);
 Slapi_PBlock *slapi_pblock_new( void ); /* allocate and initialize */
 
 /**
+ * Creates a new parameter block.
+ *
+ * \return This function returns a pointer to the new parameter block.
+ * \warning This function takes the original operation struct, and adds it the
+ *          the new pb.  This is so we can track the original bind dn
+ * \warning The pblock pointer allocated with this function must always be freed by
+ *          slapi_pblock_destroy(). The use of other memory deallocators (for example,
+ *          <tt>free()</tt>) is not supported and may lead to crashes or memory leaks.
+ * \see slapi_pblock_destroy()
+ */
+Slapi_PBlock *slapi_pblock_new_by_pb( Slapi_PBlock *pb ); /* allocate and initialize */
+
+/**
  * Initializes an existing parameter block for re-use.
  *
  * \param pb The parameter block to initialize.
@@ -6166,6 +6179,7 @@ time_t slapi_current_time( void );
 /* operation */
 #define SLAPI_OPINITIATED_TIME			140
 #define SLAPI_REQUESTOR_DN			141
+#define SLAPI_REQUESTOR_SDN			852
 #define SLAPI_REQUESTOR_NDN			156
 #define SLAPI_OPERATION_PARAMETERS		138
 #define SLAPI_OPERATION_TYPE			590
-- 
1.7.1

