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