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