summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/plugin_internal_op.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/servers/slapd/plugin_internal_op.c')
-rw-r--r--ldap/servers/slapd/plugin_internal_op.c864
1 files changed, 864 insertions, 0 deletions
diff --git a/ldap/servers/slapd/plugin_internal_op.c b/ldap/servers/slapd/plugin_internal_op.c
new file mode 100644
index 00000000..63a46e1b
--- /dev/null
+++ b/ldap/servers/slapd/plugin_internal_op.c
@@ -0,0 +1,864 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/* stevross@netscape.com June 13 1997 */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include "slapi-plugin.h"
+#include "slap.h"
+
+#if defined(NET_SSL)
+#include <ssl.h>
+#endif
+
+/* entry list node */
+typedef struct Entry_Node{
+ Slapi_Entry *data;
+ struct Entry_Node *next;
+} Entry_Node;
+
+/* referral list node */
+typedef struct Referral_Node{
+ char *data;
+ struct Referral_Node *next;
+} Referral_Node;
+
+/* data that must be passed to slapi_search_internal_callback */
+typedef struct plugin_search_internal_data{
+ int rc;
+ int num_entries;
+ int num_referrals;
+ Entry_Node *entry_list_head;
+ Referral_Node *referral_list_head;
+} plugin_search_internal_data;
+
+/* callback functions */
+typedef struct callback_fn_ptrs{
+ plugin_result_callback p_res_callback;
+ plugin_search_entry_callback p_srch_entry_callback;
+ plugin_referral_entry_callback p_ref_entry_callback;
+ void *callback_data;
+}callback_fn_ptrs;
+
+/* forward declarations */
+static int seq_internal_callback_pb (Slapi_PBlock *pb, void *callback_data,
+ plugin_result_callback prc,
+ plugin_search_entry_callback psec,
+ plugin_referral_entry_callback prec);
+static int search_internal_pb (Slapi_PBlock *pb);
+static int search_internal_callback_pb (Slapi_PBlock *pb, void *callback_data, plugin_result_callback prc,
+ plugin_search_entry_callback psec, plugin_referral_entry_callback prec);
+
+void
+internal_getresult_callback(struct conn *unused1,
+ struct op *op,
+ int err,
+ char *unused2,
+ char *unused3,
+ int unused4,
+ struct berval **unused5)
+{
+
+ if (op != NULL)
+ {
+ *((int *)op->o_handler_data) = err;
+ }
+
+}
+
+void
+internal_res_callback(struct conn *unused1, struct op *op, int err, char *unused2,
+ char *unused3, int unused4, struct berval **unused5)
+{
+ /* make sure the user has a callback defined, if so do it, otherwise do nothing */
+ if( ((callback_fn_ptrs *)op->o_handler_data) != NULL
+ && ((callback_fn_ptrs *)op->o_handler_data)->p_res_callback != NULL
+ )
+ {
+ ((callback_fn_ptrs *)op->o_handler_data)->p_res_callback
+ (err, ((callback_fn_ptrs *)op->o_handler_data)->callback_data);
+ }
+
+}
+
+int
+internal_srch_entry_callback(Slapi_Backend* be, Connection* conn,
+ Operation* op, Slapi_Entry* e)
+{
+ /* make sure the user has a callback defined, if so do it, otherwise do nothing */
+ if( ((callback_fn_ptrs *)op->o_handler_data) != NULL
+ && ((callback_fn_ptrs *)op->o_handler_data)->p_srch_entry_callback != NULL
+ )
+ {
+ return(((callback_fn_ptrs *)op->o_handler_data)->p_srch_entry_callback
+ (e, ((callback_fn_ptrs *)op->o_handler_data)->callback_data));
+ }
+
+ return(0);
+}
+
+int
+internal_ref_entry_callback(Slapi_Backend * be, Connection *conn,
+ Operation *op, struct berval **ireferral)
+{
+
+ int i;
+
+ /* make sure the user has a callback defined, if so do it, otherwise do nothing */
+ if( ((callback_fn_ptrs *)op->o_handler_data) != NULL
+ && ((callback_fn_ptrs *)op->o_handler_data)->p_ref_entry_callback != NULL
+ && ireferral != NULL
+ )
+ {
+ /* loop over referrals calling callback for each one */
+ for(i=0; ireferral[i] != NULL; i++)
+ {
+ ((callback_fn_ptrs *)op->o_handler_data)->p_ref_entry_callback(ireferral[i]->bv_val,
+ ((callback_fn_ptrs *)op->o_handler_data)->callback_data);
+ }
+ }
+ return(0);
+}
+
+Slapi_Operation*
+internal_operation_new(unsigned long op_type, int flags)
+{
+ Slapi_Operation *op= operation_new(flags | OP_FLAG_INTERNAL /*Internal*/);
+ /* set operation type: add, delete, etc */
+ operation_set_type(op,op_type);
+ /* Call the plugin extension constructors */
+ op->o_extension = factory_create_extension(get_operation_object_type(),op,NULL /* Parent */);
+ return op;
+}
+
+/******************************************************************************
+*
+* do_disconnect_server
+*
+*
+*
+*
+*******************************************************************************/
+
+/* this is just a wrapper exposed to the plugins */
+void
+slapi_disconnect_server(Slapi_Connection *conn)
+{
+ do_disconnect_server(conn, conn->c_connid, -1);
+}
+
+static get_disconnect_server_fn_ptr disconnect_server_fn = NULL;
+
+void
+do_disconnect_server(Connection *conn, int opconnid, int opid)
+{
+ if (NULL == disconnect_server_fn) {
+ if (get_entry_point(ENTRY_POINT_DISCONNECT_SERVER, (caddr_t *)(&disconnect_server_fn)) < 0) {
+ return;
+ }
+ }
+ /* It seems that we only call this from result.c when the ber_flush fails. */
+ (disconnect_server_fn)(conn, opconnid, opid, SLAPD_DISCONNECT_BER_FLUSH, 0);
+}
+
+
+/******************************************************************************
+*
+* slapi_compare_internal
+*
+* no plans to implement this, but placeholder incase we change our mind
+*
+*
+*******************************************************************************/
+
+
+Slapi_PBlock *
+slapi_compare_internal(char * dn,
+ char *attr,
+ char *value,
+ LDAPControl **controls)
+{
+ printf("slapi_compare_internal not yet implemented \n");
+ return(0);
+}
+
+int
+slapi_seq_callback( const char *ibase,
+ int type,
+ char *attrname,
+ char *val,
+ char **attrs,
+ int attrsonly,
+ void *callback_data,
+ LDAPControl **controls,
+ plugin_result_callback res_callback,
+ plugin_search_entry_callback srch_callback,
+ plugin_referral_entry_callback ref_callback)
+{
+ int r;
+ Slapi_PBlock pb;
+
+ if (ibase == NULL)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, NULL,
+ "slapi_seq_callback: NULL parameter\n");
+ return -1;
+ }
+
+ pblock_init(&pb);
+
+ slapi_seq_internal_set_pb(&pb, (char *)ibase, type, attrname, val, attrs, attrsonly, controls,
+ plugin_get_default_component_id(), 0);
+
+ r= seq_internal_callback_pb (&pb, callback_data, res_callback, srch_callback, ref_callback);
+ pblock_done(&pb);
+ return r;
+}
+
+
+
+/* pblock should contain the following data (can be set via call to slapi_seq_internal_set_pb):
+ SLAPI_SEARCH_TARGET set to search base
+ SAPI_SEQ_TYPE set to sequential access type (SLAPI_SEQ_FIRST, SLAPI_SEQ_NEXT, etc.
+ SLAPI_SEQ_ATTRNAME the next two fields define attribute value assertion
+ SLAPI_SEQ_VAL relative to which access is performed.
+ SLAPI_CONTROLS_ARG set to request controls if present
+ SLAPI_SEARCH_ATTRS set to the list of attributes to return
+ SLAPI_SEARCH_ATTRSONLY tells whether attribute values should be returned.
+ */
+
+int slapi_seq_internal_callback_pb (Slapi_PBlock *pb, void *callback_data, plugin_result_callback res_callback,
+ plugin_search_entry_callback srch_callback,
+ plugin_referral_entry_callback ref_callback)
+{
+ if (pb == NULL)
+ return -1;
+
+ if (!allow_operation (pb))
+ {
+ send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "This plugin is not configured to access operation target data", 0, NULL );
+ return 0;
+ }
+
+ return (seq_internal_callback_pb (pb, callback_data, res_callback, srch_callback, ref_callback));
+}
+
+void slapi_search_internal_set_pb (Slapi_PBlock *pb, const char *base, int scope, const char *filter, char **attrs,
+ int attrsonly, LDAPControl **controls, const char *uniqueid,
+ Slapi_ComponentId *plugin_identity, int operation_flags)
+{
+ Operation *op;
+ if (pb == NULL || base == NULL)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, NULL,
+ "slapi_search_internal_set_pb: NULL parameter\n");
+ return;
+ }
+
+ op= internal_operation_new(SLAPI_OPERATION_SEARCH,operation_flags);
+ slapi_pblock_set(pb, SLAPI_OPERATION, op);
+ slapi_pblock_set(pb, SLAPI_SEARCH_TARGET, (void*)base);
+ slapi_pblock_set(pb, SLAPI_SEARCH_SCOPE, &scope);
+ slapi_pblock_set(pb, SLAPI_SEARCH_STRFILTER, (void*)filter);
+ slapi_pblock_set(pb, SLAPI_CONTROLS_ARG, controls);
+ slapi_pblock_set(pb, SLAPI_SEARCH_ATTRS, attrs);
+ slapi_pblock_set(pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly);
+ if (uniqueid)
+ {
+ slapi_pblock_set(pb, SLAPI_TARGET_UNIQUEID, (void*)uniqueid);
+ }
+ slapi_pblock_set(pb, SLAPI_PLUGIN_IDENTITY, (void*)plugin_identity);
+}
+
+void slapi_seq_internal_set_pb(Slapi_PBlock *pb, char *base, int type, char *attrname, char *val,
+ char **attrs, int attrsonly, LDAPControl **controls,
+ Slapi_ComponentId *plugin_identity, int operation_flags)
+{
+ Operation *op;
+ if (pb == NULL || base == NULL)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, NULL,
+ "slapi_seq_internal_set_pb: NULL parameter\n");
+ return;
+ }
+
+ op= internal_operation_new(SLAPI_OPERATION_SEARCH,operation_flags);
+ slapi_pblock_set(pb, SLAPI_OPERATION, op);
+ slapi_pblock_set(pb, SLAPI_SEARCH_TARGET, base);
+ slapi_pblock_set(pb, SLAPI_SEQ_TYPE, &type);
+ slapi_pblock_set(pb, SLAPI_SEQ_ATTRNAME, attrname);
+ slapi_pblock_set(pb, SLAPI_SEQ_VAL, val);
+ slapi_pblock_set(pb, SLAPI_SEARCH_ATTRS, attrs);
+ slapi_pblock_set(pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly);
+ slapi_pblock_set(pb, SLAPI_CONTROLS_ARG, controls);
+ slapi_pblock_set(pb, SLAPI_PLUGIN_IDENTITY, plugin_identity);
+}
+
+static int seq_internal_callback_pb (Slapi_PBlock *pb, void *callback_data,
+ plugin_result_callback prc,
+ plugin_search_entry_callback psec,
+ plugin_referral_entry_callback prec)
+{
+ int rc;
+ LDAPControl **controls;
+ Operation *op;
+ struct callback_fn_ptrs callback_handler_data;
+ Slapi_Backend *be;
+ Slapi_DN sdn;
+ char *base;
+ char *attrname, *val;
+
+ slapi_pblock_get(pb, SLAPI_SEARCH_TARGET, &base);
+ slapi_pblock_get(pb, SLAPI_CONTROLS_ARG, &controls);
+
+ if (base == NULL) {
+ slapi_sdn_init_dn_byval(&sdn,"");
+ } else {
+ slapi_sdn_init_dn_byval(&sdn, base);
+ }
+ be = slapi_be_select(&sdn);
+
+ callback_handler_data.p_res_callback = prc;
+ callback_handler_data.p_srch_entry_callback = psec;
+ callback_handler_data.p_ref_entry_callback = prec;
+ callback_handler_data.callback_data = callback_data;
+
+ slapi_pblock_get(pb, SLAPI_OPERATION, &op);
+ op->o_handler_data = (void *)&callback_handler_data;
+ op->o_result_handler = internal_res_callback;
+ op->o_search_entry_handler = internal_srch_entry_callback;
+ op->o_search_referral_handler = internal_ref_entry_callback;
+
+ /* set target specification of the operation used to decide which plugins are called for the operation */
+ operation_set_target_spec (op, &sdn);
+
+
+ /* Normalize the attribute type and value */
+ slapi_pblock_get (pb, SLAPI_SEQ_ATTRNAME, &attrname);
+ slapi_pblock_get (pb, SLAPI_SEQ_VAL, &val);
+ attrname = slapi_attr_syntax_normalize(attrname);
+ val = ( NULL == val ) ? NULL : slapi_ch_strdup( val );
+
+ slapi_pblock_set(pb, SLAPI_BACKEND, be);
+ slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database);
+ slapi_pblock_set(pb, SLAPI_SEQ_ATTRNAME, attrname);
+ slapi_pblock_set(pb, SLAPI_SEQ_VAL, val);
+ slapi_pblock_set(pb, SLAPI_REQCONTROLS, controls);
+
+ /* set actions taken to process the operation */
+ set_config_params (pb);
+
+ /* set common parameters */
+ set_common_params (pb);
+
+ if (be->be_seq != NULL)
+ {
+ rc = (*be->be_seq)(pb);
+ }
+ else
+ {
+ send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Function not implemented", 0, NULL);
+ rc = 0;
+ }
+
+ slapi_ch_free((void **) &attrname);
+ slapi_ch_free((void **) &val);
+
+ slapi_sdn_done(&sdn);
+
+ return rc;
+}
+
+int
+slapi_search_internal_callback(const char *ibase,
+ int scope,
+ const char *ifstr,
+ char **attrs,
+ int attrsonly,
+ void *callback_data,
+ LDAPControl **controls,
+ plugin_result_callback res_callback,
+ plugin_search_entry_callback srch_callback,
+ plugin_referral_entry_callback ref_callback)
+{
+ Slapi_PBlock pb;
+ int rc = 0;
+
+ pblock_init(&pb);
+
+ slapi_search_internal_set_pb (&pb, ibase, scope, ifstr, attrs, attrsonly,
+ controls, NULL, plugin_get_default_component_id(), 0);
+
+ rc = search_internal_callback_pb (&pb, callback_data, res_callback,
+ srch_callback, ref_callback);
+ pblock_done(&pb);
+ return (rc);
+}
+
+Slapi_PBlock *
+slapi_search_internal(const char *base,
+ int scope,
+ const char *filter,
+ LDAPControl **controls,
+ char **attrs,
+ int attrsonly)
+{
+
+ Slapi_PBlock *pb;
+
+ /* initialize pb */
+ pb = slapi_pblock_new();
+ if (pb)
+ {
+ slapi_search_internal_set_pb (pb, base, scope, filter, attrs, attrsonly, controls,
+ NULL, plugin_get_default_component_id(), 0);
+
+ search_internal_pb (pb);
+ }
+
+ return pb;
+}
+
+/* This function free searchs result or referral set on internal_ops in pblocks */
+void
+slapi_free_search_results_internal(Slapi_PBlock *pb)
+{
+ int i;
+
+ if(pb->pb_plugin_internal_search_op_entries != NULL)
+ {
+ for(i=0; pb->pb_plugin_internal_search_op_entries[i] != NULL; i++)
+ {
+ slapi_entry_free(pb->pb_plugin_internal_search_op_entries[i]);
+ }
+ slapi_ch_free((void**)&(pb->pb_plugin_internal_search_op_entries));
+ }
+
+ /* free v3 referrals made from result handler */
+ if(pb->pb_plugin_internal_search_op_referrals != NULL)
+ {
+ for(i=0; pb->pb_plugin_internal_search_op_referrals[i] != NULL; i++)
+ {
+ slapi_ch_free((void**)&(pb->pb_plugin_internal_search_op_referrals[i]));
+ }
+ slapi_ch_free((void**)&(pb->pb_plugin_internal_search_op_referrals));
+ }
+}
+
+/* this functions can be used for dn as well as uniqueid based operations */
+
+/* pblock should contain the following data (can be set via call to slapi_search_internal_set_pb):
+ For uniqueid based search:
+ SLAPI_TARGET_DN set to dn that allows to select right backend
+ SLAPI_TARGET_UNIQUEID set to the uniqueid of the entry we are looking for
+
+ For dn based search:
+ SLAPI_TARGET_DN set to search base
+ SLAPI_SEARCH_SCOPE set to search scope
+ SLAPI_SEARCH_STRFILTER set to search filter
+ SLAPI_CONTROLS_ARG set to request controls if present
+ SLAPI_SEARCH_ATTRS set to the list of attributes to return
+ SLAPI_SEARCH_ATTRSONLY tells whether attribute values should be returned.
+ */
+int slapi_search_internal_pb (Slapi_PBlock *pb)
+{
+ if (pb == NULL)
+ return -1;
+
+ if (!allow_operation (pb))
+ {
+ slapi_send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "This plugin is not configured to access operation target data", 0, NULL );
+ return 0;
+ }
+
+ return search_internal_pb (pb);
+}
+
+/* pblock should contain the same data as for slapi_search_internal_pb */
+int slapi_search_internal_callback_pb (Slapi_PBlock *pb, void *callback_data,
+ plugin_result_callback prc,
+ plugin_search_entry_callback psec,
+ plugin_referral_entry_callback prec)
+{
+ if (pb == NULL)
+ return -1;
+
+ if (!allow_operation (pb))
+ {
+ send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "This plugin is not configured to access operation target data", 0, NULL );
+ return 0;
+ }
+
+ return (search_internal_callback_pb (pb, callback_data, prc, psec, prec));
+}
+
+static int
+internal_plugin_search_entry_callback(Slapi_Entry *e, void *callback_data)
+{
+ Entry_Node *this_entry;
+
+ /* add this entry to the list of entries we are making */
+ this_entry = (Entry_Node *)slapi_ch_calloc(1,sizeof(Entry_Node));
+
+ if ((this_entry->data = slapi_entry_dup(e)) == NULL)
+ {
+ return(0);
+ }
+
+ this_entry->next = ((plugin_search_internal_data *) callback_data)->entry_list_head;
+
+ ((plugin_search_internal_data *) callback_data)->entry_list_head = this_entry;
+ ((plugin_search_internal_data *) callback_data)->num_entries++;
+
+ return(0);
+}
+
+static int
+internal_plugin_search_referral_callback(char *referral, void *callback_data)
+{
+ Referral_Node *this_referral;
+
+ /* add this to the list of referrals we are making */
+ this_referral = (Referral_Node *)slapi_ch_calloc(1,sizeof(Referral_Node));
+
+ if ((this_referral->data = slapi_ch_strdup(referral)) == NULL)
+ {
+ return(0);
+ }
+
+ this_referral->next = ((plugin_search_internal_data *) callback_data)->referral_list_head;
+
+ ((plugin_search_internal_data *) callback_data)->referral_list_head = this_referral;
+ ((plugin_search_internal_data *) callback_data)->num_referrals++;
+
+ return(0);
+}
+
+static void internal_plugin_result_callback(int rc, void *callback_data)
+{
+ /* put the result into pb_op_result */
+ ((plugin_search_internal_data *) callback_data)->rc = rc;
+}
+
+static int search_internal_pb (Slapi_PBlock *pb)
+{
+ plugin_search_internal_data psid;
+ Entry_Node *iterator, *tmp;
+ Referral_Node *ref_iterator, *ref_tmp;
+ int i;
+ int opresult = 0;
+ Slapi_Entry **pb_search_entries = NULL;
+ char **pb_search_referrals = NULL;
+ int rc;
+
+ PR_ASSERT (pb);
+
+ /* initialize psid */
+ psid.rc = -1;
+ psid.num_entries =0;
+ psid.num_referrals =0;
+ psid.entry_list_head = NULL;
+ psid.referral_list_head = NULL;
+
+ /* setup additional pb data */
+ slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, &opresult);
+ slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, pb_search_entries);
+ slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS, pb_search_referrals);
+
+ /* call internal search callback, define search_entry_callback, and result_callback such
+ that the results of the search are stuffed into pb */
+ rc = search_internal_callback_pb (pb, &psid, internal_plugin_result_callback,
+ internal_plugin_search_entry_callback,
+ internal_plugin_search_referral_callback);
+ opresult = psid.rc;
+
+ /* stuff search entry pointers from linked list to contiguous array for pblock */
+ pb_search_entries = (Slapi_Entry **)slapi_ch_calloc((psid.num_entries + 1), sizeof(Slapi_Entry *));
+
+ for(i=0,iterator = psid.entry_list_head; iterator !=NULL; iterator=iterator->next, i++)
+ {
+ pb_search_entries[i]= iterator->data;
+ }
+ pb_search_entries[i]=NULL;
+
+ /* free the linked list now that data has been put in the array */
+ iterator=psid.entry_list_head;
+ while(iterator != NULL)
+ {
+ /* free the data held in this node */
+ tmp = iterator;
+ iterator = iterator->next;
+
+ /* free the node */
+ if(tmp != NULL)
+ {
+ slapi_ch_free((void **) &tmp);
+ }
+ }
+ psid.entry_list_head = NULL;
+
+ /* stuff referrals list into an array if we got any to put into the pblock */
+ if(psid.num_referrals != 0)
+ {
+ pb_search_referrals = (char **)slapi_ch_calloc((psid.num_referrals + 1), sizeof(char *));
+
+ for(i=0, ref_iterator = psid.referral_list_head; ref_iterator !=NULL; ref_iterator=ref_iterator->next, i++)
+ {
+ pb_search_referrals[i]= ref_iterator->data;
+ }
+ pb_search_referrals[i]=NULL;
+
+ /* free the linked list now that data has been put in the array */
+ ref_iterator=psid.referral_list_head;
+ while(ref_iterator != NULL)
+ {
+
+ ref_tmp = ref_iterator;
+ ref_iterator = ref_iterator->next;
+
+ /* free the node */
+ if(ref_tmp != NULL)
+ {
+ slapi_ch_free((void **) &ref_tmp);
+ }
+ }
+ psid.referral_list_head = NULL;
+ }
+
+ /* set the result, the array of entries, and the array of referrals in pb */
+ slapi_pblock_set(pb, SLAPI_NENTRIES, &psid.num_entries);
+ slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, &opresult);
+ slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, pb_search_entries);
+ slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS, pb_search_referrals);
+
+ return 0;
+}
+
+static int search_internal_callback_pb (Slapi_PBlock *pb, void *callback_data,
+ plugin_result_callback prc,
+ plugin_search_entry_callback psec,
+ plugin_referral_entry_callback prec)
+{
+ LDAPControl **controls;
+ Operation *op;
+ struct slapi_filter *filter = NULL;
+ char *fstr = NULL;
+ struct callback_fn_ptrs callback_handler_data;
+ int scope;
+ char *ifstr;
+ int opresult;
+ int rc = 0;
+ char *original_base = 0;
+ char *new_base = 0;
+
+ PR_ASSERT (pb);
+
+ /* retrieve search parameters */
+ slapi_pblock_get(pb, SLAPI_SEARCH_SCOPE, &scope);
+ slapi_pblock_get(pb, SLAPI_SEARCH_STRFILTER, &ifstr);
+ slapi_pblock_get(pb, SLAPI_CONTROLS_ARG, &controls);
+
+ /* data validation */
+ if (ifstr == NULL || (scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL
+ && scope != LDAP_SCOPE_SUBTREE))
+ {
+ opresult = LDAP_PARAM_ERROR;
+ slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, &opresult);
+ return -1;
+ }
+
+ callback_handler_data.p_res_callback = prc;
+ callback_handler_data.p_srch_entry_callback = psec;
+ callback_handler_data.p_ref_entry_callback = prec;
+ callback_handler_data.callback_data = callback_data;
+
+ slapi_pblock_get(pb, SLAPI_OPERATION, &op);
+ op->o_handler_data = (void *)&callback_handler_data;
+ op->o_result_handler = internal_res_callback;
+ op->o_search_entry_handler = internal_srch_entry_callback;
+ op->o_search_referral_handler = internal_ref_entry_callback;
+
+ filter = slapi_str2filter(ifstr ? (fstr = slapi_ch_strdup(ifstr)) : "");
+ if(scope == LDAP_SCOPE_BASE) filter->f_flags |= (SLAPI_FILTER_LDAPSUBENTRY | SLAPI_FILTER_TOMBSTONE);
+ if (NULL == filter)
+ {
+ send_ldap_result(pb, LDAP_FILTER_ERROR, NULL, NULL, 0, NULL);
+ rc = -1;
+ goto done;
+ }
+ filter_normalize(filter);
+
+ slapi_pblock_set(pb, SLAPI_SEARCH_FILTER, filter);
+ slapi_pblock_set(pb, SLAPI_REQCONTROLS, controls);
+
+ /* set actions taken to process the operation */
+ set_config_params (pb);
+
+ /* set parameters common for all internal operations */
+ set_common_params (pb);
+ {
+ int timelimit = -1;
+ int sizelimit = -1;
+ int deref = LDAP_DEREF_ALWAYS;
+ slapi_pblock_set(pb, SLAPI_SEARCH_DEREF, &deref);
+ slapi_pblock_set(pb, SLAPI_SEARCH_TIMELIMIT, &timelimit);
+ slapi_pblock_set(pb, SLAPI_SEARCH_SIZELIMIT, &sizelimit);
+ }
+
+ /* plugins which play with the search may
+ * change the search params may allocate
+ * memory so we need to keep track of
+ * changed base search strings
+ */
+ slapi_pblock_get(pb, SLAPI_SEARCH_TARGET, &original_base);
+
+ op_shared_search (pb, 1);
+
+ slapi_pblock_get(pb, SLAPI_SEARCH_TARGET, &new_base);
+ slapi_pblock_get(pb, SLAPI_SEARCH_FILTER, &filter);
+
+done:
+ slapi_ch_free((void **) & fstr);
+ if (filter != NULL)
+ {
+ slapi_filter_free(filter, 1 /* recurse */);
+ }
+
+ if(original_base != new_base)
+ slapi_ch_free((void**)new_base);
+
+ return(rc);
+}
+
+/* allow/disallow operation based of the plugin configuration */
+PRBool allow_operation (Slapi_PBlock *pb)
+{
+ char *dn = NULL;
+ struct slapdplugin *plugin = NULL;
+ Slapi_DN sdn;
+ PRBool allow;
+ struct slapi_componentid * cid=NULL;
+
+ PR_ASSERT (pb);
+
+ /* make sure that users of new API provide plugin identity */
+ slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &cid);
+ if (cid == NULL)
+ {
+ slapi_log_error( SLAPI_LOG_FATAL, NULL, "allow_operation: component identity is NULL\n");
+ return PR_FALSE;
+ }
+ plugin=(struct slapdplugin *) cid->sci_plugin;
+ if (plugin == NULL)
+ {
+ slapi_log_error( SLAPI_LOG_FATAL, NULL, "allow_operation: plugin identity is NULL\n");
+ return PR_FALSE;
+ }
+
+ slapi_pblock_get (pb, SLAPI_TARGET_DN, &dn);
+ if (dn == NULL) {
+ slapi_sdn_init_dn_byval(&sdn,"");
+ } else {
+ slapi_sdn_init_dn_byval(&sdn, dn);
+ }
+
+ allow = plugin_allow_internal_op (&sdn, plugin);
+
+ slapi_sdn_done (&sdn);
+
+ return allow;
+}
+
+/* set operation configuration based on the plugin configuration */
+void set_config_params (Slapi_PBlock *pb)
+{
+ Slapi_Operation *operation;
+ struct slapdplugin *plugin = NULL;
+ char *dn;
+ struct slapi_componentid * cid=NULL;
+
+ slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &cid);
+ if (cid)
+ plugin=(struct slapdplugin *) cid->sci_plugin;
+
+ /* set actions */
+ slapi_pblock_get( pb, SLAPI_OPERATION, &operation);
+ operation_set_flag(operation,plugin_build_operation_action_bitmap(operation->o_flags, plugin));
+
+ /* Check if we have a flag to keep the operation secret */
+ if (operation_is_flag_set(operation, OP_FLAG_ACTION_NOLOG)) {
+ /* Clear the LOG_AUDIT and LOG_CHANGES flag */
+ 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);
+}
+
+/* set parameters common for all internal operations */
+void set_common_params (Slapi_PBlock *pb)
+{
+ int isroot = 1;
+ LDAPControl **controls;
+
+ slapi_pblock_get(pb, SLAPI_CONTROLS_ARG, &controls);
+
+ if (NULL != controls)
+ {
+ int managedsait = slapi_control_present(controls,
+ LDAP_CONTROL_MANAGEDSAIT, NULL, NULL);
+ int pwpolicy_ctrl = slapi_control_present(controls,
+ LDAP_X_CONTROL_PWPOLICY_REQUEST, NULL, NULL);
+
+ slapi_pblock_set(pb, SLAPI_MANAGEDSAIT, &managedsait);
+ slapi_pblock_set(pb, SLAPI_PWPOLICY, &pwpolicy_ctrl);
+ }
+
+ slapi_pblock_set(pb, SLAPI_REQUESTOR_ISROOT, &isroot);
+}
+
+
+/*
+ * Given a DN, find an entry by doing an internal search. An LDAP error
+ * code is returned.
+ */
+int
+slapi_search_internal_get_entry( Slapi_DN *dn, char ** attrs, Slapi_Entry **ret_entry , void * component_identity)
+{
+ Slapi_Entry **entries = NULL;
+ Slapi_PBlock *int_search_pb = NULL;
+ int rc = 0;
+
+ *ret_entry = NULL;
+ int_search_pb = slapi_pblock_new ();
+ slapi_search_internal_set_pb ( int_search_pb, slapi_sdn_get_dn(dn), LDAP_SCOPE_BASE, "(|(objectclass=*)(objectclass=ldapsubentry))",
+ attrs ,
+ 0 /* attrsonly */, NULL /* controls */,
+ NULL /* uniqueid */,
+ component_identity, 0 /* actions */ );
+ slapi_search_internal_pb ( int_search_pb );
+ slapi_pblock_get( int_search_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc );
+ if ( LDAP_SUCCESS == rc ) {
+ slapi_pblock_get( int_search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries );
+ if ( NULL != entries && NULL != entries[ 0 ]) {
+ Slapi_Entry *temp_entry = NULL;
+ temp_entry = entries[ 0 ];
+ *ret_entry = slapi_entry_dup(temp_entry);
+ } else {
+ /* No entry there */
+ rc = LDAP_NO_SUCH_OBJECT;
+ }
+ }
+ slapi_free_search_results_internal(int_search_pb);
+ slapi_pblock_destroy(int_search_pb);
+ int_search_pb = NULL;
+ return rc;
+}