]> git.sur5r.net Git - openldap/blob - servers/slapd/slapi/slapi_ops.c
839d5c20c1f9b8af95dfb928633ac9d58981c167
[openldap] / servers / slapd / slapi / slapi_ops.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2002-2005 The OpenLDAP Foundation.
5  * Portions Copyright 1997,2002-2003 IBM Corporation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16 /* ACKNOWLEDGEMENTS:
17  * This work was initially developed by IBM Corporation for use in
18  * IBM products and subsequently ported to OpenLDAP Software by
19  * Steve Omrani.  Additional significant contributors include:
20  *   Luke Howard
21  */
22
23 #include "portable.h"
24
25 #include <ac/string.h>
26 #include <ac/stdarg.h>
27 #include <ac/ctype.h>
28 #include <ac/unistd.h>
29
30 #include <slap.h>
31 #include <lber_pvt.h>
32 #include <slapi.h>
33
34 /*
35  * use a fake listener when faking a connection,
36  * so it can be used in ACLs
37  */
38 static struct slap_listener slap_unknown_listener = {
39         BER_BVC("unknown"),     /* FIXME: use a URI form? (e.g. slapi://) */
40         BER_BVC("UNKNOWN")
41 };
42
43 struct slapi_internal_args {
44         Slapi_PBlock *pb;
45         void *callback_data;
46         plugin_result_callback result_callback;
47         plugin_search_entry_callback search_entry_callback;
48         plugin_referral_entry_callback referral_entry_callback;
49 };
50
51 static void
52 slapi_int_send_ldap_result_shim(
53         Operation       *op, 
54         SlapReply       *rs )
55 {
56         struct slapi_internal_args *args;
57
58         args = (struct slapi_internal_args *)op->o_pb;
59         if ( args != NULL && args->result_callback != NULL ) {
60                 (args->result_callback)( rs->sr_err, args->callback_data );
61         }
62
63         return;
64 }
65
66 static int
67 slapi_int_send_search_entry_shim(
68         Operation       *op,
69         SlapReply       *rs )
70 {
71         struct slapi_internal_args *args;
72
73         args = (struct slapi_internal_args *)op->o_pb;
74         if ( args != NULL && args->search_entry_callback != NULL ) {
75                 return (args->search_entry_callback)( rs->sr_entry, args->callback_data );
76         }
77
78         return LDAP_SUCCESS;
79 }
80
81 static void
82 slapi_int_send_ldap_extended_shim(
83         Operation       *op,    
84         SlapReply       *rs )
85 {
86         return;
87 }
88
89 static int
90 slapi_int_send_search_reference_shim(
91         Operation       *op,    
92         SlapReply       *rs )
93 {
94         int i, rc = LDAP_SUCCESS;
95         struct slapi_internal_args *args;
96
97         args = (struct slapi_internal_args *)op->o_pb;
98         if ( args != NULL && args->referral_entry_callback != NULL ) {
99                 for ( i = 0; rs->sr_ref[i].bv_val != NULL; i++ ) {
100                         rc = (args->referral_entry_callback)( rs->sr_ref[i].bv_val, args->callback_data );
101                         if ( rc != LDAP_SUCCESS ) {
102                                 break;
103                         }
104                 }
105         }
106
107         return rc;
108 }
109
110 Connection *
111 slapi_int_init_connection(
112         char *DN, 
113         int OpType ) 
114
115         Connection *pConn;
116         Operation *op;
117         ber_len_t max = sockbuf_max_incoming;
118
119         pConn = (Connection *) slapi_ch_calloc(1, sizeof(Connection));
120
121         LDAP_STAILQ_INIT( &pConn->c_pending_ops );
122
123         op = (Operation *) slapi_ch_calloc( 1, OPERATION_BUFFER_SIZE );
124         op->o_hdr = (Opheader *)(op + 1);
125         op->o_controls = (void **)(op->o_hdr + 1);
126
127         pConn->c_pending_ops.stqh_first = op;
128         pConn->c_pending_ops.stqh_first->o_pb = NULL;
129         pConn->c_pending_ops.stqh_first->o_extensions = NULL;
130
131         /* connection object */
132         pConn->c_authmech.bv_val = NULL;
133         pConn->c_authmech.bv_len = 0;
134         pConn->c_dn.bv_val = NULL;
135         pConn->c_dn.bv_len = 0;
136         pConn->c_ndn.bv_val = NULL;
137         pConn->c_ndn.bv_len = 0;
138
139         pConn->c_listener = &slap_unknown_listener;
140         ber_dupbv( &pConn->c_peer_domain, (struct berval *)&slap_unknown_bv );
141         ber_dupbv( &pConn->c_peer_name, (struct berval *)&slap_unknown_bv );
142
143         LDAP_STAILQ_INIT( &pConn->c_ops );
144
145         pConn->c_sasl_bind_mech.bv_val = NULL;
146         pConn->c_sasl_bind_mech.bv_len = 0;
147         pConn->c_sasl_authctx = NULL;
148         pConn->c_sasl_sockctx = NULL;
149         pConn->c_sasl_extra = NULL;
150
151         pConn->c_sb = ber_sockbuf_alloc( );
152
153         ber_sockbuf_ctrl( pConn->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
154
155         pConn->c_currentber = NULL;
156
157         /* should check status of thread calls */
158         ldap_pvt_thread_mutex_init( &pConn->c_mutex );
159         ldap_pvt_thread_mutex_init( &pConn->c_write_mutex );
160         ldap_pvt_thread_cond_init( &pConn->c_write_cv );
161
162         ldap_pvt_thread_mutex_lock( &pConn->c_mutex );
163
164         pConn->c_n_ops_received = 0;
165         pConn->c_n_ops_executing = 0;
166         pConn->c_n_ops_pending = 0;
167         pConn->c_n_ops_completed = 0;
168
169         pConn->c_n_get = 0;
170         pConn->c_n_read = 0;
171         pConn->c_n_write = 0;
172
173         pConn->c_protocol = LDAP_VERSION3; 
174
175         pConn->c_activitytime = pConn->c_starttime = slap_get_time();
176
177         /*
178          * A real connection ID is required, because syncrepl associates
179          * pending CSNs with unique ( connection, operation ) tuples.
180          * Setting a fake connection ID will cause slap_get_commit_csn()
181          * to return a stale value.
182          */
183         connection_assign_nextid( pConn );
184
185         pConn->c_conn_state  = 0x01;    /* SLAP_C_ACTIVE */
186         pConn->c_struct_state = 0x02;   /* SLAP_C_USED */
187
188         pConn->c_ssf = pConn->c_transport_ssf = 0;
189         pConn->c_tls_ssf = 0;
190
191         backend_connection_init( pConn );
192
193         pConn->c_send_ldap_result = slapi_int_send_ldap_result_shim;
194         pConn->c_send_search_entry = slapi_int_send_search_entry_shim;
195         pConn->c_send_ldap_extended = slapi_int_send_ldap_extended_shim;
196         pConn->c_send_search_reference = slapi_int_send_search_reference_shim;
197
198         /* operation object */
199         pConn->c_pending_ops.stqh_first->o_tag = OpType;
200         pConn->c_pending_ops.stqh_first->o_protocol = LDAP_VERSION3; 
201         pConn->c_pending_ops.stqh_first->o_authmech.bv_val = NULL; 
202         pConn->c_pending_ops.stqh_first->o_authmech.bv_len = 0; 
203         pConn->c_pending_ops.stqh_first->o_time = slap_get_time();
204         pConn->c_pending_ops.stqh_first->o_do_not_cache = 1;
205         pConn->c_pending_ops.stqh_first->o_threadctx = ldap_pvt_thread_pool_context();
206         pConn->c_pending_ops.stqh_first->o_tmpmemctx = NULL;
207         pConn->c_pending_ops.stqh_first->o_tmpmfuncs = &ch_mfuncs;
208         pConn->c_pending_ops.stqh_first->o_conn = pConn;
209         pConn->c_pending_ops.stqh_first->o_connid = pConn->c_connid;
210
211         ldap_pvt_thread_mutex_unlock( &pConn->c_mutex );
212
213         return pConn;
214 }
215
216 void slapi_int_connection_destroy( Connection **pConn )
217 {
218         Connection *conn = *pConn;
219         Operation *op;
220
221         if ( pConn == NULL ) {
222                 return;
223         }
224
225         op = (Operation *)conn->c_pending_ops.stqh_first;
226
227         slap_graduate_commit_csn( op );
228
229         if ( op->o_req_dn.bv_val != NULL ) {
230                 slapi_ch_free( (void **)&op->o_req_dn.bv_val );
231         }
232         if ( op->o_req_ndn.bv_val != NULL ) {
233                 slapi_ch_free( (void **)&op->o_req_ndn.bv_val );
234         }
235
236         if ( conn->c_sb != NULL ) {
237                 ber_sockbuf_free( conn->c_sb );
238         }
239         if ( op != NULL ) {
240                 slapi_ch_free( (void **)&op );
241         }
242         slapi_ch_free( (void **)pConn );
243 }
244
245 /*
246  * Function : values2obj
247  * Convert an array of strings into a BerVarray.
248  * the strings.
249  */
250 static int
251 values2obj_copy(
252         char **ppValue,
253         BerVarray *bvobj )
254 {
255         int i;
256         BerVarray tmpberval;
257
258         if ( ppValue == NULL ) {
259                 *bvobj = NULL;
260                 return LDAP_SUCCESS;
261         }
262
263         for ( i = 0; ppValue[i] != NULL; i++ )
264                 ; /* EMPTY */
265
266         tmpberval = (BerVarray)slapi_ch_malloc( (i+1) * (sizeof(struct berval)) );
267         if ( tmpberval == NULL ) {
268                 return LDAP_NO_MEMORY;
269         }
270         for ( i = 0; ppValue[i] != NULL; i++ ) {
271                 size_t len = strlen( ppValue[i] );
272
273                 tmpberval[i].bv_val = slapi_ch_malloc( len + 1 );
274                 AC_MEMCPY( tmpberval[i].bv_val, ppValue[i], len + 1 );
275                 tmpberval[i].bv_len = len;
276         }
277         tmpberval[i].bv_val = NULL;
278         tmpberval[i].bv_len = 0;
279
280         *bvobj = tmpberval;
281
282         return LDAP_SUCCESS;
283 }
284
285 static int
286 bvptr2obj_copy(
287         struct berval   **bvptr, 
288         BerVarray       *bvobj )
289 {
290         int             i;
291         BerVarray       tmpberval;
292
293         if ( bvptr == NULL ) {
294                 *bvobj = NULL;
295                 return LDAP_SUCCESS;
296         }
297
298         for ( i = 0; bvptr[i] != NULL; i++ )
299                 ; /* EMPTY */
300
301         tmpberval = (BerVarray)slapi_ch_malloc( (i + 1) * sizeof(struct berval));
302         if ( tmpberval == NULL ) {
303                 return LDAP_NO_MEMORY;
304         } 
305
306         for ( i = 0; bvptr[i] != NULL; i++ ) {
307                 tmpberval[i].bv_val = slapi_ch_malloc( bvptr[i]->bv_len );
308                 tmpberval[i].bv_len = bvptr[i]->bv_len;
309                 AC_MEMCPY( tmpberval[i].bv_val, bvptr[i]->bv_val, bvptr[i]->bv_len );
310         }
311
312         tmpberval[i].bv_val = NULL;
313         tmpberval[i].bv_len = 0;
314
315         *bvobj = tmpberval;
316
317         return LDAP_SUCCESS;
318 }
319
320 /*
321  * Function : slapi_int_ldapmod_to_entry 
322  * convert a dn plus an array of LDAPMod struct ptrs to an entry structure
323  * with a link list of the correspondent attributes.
324  * Return value : LDAP_SUCCESS
325  *                LDAP_NO_MEMORY
326  *                LDAP_OTHER
327 */
328 static Entry *
329 slapi_int_ldapmod_to_entry(
330         Connection *pConn,
331         char *ldn, 
332         LDAPMod **mods )
333 {
334         struct berval           dn = BER_BVNULL;
335         Entry                   *pEntry=NULL;
336         LDAPMod                 *pMod;
337         struct berval           *bv;
338         Operation               *op;
339
340         Modifications           *modlist = NULL;
341         Modifications           **modtail = &modlist;
342         Modifications           tmp;
343
344         int                     rc = LDAP_SUCCESS;
345         int                     i;
346
347         const char              *text = NULL;
348
349         op = (Operation *)pConn->c_pending_ops.stqh_first;
350
351         pEntry = (Entry *) ch_calloc( 1, sizeof(Entry) );
352         if ( pEntry == NULL) {
353                 rc = LDAP_NO_MEMORY;
354                 goto cleanup;
355         } 
356
357         dn.bv_val = ldn;
358         dn.bv_len = strlen(ldn);
359
360         rc = dnPrettyNormal( NULL, &dn, &pEntry->e_name, &pEntry->e_nname, NULL );
361         if ( rc != LDAP_SUCCESS ) {
362                 goto cleanup;
363         }
364
365         if ( rc == LDAP_SUCCESS ) {
366                 for ( i = 0, pMod = mods[0]; rc == LDAP_SUCCESS && pMod != NULL; pMod = mods[++i]) {
367                         Modifications *mod;
368
369                         if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {
370                                 /*
371                                  * Convert an array of pointers to bervals to
372                                  * an array of bervals. Note that we need to copy the
373                                  * values too, as the slap_mods_check() will free the
374                                  * original values after prettying; the modifications
375                                  * being passed in may not have been allocated on the
376                                  * heap.
377                                  */
378                                 rc = bvptr2obj_copy( pMod->mod_bvalues, &bv );
379                                 if ( rc != LDAP_SUCCESS ) goto cleanup;
380                                 tmp.sml_type.bv_val = pMod->mod_type;
381                                 tmp.sml_type.bv_len = strlen( pMod->mod_type );
382                                 tmp.sml_values = bv;
383                                 tmp.sml_nvalues = NULL;
384                 
385                                 mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
386
387                                 mod->sml_op = LDAP_MOD_ADD;
388                                 mod->sml_flags = 0;
389                                 mod->sml_next = NULL;
390                                 mod->sml_desc = NULL;
391                                 mod->sml_type = tmp.sml_type;
392                                 mod->sml_values = tmp.sml_values;
393                                 mod->sml_nvalues = tmp.sml_nvalues;
394
395                                 *modtail = mod;
396                                 modtail = &mod->sml_next;
397
398                         } else {
399                                 /* attr values are in string format, need to be converted */
400                                 /* to an array of bervals */ 
401                                 if ( pMod->mod_values == NULL ) {
402                                         rc = LDAP_OTHER;
403                                 } else {
404                                         rc = values2obj_copy( pMod->mod_values, &bv );
405                                         if ( rc != LDAP_SUCCESS ) goto cleanup;
406                                         tmp.sml_type.bv_val = pMod->mod_type;
407                                         tmp.sml_type.bv_len = strlen( pMod->mod_type );
408                                         tmp.sml_values = bv;
409                                         tmp.sml_nvalues = NULL;
410                 
411                                         mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
412
413                                         mod->sml_op = LDAP_MOD_ADD;
414                                         mod->sml_flags = 0;
415                                         mod->sml_next = NULL;
416                                         mod->sml_desc = NULL;
417                                         mod->sml_type = tmp.sml_type;
418                                         mod->sml_values = tmp.sml_values;
419                                         mod->sml_nvalues = tmp.sml_nvalues;
420
421                                         *modtail = mod;
422                                         modtail = &mod->sml_next;
423                                 }
424                         }
425                 } /* for each LDAPMod */
426         }
427
428         op->o_bd = select_backend( &pEntry->e_nname, 0, 0 );
429         if ( op->o_bd == NULL ) {
430                 rc = LDAP_PARTIAL_RESULTS;
431         } else {
432                 int repl_user = be_isupdate_dn( op->o_bd, &op->o_bd->be_rootdn );
433                 if ( !op->o_bd->be_update_ndn.bv_len || repl_user ) {
434                         int     update = !BER_BVISNULL( &op->o_bd->be_update_ndn );
435                         char    textbuf[ SLAP_TEXT_BUFLEN ];
436                         size_t  textlen = sizeof( textbuf );
437
438                         rc = slap_mods_check( modlist, &text, 
439                                 textbuf, textlen, NULL );
440
441                         if ( rc != LDAP_SUCCESS) {
442                                 goto cleanup;
443                         }
444
445                         if ( !update ) {
446                                 rc = slap_mods_no_user_mod_check( op, modlist,
447                                         &text, textbuf, textlen );
448                                 if ( rc != LDAP_SUCCESS) {
449                                         goto cleanup;
450                                 }
451                         }
452
453                         if ( !repl_user ) {
454                                 rc = slap_mods_opattrs( op, modlist, modtail,
455                                         &text, textbuf, textlen, 1 );
456                                 if ( rc != LDAP_SUCCESS) {
457                                         goto cleanup;
458                                 }
459                         }
460
461                         rc = slap_mods2entry( modlist, &pEntry, repl_user,
462                                               0, &text, textbuf, textlen );
463                         if (rc != LDAP_SUCCESS) {
464                                 goto cleanup;
465                         }
466
467                 } else {
468                         rc = LDAP_REFERRAL;
469                 }
470         }
471
472 cleanup:;
473         if ( modlist != NULL )
474                 slap_mods_free( modlist );
475         if ( rc != LDAP_SUCCESS ) {
476                 if ( pEntry != NULL ) {
477                         slapi_entry_free( pEntry );
478                 }
479                 pEntry = NULL;
480         }
481
482         return( pEntry );
483 }
484
485 int
486 slapi_delete_internal_pb( Slapi_PBlock *pb )
487 {
488 #ifdef LDAP_SLAPI
489         Connection              *pConn = NULL;
490         Operation               *op = NULL;
491         SlapReply               rs = { REP_RESULT };
492         struct berval           dn = BER_BVNULL;
493         char                    *ldn = NULL;
494         LDAPControl             **controls = NULL;
495         int                     manageDsaIt = SLAP_CONTROL_NONE;
496         int                     operation_flags = 0;
497         int                     isCritical;
498
499         if ( pb == NULL ) {
500                 return -1;
501         }
502
503         slapi_pblock_get( pb, SLAPI_TARGET_DN, &ldn );
504         slapi_pblock_get( pb, SLAPI_REQCONTROLS, &controls );
505         slapi_pblock_get( pb, SLAPI_X_INTOP_FLAGS, &operation_flags );
506
507         if ( ldn == NULL ) {
508                 rs.sr_err = LDAP_PARAM_ERROR; 
509                 goto cleanup;
510         }
511
512         pConn = slapi_int_init_connection( NULL, LDAP_REQ_DELETE );
513         if (pConn == NULL) {
514                 rs.sr_err = LDAP_NO_MEMORY;
515                 goto cleanup;
516         }
517
518         op = (Operation *)pConn->c_pending_ops.stqh_first;
519         op->o_ctrls = controls;
520
521         dn.bv_val = ldn;
522         dn.bv_len = strlen(ldn);
523
524         rs.sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn, NULL );
525         if ( rs.sr_err != LDAP_SUCCESS )
526                 goto cleanup;
527
528         if ( slapi_control_present( controls, 
529                         SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical) ) {
530                 manageDsaIt = isCritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; 
531         }
532
533         op->o_bd = select_backend( &op->o_req_ndn, manageDsaIt, 1 );
534         if ( op->o_bd == NULL ) {
535                 rs.sr_err = LDAP_PARTIAL_RESULTS;
536                 goto cleanup;
537         }
538
539         op->o_dn = pConn->c_dn = op->o_bd->be_rootdn;
540         op->o_ndn = pConn->c_ndn = op->o_bd->be_rootndn;
541
542         if ( op->o_bd->be_delete ) {
543                 int repl_user = be_isupdate( op );
544                 if ( !op->o_bd->be_update_ndn.bv_len || repl_user ) {
545                         slap_callback cb = { NULL, slap_replog_cb, NULL, NULL };
546                         if ( operation_flags & SLAPI_OP_FLAG_LOG_CHANGE )
547                                 op->o_callback = &cb;
548
549                         op->o_bd->be_delete( op, &rs );
550                 } else {
551                         rs.sr_err = LDAP_REFERRAL;
552                 }
553         } else {
554                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
555         }
556
557 cleanup:
558         slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rs.sr_err );
559         slapi_pblock_set( pb, SLAPI_RESCONTROLS, (void *)rs.sr_ctrls );
560
561         slapi_int_connection_destroy( &pConn );
562
563         return 0;
564 #else
565         return -1;
566 #endif /* LDAP_SLAPI */
567 }
568
569 int
570 slapi_add_internal_pb( Slapi_PBlock *pb )
571 {
572 #ifdef LDAP_SLAPI
573         Connection              *pConn = NULL;
574         Slapi_Entry             *entry = NULL;
575         Slapi_Entry             *argEntry = NULL;
576         char                    *dn = NULL;
577         LDAPMod                 **mods = NULL;
578         LDAPControl             **controls = NULL;
579         int                     operation_flags = 0;
580         Operation               *op = NULL;
581
582         int                     manageDsaIt = SLAP_CONTROL_NONE;
583         int                     isCritical;
584         int                     freeEntry = 0;
585         int                     i;
586         SlapReply               rs = { REP_RESULT };
587
588         if ( pb == NULL ) {
589                 return -1;
590         }
591
592         pConn = slapi_int_init_connection( NULL, LDAP_REQ_ADD );
593         if ( pConn == NULL ) {
594                 rs.sr_err = LDAP_OTHER;
595                 goto cleanup;
596         }
597
598         slapi_pblock_get( pb, SLAPI_ADD_TARGET, &dn );
599         slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &argEntry );
600         slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
601         slapi_pblock_get( pb, SLAPI_REQCONTROLS, &controls );
602         slapi_pblock_get( pb, SLAPI_X_INTOP_FLAGS, &operation_flags );
603
604         if ( argEntry != NULL ) {
605                 entry = slapi_entry_dup( argEntry );
606                 dn = slapi_entry_get_dn( argEntry );
607         } else {
608                 if ( mods == NULL || dn == NULL ) {
609                         rs.sr_err = LDAP_PARAM_ERROR;
610                         goto cleanup;
611                 }
612
613                 for ( i = 0; mods[i] != NULL; i++ ) {
614                         if ( (mods[i]->mod_op & LDAP_MOD_OP ) != LDAP_MOD_ADD ) {
615                                 rs.sr_err = LDAP_OTHER;
616                                 goto cleanup;
617                         }
618                 }
619
620                 entry = slapi_int_ldapmod_to_entry( pConn, dn, mods );
621                 if ( entry == NULL ) {
622                         rs.sr_err = LDAP_OTHER;
623                         goto cleanup;
624                 }
625         }
626
627         if ( slapi_control_present( controls, LDAP_CONTROL_MANAGEDSAIT,
628                                 NULL, &isCritical ) ) {
629                 manageDsaIt = isCritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; 
630         }
631
632         op = (Operation *)pConn->c_pending_ops.stqh_first;
633         op->o_ctrls = controls;
634
635         op->o_bd = select_backend( &entry->e_nname, manageDsaIt, 1 );
636         if ( op->o_bd == NULL ) {
637                 rs.sr_err = LDAP_PARTIAL_RESULTS;
638                 goto cleanup;
639         }
640
641         op->o_dn = pConn->c_dn = op->o_bd->be_rootdn;
642         op->o_ndn = pConn->c_ndn = op->o_bd->be_rootndn;
643         op->oq_add.rs_e = entry;
644
645         if ( op->o_bd->be_add ) {
646                 int repl_user = be_isupdate( op );
647                 if ( !op->o_bd->be_update_ndn.bv_len || repl_user ) {
648                         slap_callback cb = { NULL, slap_replog_cb, NULL, NULL };
649
650                         if ( operation_flags & SLAPI_OP_FLAG_LOG_CHANGE )
651                                 op->o_callback = &cb;
652
653                         if ( op->o_bd->be_add( op, &rs ) == LDAP_SUCCESS ) {
654                                 be_entry_release_w( op, entry );
655                                 entry = NULL;
656                         }
657                 } else {
658                         rs.sr_err = LDAP_REFERRAL;
659                 }
660         } else {
661                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
662         }
663
664 cleanup:
665         slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rs.sr_err );
666         slapi_pblock_set( pb, SLAPI_RESCONTROLS, (void *)rs.sr_ctrls );
667
668         if ( entry != NULL ) {
669                 slapi_entry_free( entry );
670         }
671
672         slapi_int_connection_destroy( &pConn );
673
674         return 0;
675 #else
676         return -1;
677 #endif /* LDAP_SLAPI */
678 }
679
680 int
681 slapi_modrdn_internal_pb( Slapi_PBlock *pb )
682 {
683 #ifdef LDAP_SLAPI
684         struct berval           dn = BER_BVNULL;
685         struct berval           newrdn = BER_BVNULL;
686         struct berval           newsupdn = BER_BVNULL;
687         struct berval           newSuperiorPretty = BER_BVNULL;
688         struct berval           newSuperiorNormalized = BER_BVNULL;
689         Connection              *pConn = NULL;
690         Operation               *op = NULL;
691         int                     manageDsaIt = SLAP_CONTROL_NONE;
692         int                     isCritical;
693         SlapReply               rs = { REP_RESULT };
694
695         char                    *olddn;
696         char                    *lnewrdn;
697         char                    *newsuperior;
698         int                     deloldrdn;
699         LDAPControl             **controls;
700         int                     operation_flags;
701
702         if ( pb == NULL ) {
703                 return -1;
704         }
705
706         slapi_pblock_get( pb, SLAPI_MODRDN_TARGET, &olddn );
707         slapi_pblock_get( pb, SLAPI_MODRDN_NEWRDN, &lnewrdn );
708         slapi_pblock_get( pb, SLAPI_MODRDN_NEWSUPERIOR, &newsuperior );
709         slapi_pblock_get( pb, SLAPI_MODRDN_DELOLDRDN, &deloldrdn );
710         slapi_pblock_get( pb, SLAPI_REQCONTROLS, &controls );
711 #if 0
712         slapi_pblock_get( pb, SLAPI_TARGET_UNIQUEID, uniqueid );
713         slapi_pblock_get( pb, SLAPI_PLUGIN_IDENTITY, plugin_identity );
714 #endif
715         slapi_pblock_get( pb, SLAPI_X_INTOP_FLAGS, &operation_flags );
716
717         pConn = slapi_int_init_connection( NULL, LDAP_REQ_MODRDN );
718         if ( pConn == NULL) {
719                 rs.sr_err = LDAP_NO_MEMORY;
720                 goto cleanup;
721         }
722
723         op = (Operation *)pConn->c_pending_ops.stqh_first;
724         op->o_ctrls = controls;
725
726         if ( slapi_control_present( controls, 
727                         SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical ) ) {
728                 manageDsaIt = isCritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; 
729         }
730
731         op->o_bd = select_backend( &op->o_req_ndn, manageDsaIt, 1 );
732         if ( op->o_bd == NULL ) {
733                 rs.sr_err =  LDAP_PARTIAL_RESULTS;
734                 goto cleanup;
735         }
736
737         op->o_dn = pConn->c_dn = op->o_bd->be_rootdn;
738         op->o_ndn = pConn->c_ndn = op->o_bd->be_rootndn;
739
740         dn.bv_val = (char *)olddn;
741         dn.bv_len = strlen( olddn );
742
743         rs.sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn, NULL );
744         if ( rs.sr_err != LDAP_SUCCESS ) {
745                 goto cleanup;
746         }
747
748         if ( op->o_req_dn.bv_len == 0 ) {
749                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
750                 goto cleanup;
751         }
752
753         newrdn.bv_val = (char *)lnewrdn;
754         newrdn.bv_len = strlen( lnewrdn );
755
756         rs.sr_err = dnPrettyNormal( NULL, &newrdn, &op->oq_modrdn.rs_newrdn, &op->oq_modrdn.rs_nnewrdn, NULL );
757         if ( rs.sr_err != LDAP_SUCCESS ) {
758                 goto cleanup;
759         }
760
761         if ( rdn_validate( &op->oq_modrdn.rs_nnewrdn ) != LDAP_SUCCESS ) {
762                 goto cleanup;
763         }
764
765         if ( newsuperior != NULL ) {
766                 newsupdn.bv_val = (char *)newsuperior;
767                 newsupdn.bv_len = strlen( newsuperior );
768
769                 rs.sr_err = dnPrettyNormal( NULL, &newsupdn, &newSuperiorPretty, &newSuperiorNormalized, NULL );
770                 if ( rs.sr_err != LDAP_SUCCESS )
771                         goto cleanup;
772
773                 op->oq_modrdn.rs_newSup = &newSuperiorPretty;
774                 op->oq_modrdn.rs_nnewSup = &newSuperiorNormalized;
775         } else {
776                 op->oq_modrdn.rs_newSup = NULL;
777                 op->oq_modrdn.rs_nnewSup = NULL;
778         }
779
780         op->oq_modrdn.rs_deleteoldrdn = deloldrdn;
781
782         if ( op->o_bd->be_modrdn ) {
783                 int repl_user = be_isupdate( op );
784                 if ( !op->o_bd->be_update_ndn.bv_len || repl_user ) {
785                         slap_callback cb = { NULL, slap_replog_cb, NULL, NULL };
786
787                         if ( operation_flags & SLAPI_OP_FLAG_LOG_CHANGE )
788                                 op->o_callback = &cb;
789
790                         op->o_bd->be_modrdn( op, &rs );
791                 } else {
792                         rs.sr_err = LDAP_REFERRAL;
793                 }
794         } else {
795                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
796         }
797
798 cleanup:
799
800         slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rs.sr_err );
801         slapi_pblock_set( pb, SLAPI_RESCONTROLS, (void *)rs.sr_ctrls );
802
803         if ( op->oq_modrdn.rs_newrdn.bv_val != NULL )
804                 slapi_ch_free( (void **)&op->oq_modrdn.rs_newrdn.bv_val );
805         if ( op->oq_modrdn.rs_nnewrdn.bv_val != NULL )
806                 slapi_ch_free( (void **)&op->oq_modrdn.rs_nnewrdn.bv_val );
807         if ( newSuperiorPretty.bv_val != NULL )
808                 slapi_ch_free( (void **)&newSuperiorPretty.bv_val );
809         if ( newSuperiorNormalized.bv_val != NULL )
810                 slapi_ch_free( (void **)&newSuperiorNormalized.bv_val );
811
812         slapi_int_connection_destroy( &pConn );
813
814         return 0;
815 #else
816         return -1;
817 #endif /* LDAP_SLAPI */
818 }
819
820 int slapi_modify_internal_pb( Slapi_PBlock *pb )
821 {
822 #ifdef LDAP_SLAPI
823         int                     i;
824         Connection              *pConn = NULL;
825         Operation               *op = NULL;
826
827         struct berval dn = BER_BVNULL;
828
829         int                     manageDsaIt = SLAP_CONTROL_NONE;
830         int                     isCritical;
831         struct berval           *bv;
832         LDAPMod                 *pMod;
833
834         Modifications           *modlist = NULL;
835         Modifications           **modtail = &modlist;
836         Modifications           tmp;
837
838         SlapReply               rs = { REP_RESULT };
839
840         char                    *ldn = NULL;
841         LDAPMod                 **mods = NULL;
842         LDAPControl             **controls = NULL;
843         int                     operation_flags = 0;
844
845         if ( pb == NULL ) {
846                 return -1;
847         }
848
849         slapi_pblock_get( pb, SLAPI_MODIFY_TARGET, &ldn );
850         slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
851         slapi_pblock_get( pb, SLAPI_REQCONTROLS, &controls );
852 #if 0
853         slapi_pblock_get( pb, SLAPI_TARGET_UNIQUEID, uniqueid );
854         slapi_pblock_get( pb, SLAPI_PLUGIN_IDENTITY, plugin_identity );
855 #endif
856         slapi_pblock_get( pb, SLAPI_X_INTOP_FLAGS, &operation_flags );
857
858         if ( mods == NULL || *mods == NULL || ldn == NULL ) {
859                 rs.sr_err = LDAP_PARAM_ERROR ;
860                 goto cleanup;
861         }
862
863         pConn = slapi_int_init_connection( NULL,  LDAP_REQ_MODIFY );
864         if ( pConn == NULL ) {
865                 rs.sr_err = LDAP_NO_MEMORY;
866                 goto cleanup;
867         }
868
869         op = (Operation *)pConn->c_pending_ops.stqh_first;
870         op->o_ctrls = controls;
871
872         dn.bv_val = ldn;
873         dn.bv_len = strlen( ldn );
874
875         rs.sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn, NULL );
876         if ( rs.sr_err != LDAP_SUCCESS ) {
877                 goto cleanup;
878         }
879
880         if ( slapi_control_present( controls, 
881                         SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical ) ) {
882                 manageDsaIt = isCritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; 
883         }
884
885         op->o_bd = select_backend( &op->o_req_ndn, manageDsaIt, 1 );
886         if ( op->o_bd == NULL ) {
887                 rs.sr_err = LDAP_PARTIAL_RESULTS;
888                 goto cleanup;
889         }
890
891         op->o_dn = pConn->c_dn = op->o_bd->be_rootdn;
892         op->o_ndn = pConn->c_ndn = op->o_bd->be_rootndn;
893
894         for ( i = 0, pMod = mods[0];
895                 rs.sr_err == LDAP_SUCCESS && pMod != NULL; 
896                 pMod = mods[++i] )
897         {
898                 Modifications *mod;
899
900                 if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {
901                         /*
902                          * attr values are in berval format
903                          * convert an array of pointers to bervals
904                          * to an array of bervals
905                          */
906                         rs.sr_err = bvptr2obj_copy( pMod->mod_bvalues, &bv );
907                         if ( rs.sr_err != LDAP_SUCCESS )
908                                 goto cleanup;
909                         tmp.sml_type.bv_val = pMod->mod_type;
910                         tmp.sml_type.bv_len = strlen( pMod->mod_type );
911                         tmp.sml_values = bv;
912                         tmp.sml_nvalues = NULL;
913
914                         mod  = (Modifications *)ch_malloc( sizeof(Modifications) );
915
916                         mod->sml_op = pMod->mod_op & LDAP_MOD_OP;
917                         mod->sml_flags = 0;
918                         mod->sml_next = NULL;
919                         mod->sml_desc = NULL;
920                         mod->sml_type = tmp.sml_type;
921                         mod->sml_values = tmp.sml_values;
922                         mod->sml_nvalues = tmp.sml_nvalues;
923                 } else { 
924                         rs.sr_err = values2obj_copy( pMod->mod_values, &bv );
925                         if ( rs.sr_err != LDAP_SUCCESS )
926                                 goto cleanup;
927                         tmp.sml_type.bv_val = pMod->mod_type;
928                         tmp.sml_type.bv_len = strlen( pMod->mod_type );
929                         tmp.sml_values = bv;
930                         tmp.sml_nvalues = NULL;
931
932                         mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
933
934                         mod->sml_op = pMod->mod_op & LDAP_MOD_OP;
935                         mod->sml_flags = 0;
936                         mod->sml_next = NULL;
937                         mod->sml_desc = NULL;
938                         mod->sml_type = tmp.sml_type;
939                         mod->sml_values = tmp.sml_values;
940                         mod->sml_nvalues = tmp.sml_nvalues;
941                 }
942                 *modtail = mod;
943                 modtail = &mod->sml_next;
944
945                 switch( pMod->mod_op & LDAP_MOD_OP ) {
946                 case LDAP_MOD_ADD:
947                 if ( mod->sml_values == NULL ) {
948                         rs.sr_err = LDAP_PROTOCOL_ERROR;
949                         goto cleanup;
950                 }
951
952                 /* fall through */
953                 case LDAP_MOD_DELETE:
954                 case LDAP_MOD_REPLACE:
955                 case LDAP_MOD_INCREMENT:
956                 break;
957
958                 default:
959                         rs.sr_err = LDAP_PROTOCOL_ERROR;
960                         goto cleanup;
961                 }
962         } 
963         *modtail = NULL;
964
965         if ( op->o_req_ndn.bv_len == 0 ) {
966                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
967                 goto cleanup;
968         }
969
970         op->oq_modify.rs_modlist = modlist;
971
972         if ( op->o_bd->be_modify ) {
973                 int repl_user = be_isupdate( op );
974                 if ( !op->o_bd->be_update_ndn.bv_len || repl_user ) {
975                         int             update = !BER_BVISEMPTY( &op->o_bd->be_update_ndn );
976                         const char      *text = NULL;
977                         char            textbuf[ SLAP_TEXT_BUFLEN ];
978                         size_t          textlen = sizeof( textbuf );
979                         slap_callback   cb = { NULL, slap_replog_cb, NULL, NULL };
980
981                         rs.sr_err = slap_mods_check( modlist,
982                                 &text, textbuf, textlen, NULL );
983                         if ( rs.sr_err != LDAP_SUCCESS ) {
984                                 goto cleanup;
985                         }
986
987                         if ( !update ) {
988                                 rs.sr_err = slap_mods_no_user_mod_check( op, modlist,
989                                         &text, textbuf, textlen );
990                                 if ( rs.sr_err != LDAP_SUCCESS ) {
991                                         goto cleanup;
992                                 }
993                         }
994
995                         if ( !repl_user ) {
996                                 rs.sr_err = slap_mods_opattrs( op, modlist,
997                                                 modtail, &text, textbuf, 
998                                                 textlen, 1 );
999                                 if ( rs.sr_err != LDAP_SUCCESS ) {
1000                                         goto cleanup;
1001                                 }
1002                         }
1003
1004                         if ( operation_flags & SLAPI_OP_FLAG_LOG_CHANGE )
1005                                 op->o_callback = &cb;
1006
1007                         op->o_bd->be_modify( op, &rs );
1008                 } else {
1009                         rs.sr_err = LDAP_REFERRAL;
1010                 }
1011         } else {
1012                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
1013         }
1014
1015 cleanup:
1016         slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rs.sr_err );
1017         slapi_pblock_set( pb, SLAPI_RESCONTROLS, (void *)rs.sr_ctrls );
1018
1019         if ( modlist != NULL )
1020                 slap_mods_free( modlist );
1021
1022         slapi_int_connection_destroy( &pConn );
1023
1024         return 0;
1025 #else
1026         return -1;
1027 #endif /* LDAP_SLAPI */
1028 }
1029
1030 #ifdef LDAP_SLAPI
1031 static int
1032 slapi_int_search_entry_callback( Slapi_Entry *entry, void *callback_data )
1033 {
1034         int nentries = 0, i = 0;
1035         Slapi_Entry **head = NULL, **tp;
1036         Slapi_PBlock *pb = (Slapi_PBlock *)callback_data;
1037
1038         entry = slapi_entry_dup( entry );
1039         if ( entry == NULL ) {
1040                 return 1;
1041         }
1042
1043         slapi_pblock_get( pb, SLAPI_NENTRIES, &nentries );
1044         slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &head );
1045         
1046         i = nentries + 1;
1047         if ( nentries == 0 ) {
1048                 tp = (Slapi_Entry **)slapi_ch_malloc( 2 * sizeof(Slapi_Entry *) );
1049                 if ( tp == NULL ) {
1050                         slapi_entry_free( entry );
1051                         return 1;
1052                 }
1053
1054                 tp[ 0 ] = entry;
1055         } else {
1056                 tp = (Slapi_Entry **)slapi_ch_realloc( (char *)head,
1057                                 sizeof(Slapi_Entry *) * ( i + 1 ) );
1058                 if ( tp == NULL ) {
1059                         slapi_entry_free( entry );
1060                         return 1;
1061                 }
1062                 tp[ i - 1 ] = entry;
1063         }
1064         tp[ i ] = NULL;
1065                   
1066         slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, (void *)tp );
1067         slapi_pblock_set( pb, SLAPI_NENTRIES, (void *)i );
1068
1069         return LDAP_SUCCESS;
1070 }
1071 #endif /* LDAP_SLAPI */
1072
1073 int slapi_search_internal_pb( Slapi_PBlock *pb )
1074 {
1075 #ifdef LDAP_SLAPI
1076         return slapi_search_internal_callback_pb( pb,
1077                 (void *)pb,
1078                 NULL,
1079                 slapi_int_search_entry_callback,
1080                 NULL );
1081 #else
1082         return -1;
1083 #endif
1084 }
1085
1086 int slapi_search_internal_callback_pb( Slapi_PBlock *pb,
1087         void *callback_data,
1088         plugin_result_callback prc,
1089         plugin_search_entry_callback psec,
1090         plugin_referral_entry_callback prec )
1091 {
1092 #ifdef LDAP_SLAPI
1093         Connection              *c;
1094         Operation               *op = NULL;
1095         struct berval           dn = BER_BVNULL;
1096         Filter                  *filter=NULL;
1097         struct berval           fstr = BER_BVNULL;
1098         AttributeName           *an = NULL;
1099         const char              *text = NULL;
1100         struct slapi_internal_args args;
1101
1102         int                     manageDsaIt = SLAP_CONTROL_NONE;
1103         int                     isCritical;
1104         int                     i;
1105
1106         char                    *ldn = NULL;
1107         int                     scope = LDAP_SCOPE_BASE;
1108         char                    *filStr = NULL;
1109         LDAPControl             **controls = NULL;
1110         char                    **attrs = NULL;
1111         char                    *uniqueid = NULL;
1112         int                     attrsonly = 0;
1113         int                     operation_flags = 0;
1114         int                     freeFilter = 0;
1115
1116         SlapReply               rs = { REP_RESULT };
1117
1118         if ( pb == NULL ) {
1119                 return -1;
1120         }
1121
1122         slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &ldn );
1123         slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope );
1124         slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter );
1125         slapi_pblock_get( pb, SLAPI_SEARCH_STRFILTER, &filStr );
1126         slapi_pblock_get( pb, SLAPI_SEARCH_ATTRS, &attrs );
1127         slapi_pblock_get( pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly );
1128         slapi_pblock_get( pb, SLAPI_REQCONTROLS, &controls );
1129         slapi_pblock_get( pb, SLAPI_TARGET_UNIQUEID, &uniqueid );
1130         slapi_pblock_get( pb, SLAPI_X_INTOP_FLAGS, &operation_flags );
1131
1132         args.pb = pb; /* args pointer can be safely cast to Slapi_PBlock */
1133         args.callback_data = callback_data;
1134         args.result_callback = prc;
1135         args.search_entry_callback = psec;
1136         args.referral_entry_callback = prec;
1137
1138         c = slapi_int_init_connection( NULL, LDAP_REQ_SEARCH );
1139         if ( c == NULL ) {
1140                 rs.sr_err = LDAP_NO_MEMORY;
1141                 goto cleanup;
1142         }
1143
1144         op = (Operation *)c->c_pending_ops.stqh_first;
1145         op->o_ctrls = controls;
1146         op->o_pb = (void *)&args;
1147
1148         if ( ldn != NULL ) {
1149                 dn.bv_val = ldn;
1150                 dn.bv_len = strlen(ldn);
1151         }
1152
1153         rs.sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn, NULL );
1154         if ( rs.sr_err != LDAP_SUCCESS ) {
1155                 goto cleanup;
1156         }
1157
1158         if ( scope != LDAP_SCOPE_BASE && 
1159              scope != LDAP_SCOPE_ONELEVEL && 
1160              scope != LDAP_SCOPE_SUBTREE ) {
1161                 rs.sr_err = LDAP_PROTOCOL_ERROR;
1162                 goto cleanup;
1163         }
1164
1165         if ( filter == NULL ) {
1166                 if ( filStr == NULL ) {
1167                         rs.sr_err = LDAP_PARAM_ERROR;
1168                         goto cleanup;
1169                 }
1170
1171                 filter = slapi_str2filter( filStr );
1172                 if ( filter == NULL ) {
1173                         rs.sr_err = LDAP_PROTOCOL_ERROR;
1174                         goto cleanup;
1175                 }
1176
1177                 freeFilter = 1;
1178         }
1179
1180         filter2bv( filter, &fstr );
1181
1182         for ( i = 0; attrs != NULL && attrs[i] != NULL; i++ ) {
1183                 ; /* count the number of attributes */
1184         }
1185
1186         if (i > 0) {
1187                 an = (AttributeName *)slapi_ch_calloc( (i + 1), sizeof(AttributeName) );
1188                 for (i = 0; attrs[i] != 0; i++) {
1189                         an[i].an_desc = NULL;
1190                         an[i].an_oc = NULL;
1191                         an[i].an_oc_exclude = 0;
1192                         an[i].an_name.bv_val = slapi_ch_strdup(attrs[i]);
1193                         an[i].an_name.bv_len = strlen(attrs[i]);
1194                         slap_bv2ad( &an[i].an_name, &an[i].an_desc, &text );
1195                 }
1196                 an[i].an_name.bv_val = NULL;
1197         }
1198
1199         memset( &rs, 0, sizeof(rs) );
1200         rs.sr_type = REP_RESULT;
1201         rs.sr_err = LDAP_SUCCESS;
1202         rs.sr_entry = NULL; /* paranoia */
1203
1204         if ( scope == LDAP_SCOPE_BASE ) {
1205                 rs.sr_entry = NULL;
1206
1207                 if ( op->o_req_ndn.bv_len == 0 ) {
1208                         rs.sr_err = root_dse_info( c, &rs.sr_entry, &rs.sr_text );
1209                 }
1210
1211                 if( rs.sr_err != LDAP_SUCCESS ) {
1212                         send_ldap_result( op, &rs );
1213                         goto cleanup;
1214                 } else if ( rs.sr_entry != NULL ) {
1215                         rs.sr_err = test_filter( op, rs.sr_entry, filter );
1216
1217                         if ( rs.sr_err == LDAP_COMPARE_TRUE ) {
1218                                 rs.sr_type = REP_SEARCH;
1219                                 rs.sr_err = LDAP_SUCCESS;
1220                                 rs.sr_attrs = an;
1221                                 rs.sr_operational_attrs = NULL;
1222                                 rs.sr_flags = REP_ENTRY_MODIFIABLE;
1223
1224                                 send_search_entry( op, &rs );
1225                         }
1226
1227                         entry_free( rs.sr_entry );
1228
1229                         rs.sr_type = REP_RESULT;
1230                         rs.sr_err = LDAP_SUCCESS;
1231
1232                         send_ldap_result( op, &rs );
1233
1234                         goto cleanup;
1235                 }
1236         }
1237
1238         if ( !op->o_req_ndn.bv_len && default_search_nbase.bv_len ) {
1239                 slapi_ch_free( (void **)&op->o_req_dn.bv_val );
1240                 slapi_ch_free( (void **)&op->o_req_ndn.bv_val );
1241
1242                 ber_dupbv( &op->o_req_dn, &default_search_base );
1243                 ber_dupbv( &op->o_req_ndn, &default_search_nbase );
1244         }
1245
1246         if ( slapi_control_present( controls,
1247                         LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) {
1248                 manageDsaIt = isCritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; 
1249         }
1250
1251         op->o_bd = select_backend( &op->o_req_ndn, manageDsaIt, 1 );
1252         if ( op->o_bd == NULL ) {
1253                 if ( manageDsaIt > SLAP_CONTROL_NONE ) {
1254                         rs.sr_err = LDAP_NO_SUCH_OBJECT;
1255                 } else {
1256                         rs.sr_err = LDAP_PARTIAL_RESULTS;
1257                 }
1258                 goto cleanup;
1259         } 
1260
1261         op->o_dn = c->c_dn = op->o_bd->be_rootdn;
1262         op->o_ndn = c->c_ndn = op->o_bd->be_rootndn;
1263
1264         op->oq_search.rs_scope = scope;
1265         op->oq_search.rs_deref = 0;
1266         op->oq_search.rs_slimit = SLAP_NO_LIMIT;
1267         op->oq_search.rs_tlimit = SLAP_NO_LIMIT;
1268         op->oq_search.rs_attrsonly = attrsonly;
1269         op->oq_search.rs_attrs = an;
1270         op->oq_search.rs_filter = filter;
1271         op->oq_search.rs_filterstr = fstr;
1272
1273         if ( op->o_bd->be_search != NULL ) {
1274                 (*op->o_bd->be_search)( op, &rs );
1275         } else {
1276                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
1277         }
1278
1279 cleanup:
1280         slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rs.sr_err );
1281         slapi_pblock_set( pb, SLAPI_RESCONTROLS, (void *)rs.sr_ctrls );
1282
1283         if ( freeFilter && filter != NULL )
1284                 slapi_filter_free( filter, 1 );
1285         if ( fstr.bv_val )
1286                 slapi_ch_free( (void **)&fstr.bv_val );
1287         if ( an != NULL )
1288                 slapi_ch_free( (void **)&an );
1289
1290         slapi_int_connection_destroy( &c );
1291
1292         return 0;
1293 #else
1294         return -1;
1295 #endif /* LDAP_SLAPI */
1296 }
1297
1298 /* Wrappers for old API */
1299
1300 void slapi_search_internal_set_pb( Slapi_PBlock *pb,
1301         const char *base,
1302         int scope,
1303         const char *filter,
1304         char **attrs,
1305         int attrsonly,
1306         LDAPControl **controls,
1307         const char *uniqueid,
1308         Slapi_ComponentId *plugin_identity,
1309         int operation_flags )
1310 {
1311 #ifdef LDAP_SLAPI
1312         slapi_pblock_set( pb, SLAPI_SEARCH_TARGET, (void *)base );
1313         slapi_pblock_set( pb, SLAPI_SEARCH_SCOPE, (void *)scope );
1314         slapi_pblock_set( pb, SLAPI_SEARCH_FILTER, NULL );
1315         slapi_pblock_set( pb, SLAPI_SEARCH_STRFILTER, (void *)filter );
1316         slapi_pblock_set( pb, SLAPI_SEARCH_ATTRS, (void *)attrs );
1317         slapi_pblock_set( pb, SLAPI_SEARCH_ATTRSONLY, (void *)attrsonly );
1318         slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)controls );
1319         slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID, (void *)uniqueid );
1320         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
1321         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS, (void *)operation_flags );
1322 #endif /* LDAP_SLAPI */
1323 }
1324
1325 Slapi_PBlock *
1326 slapi_search_internal(
1327         char *ldn, 
1328         int scope, 
1329         char *filStr, 
1330         LDAPControl **controls, 
1331         char **attrs, 
1332         int attrsonly ) 
1333 {
1334 #ifdef LDAP_SLAPI
1335         Slapi_PBlock *pb;
1336
1337         pb = slapi_pblock_new();
1338         if ( pb == NULL ) {
1339                 return NULL;
1340         }
1341
1342         slapi_search_internal_set_pb( pb, ldn, scope, filStr, attrs, attrsonly,
1343                 controls, NULL, NULL, 0 );
1344
1345         slapi_search_internal_pb( pb );
1346
1347         return pb;
1348 #else
1349         return NULL;
1350 #endif /* LDAP_SLAPI */
1351 }
1352
1353 void slapi_modify_internal_set_pb( Slapi_PBlock *pb,
1354         const char *dn,
1355         LDAPMod **mods,
1356         LDAPControl **controls,
1357         const char *uniqueid,
1358         Slapi_ComponentId *plugin_identity,
1359         int operation_flags )
1360 {
1361 #ifdef LDAP_SLAPI
1362         slapi_pblock_set( pb, SLAPI_MODIFY_TARGET, (void *)dn );
1363         slapi_pblock_set( pb, SLAPI_MODIFY_MODS, (void *)mods );
1364         slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)controls );
1365         slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID, (void *)uniqueid );
1366         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
1367         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS, (void *)operation_flags );
1368 #endif /* LDAP_SLAPI */
1369 }
1370
1371 /* Function : slapi_modify_internal
1372  *
1373  * Description: Plugin functions call this routine to modify an entry 
1374  *                              in the backend directly
1375  * Return values : LDAP_SUCCESS
1376  *                 LDAP_PARAM_ERROR
1377  *                 LDAP_NO_MEMORY
1378  *                 LDAP_OTHER
1379  *                 LDAP_UNWILLING_TO_PERFORM
1380 */
1381 Slapi_PBlock *
1382 slapi_modify_internal(
1383         char *ldn,      
1384         LDAPMod **mods, 
1385         LDAPControl **controls, 
1386         int log_change )
1387 {
1388 #ifdef LDAP_SLAPI
1389         Slapi_PBlock *pb;
1390
1391         pb = slapi_pblock_new();
1392         if ( pb == NULL ) {
1393                 return NULL;
1394         }
1395
1396         slapi_modify_internal_set_pb( pb, ldn, mods, controls, NULL, NULL,
1397                 log_change ? SLAPI_OP_FLAG_LOG_CHANGE : 0 );
1398
1399         slapi_modify_internal_pb( pb );
1400
1401         return pb;
1402 #else
1403         return NULL;
1404 #endif /* LDAP_SLAPI */
1405 }
1406
1407 int slapi_add_internal_set_pb( Slapi_PBlock *pb,
1408         const char *dn,
1409         LDAPMod **attrs,
1410         LDAPControl **controls,
1411         Slapi_ComponentId *plugin_identity,
1412         int operation_flags )
1413 {
1414 #ifdef LDAP_SLAPI
1415         slapi_pblock_set( pb, SLAPI_ADD_TARGET, (void *)dn );
1416         slapi_pblock_set( pb, SLAPI_MODIFY_MODS, (void *)attrs );
1417         slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)controls );
1418         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
1419         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS, (void *)operation_flags );
1420
1421         return 0;
1422 #else
1423         return -1;
1424 #endif /* LDAP_SLAPI */
1425 }
1426
1427 Slapi_PBlock *slapi_add_internal(
1428         char * dn,
1429         LDAPMod **attrs,
1430         LDAPControl **controls,
1431         int log_changes )
1432 {
1433 #ifdef LDAP_SLAPI
1434         Slapi_PBlock *pb;
1435
1436         pb = slapi_pblock_new();
1437         if ( pb == NULL )
1438                 return NULL;
1439
1440         slapi_add_internal_set_pb( pb, dn, attrs, controls, NULL,
1441                 log_changes ? SLAPI_OP_FLAG_LOG_CHANGE : 0 );
1442         
1443         slapi_add_internal_pb( pb );
1444
1445         return pb;
1446 #else
1447         return NULL;
1448 #endif /* LDAP_SLAPI */
1449 }
1450
1451 void slapi_add_entry_internal_set_pb( Slapi_PBlock *pb,
1452         Slapi_Entry *e,
1453         LDAPControl **controls,
1454         Slapi_ComponentId *plugin_identity,
1455         int operation_flags )
1456 {
1457 #ifdef LDAP_SLAPI
1458         slapi_pblock_set( pb, SLAPI_ADD_ENTRY, (void *)e );
1459         slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)controls );
1460         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
1461         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS, (void *)operation_flags );
1462 #endif /* LDAP_SLAPI */
1463 }
1464
1465 Slapi_PBlock * 
1466 slapi_add_entry_internal(
1467         Slapi_Entry *e, 
1468         LDAPControl **controls, 
1469         int log_changes )
1470 {
1471 #ifdef LDAP_SLAPI
1472         Slapi_PBlock *pb;
1473
1474         pb = slapi_pblock_new();
1475         if ( pb == NULL )
1476                 return NULL;
1477
1478         slapi_add_entry_internal_set_pb( pb, e, controls, NULL,
1479                 log_changes ? SLAPI_OP_FLAG_LOG_CHANGE : 0 );
1480         
1481         slapi_add_internal_pb( pb );
1482
1483         return pb;
1484 #else
1485         return NULL;
1486 #endif /* LDAP_SLAPI */
1487 }
1488
1489 void slapi_rename_internal_set_pb( Slapi_PBlock *pb,
1490         const char *olddn,
1491         const char *newrdn,
1492         const char *newsuperior,
1493         int deloldrdn,
1494         LDAPControl **controls,
1495         const char *uniqueid,
1496         Slapi_ComponentId *plugin_identity,
1497         int operation_flags )
1498 {
1499 #ifdef LDAP_SLAPI
1500         slapi_pblock_set( pb, SLAPI_MODRDN_TARGET, (void *)olddn );
1501         slapi_pblock_set( pb, SLAPI_MODRDN_NEWRDN, (void *)newrdn );
1502         slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR, (void *)newsuperior );
1503         slapi_pblock_set( pb, SLAPI_MODRDN_DELOLDRDN, (void *)deloldrdn );
1504         slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)controls );
1505         slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID, (void *)uniqueid );
1506         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
1507         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS, (void *)operation_flags );
1508 #endif /* LDAP_SLAPI */
1509 }
1510
1511 /* Function : slapi_modrdn_internal
1512  *
1513  * Description : Plugin functions call this routine to modify the rdn 
1514  *                               of an entry in the backend directly
1515  * Return values : LDAP_SUCCESS
1516  *                 LDAP_PARAM_ERROR
1517  *                 LDAP_NO_MEMORY
1518  *                 LDAP_OTHER
1519  *                 LDAP_UNWILLING_TO_PERFORM
1520  *
1521  * NOTE: This function does not support the "newSuperior" option from LDAP V3.
1522  */
1523 Slapi_PBlock *
1524 slapi_modrdn_internal(
1525         char *olddn, 
1526         char *lnewrdn, 
1527         int deloldrdn, 
1528         LDAPControl **controls, 
1529         int log_change )
1530 {
1531 #ifdef LDAP_SLAPI
1532         Slapi_PBlock *pb;
1533
1534         pb = slapi_pblock_new();
1535         if ( pb == NULL ) {
1536                 return NULL;
1537         }
1538
1539         slapi_rename_internal_set_pb( pb, olddn, lnewrdn, NULL,
1540                 deloldrdn, controls, NULL, NULL,
1541                 log_change ? SLAPI_OP_FLAG_LOG_CHANGE : 0 );
1542
1543         slapi_modrdn_internal_pb( pb );
1544
1545         return pb;
1546 #else
1547         return NULL;
1548 #endif /* LDAP_SLAPI */
1549 }
1550
1551 void slapi_delete_internal_set_pb( Slapi_PBlock *pb,
1552         const char *dn,
1553         LDAPControl **controls,
1554         const char *uniqueid,
1555         Slapi_ComponentId *plugin_identity,
1556         int operation_flags )
1557 {
1558 #ifdef LDAP_SLAPI
1559         slapi_pblock_set( pb, SLAPI_TARGET_DN, (void *)dn );
1560         slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)controls );
1561         slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID, (void *)uniqueid );
1562         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
1563         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS, (void *)operation_flags );
1564 #endif /* LDAP_SLAPI */
1565 }
1566
1567 /* Function : slapi_delete_internal
1568  *
1569  * Description : Plugin functions call this routine to delete an entry 
1570  *               in the backend directly
1571  * Return values : LDAP_SUCCESS
1572  *                 LDAP_PARAM_ERROR
1573  *                 LDAP_NO_MEMORY
1574  *                 LDAP_OTHER
1575  *                 LDAP_UNWILLING_TO_PERFORM
1576 */
1577 Slapi_PBlock *
1578 slapi_delete_internal(
1579         char *ldn, 
1580         LDAPControl **controls, 
1581         int log_change )
1582 {
1583 #ifdef LDAP_SLAPI
1584         Slapi_PBlock *pb;
1585
1586         pb = slapi_pblock_new();
1587         if ( pb == NULL )
1588                 return NULL;
1589
1590         slapi_delete_internal_set_pb( pb, ldn, controls, NULL, NULL,
1591                 log_change ? SLAPI_OP_FLAG_LOG_CHANGE : 0 );
1592
1593         slapi_delete_internal_pb( pb );
1594
1595         return pb;
1596 #else
1597         return NULL;
1598 #endif /* LDAP_SLAPI */
1599 }
1600