]> git.sur5r.net Git - openldap/blob - servers/slapd/slapi/slapi_ops.c
2f207934e7ac483a217ccea60f5089d1ca6dd0e0
[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         op->o_bd = select_backend( &op->o_req_ndn, manageDsaIt, 1 );
796         if ( op->o_bd == NULL ) {
797                 rs.sr_err =  LDAP_PARTIAL_RESULTS;
798                 goto cleanup;
799         }
800
801         op->o_dn = pConn->c_dn = op->o_bd->be_rootdn;
802         op->o_ndn = pConn->c_ndn = op->o_bd->be_rootndn;
803
804         dn.bv_val = (char *)olddn;
805         dn.bv_len = strlen( olddn );
806
807         rs.sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn, NULL );
808         if ( rs.sr_err != LDAP_SUCCESS ) {
809                 goto cleanup;
810         }
811
812         if ( op->o_req_dn.bv_len == 0 ) {
813                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
814                 goto cleanup;
815         }
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
1350         if ( freeFilter && filter != NULL )
1351                 slapi_filter_free( filter, 1 );
1352         if ( fstr.bv_val )
1353                 slapi_ch_free( (void **)&fstr.bv_val );
1354         if ( an != NULL )
1355                 slapi_ch_free( (void **)&an );
1356
1357         slapi_int_connection_destroy( &c );
1358
1359         return 0;
1360 #else
1361         return -1;
1362 #endif /* LDAP_SLAPI */
1363 }
1364
1365 /* Wrappers for old API */
1366
1367 void slapi_search_internal_set_pb( Slapi_PBlock *pb,
1368         const char *base,
1369         int scope,
1370         const char *filter,
1371         char **attrs,
1372         int attrsonly,
1373         LDAPControl **controls,
1374         const char *uniqueid,
1375         Slapi_ComponentId *plugin_identity,
1376         int operation_flags )
1377 {
1378 #ifdef LDAP_SLAPI
1379         slapi_pblock_set( pb, SLAPI_SEARCH_TARGET, (void *)base );
1380         slapi_pblock_set( pb, SLAPI_SEARCH_SCOPE, (void *)scope );
1381         slapi_pblock_set( pb, SLAPI_SEARCH_FILTER, NULL );
1382         slapi_pblock_set( pb, SLAPI_SEARCH_STRFILTER, (void *)filter );
1383         slapi_pblock_set( pb, SLAPI_SEARCH_ATTRS, (void *)attrs );
1384         slapi_pblock_set( pb, SLAPI_SEARCH_ATTRSONLY, (void *)attrsonly );
1385         slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)controls );
1386         slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID, (void *)uniqueid );
1387         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
1388         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS, (void *)operation_flags );
1389 #endif /* LDAP_SLAPI */
1390 }
1391
1392 Slapi_PBlock *
1393 slapi_search_internal(
1394         char *ldn, 
1395         int scope, 
1396         char *filStr, 
1397         LDAPControl **controls, 
1398         char **attrs, 
1399         int attrsonly ) 
1400 {
1401 #ifdef LDAP_SLAPI
1402         Slapi_PBlock *pb;
1403
1404         pb = slapi_pblock_new();
1405         if ( pb == NULL ) {
1406                 return NULL;
1407         }
1408
1409         slapi_search_internal_set_pb( pb, ldn, scope, filStr, attrs, attrsonly,
1410                 controls, NULL, NULL, 0 );
1411
1412         slapi_search_internal_pb( pb );
1413
1414         return pb;
1415 #else
1416         return NULL;
1417 #endif /* LDAP_SLAPI */
1418 }
1419
1420 void slapi_modify_internal_set_pb( Slapi_PBlock *pb,
1421         const char *dn,
1422         LDAPMod **mods,
1423         LDAPControl **controls,
1424         const char *uniqueid,
1425         Slapi_ComponentId *plugin_identity,
1426         int operation_flags )
1427 {
1428 #ifdef LDAP_SLAPI
1429         slapi_pblock_set( pb, SLAPI_MODIFY_TARGET, (void *)dn );
1430         slapi_pblock_set( pb, SLAPI_MODIFY_MODS, (void *)mods );
1431         slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)controls );
1432         slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID, (void *)uniqueid );
1433         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
1434         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS, (void *)operation_flags );
1435 #endif /* LDAP_SLAPI */
1436 }
1437
1438 /* Function : slapi_modify_internal
1439  *
1440  * Description: Plugin functions call this routine to modify an entry 
1441  *                              in the backend directly
1442  * Return values : LDAP_SUCCESS
1443  *                 LDAP_PARAM_ERROR
1444  *                 LDAP_NO_MEMORY
1445  *                 LDAP_OTHER
1446  *                 LDAP_UNWILLING_TO_PERFORM
1447 */
1448 Slapi_PBlock *
1449 slapi_modify_internal(
1450         char *ldn,      
1451         LDAPMod **mods, 
1452         LDAPControl **controls, 
1453         int log_change )
1454 {
1455 #ifdef LDAP_SLAPI
1456         Slapi_PBlock *pb;
1457
1458         pb = slapi_pblock_new();
1459         if ( pb == NULL ) {
1460                 return NULL;
1461         }
1462
1463         slapi_modify_internal_set_pb( pb, ldn, mods, controls, NULL, NULL,
1464                 log_change ? SLAPI_OP_FLAG_LOG_CHANGE : 0 );
1465
1466         slapi_modify_internal_pb( pb );
1467
1468         return pb;
1469 #else
1470         return NULL;
1471 #endif /* LDAP_SLAPI */
1472 }
1473
1474 int slapi_add_internal_set_pb( Slapi_PBlock *pb,
1475         const char *dn,
1476         LDAPMod **attrs,
1477         LDAPControl **controls,
1478         Slapi_ComponentId *plugin_identity,
1479         int operation_flags )
1480 {
1481 #ifdef LDAP_SLAPI
1482         slapi_pblock_set( pb, SLAPI_ADD_TARGET, (void *)dn );
1483         slapi_pblock_set( pb, SLAPI_MODIFY_MODS, (void *)attrs );
1484         slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)controls );
1485         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
1486         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS, (void *)operation_flags );
1487
1488         return 0;
1489 #else
1490         return -1;
1491 #endif /* LDAP_SLAPI */
1492 }
1493
1494 Slapi_PBlock *slapi_add_internal(
1495         char * dn,
1496         LDAPMod **attrs,
1497         LDAPControl **controls,
1498         int log_changes )
1499 {
1500 #ifdef LDAP_SLAPI
1501         Slapi_PBlock *pb;
1502
1503         pb = slapi_pblock_new();
1504         if ( pb == NULL )
1505                 return NULL;
1506
1507         slapi_add_internal_set_pb( pb, dn, attrs, controls, NULL,
1508                 log_changes ? SLAPI_OP_FLAG_LOG_CHANGE : 0 );
1509         
1510         slapi_add_internal_pb( pb );
1511
1512         return pb;
1513 #else
1514         return NULL;
1515 #endif /* LDAP_SLAPI */
1516 }
1517
1518 void slapi_add_entry_internal_set_pb( Slapi_PBlock *pb,
1519         Slapi_Entry *e,
1520         LDAPControl **controls,
1521         Slapi_ComponentId *plugin_identity,
1522         int operation_flags )
1523 {
1524 #ifdef LDAP_SLAPI
1525         slapi_pblock_set( pb, SLAPI_ADD_ENTRY, (void *)e );
1526         slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)controls );
1527         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
1528         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS, (void *)operation_flags );
1529 #endif /* LDAP_SLAPI */
1530 }
1531
1532 Slapi_PBlock * 
1533 slapi_add_entry_internal(
1534         Slapi_Entry *e, 
1535         LDAPControl **controls, 
1536         int log_changes )
1537 {
1538 #ifdef LDAP_SLAPI
1539         Slapi_PBlock *pb;
1540
1541         pb = slapi_pblock_new();
1542         if ( pb == NULL )
1543                 return NULL;
1544
1545         slapi_add_entry_internal_set_pb( pb, e, controls, NULL,
1546                 log_changes ? SLAPI_OP_FLAG_LOG_CHANGE : 0 );
1547         
1548         slapi_add_internal_pb( pb );
1549
1550         return pb;
1551 #else
1552         return NULL;
1553 #endif /* LDAP_SLAPI */
1554 }
1555
1556 void slapi_rename_internal_set_pb( Slapi_PBlock *pb,
1557         const char *olddn,
1558         const char *newrdn,
1559         const char *newsuperior,
1560         int deloldrdn,
1561         LDAPControl **controls,
1562         const char *uniqueid,
1563         Slapi_ComponentId *plugin_identity,
1564         int operation_flags )
1565 {
1566 #ifdef LDAP_SLAPI
1567         slapi_pblock_set( pb, SLAPI_MODRDN_TARGET, (void *)olddn );
1568         slapi_pblock_set( pb, SLAPI_MODRDN_NEWRDN, (void *)newrdn );
1569         slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR, (void *)newsuperior );
1570         slapi_pblock_set( pb, SLAPI_MODRDN_DELOLDRDN, (void *)deloldrdn );
1571         slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)controls );
1572         slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID, (void *)uniqueid );
1573         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
1574         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS, (void *)operation_flags );
1575 #endif /* LDAP_SLAPI */
1576 }
1577
1578 /* Function : slapi_modrdn_internal
1579  *
1580  * Description : Plugin functions call this routine to modify the rdn 
1581  *                               of an entry in the backend directly
1582  * Return values : LDAP_SUCCESS
1583  *                 LDAP_PARAM_ERROR
1584  *                 LDAP_NO_MEMORY
1585  *                 LDAP_OTHER
1586  *                 LDAP_UNWILLING_TO_PERFORM
1587  *
1588  * NOTE: This function does not support the "newSuperior" option from LDAP V3.
1589  */
1590 Slapi_PBlock *
1591 slapi_modrdn_internal(
1592         char *olddn, 
1593         char *lnewrdn, 
1594         int deloldrdn, 
1595         LDAPControl **controls, 
1596         int log_change )
1597 {
1598 #ifdef LDAP_SLAPI
1599         Slapi_PBlock *pb;
1600
1601         pb = slapi_pblock_new();
1602         if ( pb == NULL ) {
1603                 return NULL;
1604         }
1605
1606         slapi_rename_internal_set_pb( pb, olddn, lnewrdn, NULL,
1607                 deloldrdn, controls, NULL, NULL,
1608                 log_change ? SLAPI_OP_FLAG_LOG_CHANGE : 0 );
1609
1610         slapi_modrdn_internal_pb( pb );
1611
1612         return pb;
1613 #else
1614         return NULL;
1615 #endif /* LDAP_SLAPI */
1616 }
1617
1618 void slapi_delete_internal_set_pb( Slapi_PBlock *pb,
1619         const char *dn,
1620         LDAPControl **controls,
1621         const char *uniqueid,
1622         Slapi_ComponentId *plugin_identity,
1623         int operation_flags )
1624 {
1625 #ifdef LDAP_SLAPI
1626         slapi_pblock_set( pb, SLAPI_TARGET_DN, (void *)dn );
1627         slapi_pblock_set( pb, SLAPI_REQCONTROLS, (void *)controls );
1628         slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID, (void *)uniqueid );
1629         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
1630         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS, (void *)operation_flags );
1631 #endif /* LDAP_SLAPI */
1632 }
1633
1634 /* Function : slapi_delete_internal
1635  *
1636  * Description : Plugin functions call this routine to delete an entry 
1637  *               in the backend directly
1638  * Return values : LDAP_SUCCESS
1639  *                 LDAP_PARAM_ERROR
1640  *                 LDAP_NO_MEMORY
1641  *                 LDAP_OTHER
1642  *                 LDAP_UNWILLING_TO_PERFORM
1643 */
1644 Slapi_PBlock *
1645 slapi_delete_internal(
1646         char *ldn, 
1647         LDAPControl **controls, 
1648         int log_change )
1649 {
1650 #ifdef LDAP_SLAPI
1651         Slapi_PBlock *pb;
1652
1653         pb = slapi_pblock_new();
1654         if ( pb == NULL )
1655                 return NULL;
1656
1657         slapi_delete_internal_set_pb( pb, ldn, controls, NULL, NULL,
1658                 log_change ? SLAPI_OP_FLAG_LOG_CHANGE : 0 );
1659
1660         slapi_delete_internal_pb( pb );
1661
1662         return pb;
1663 #else
1664         return NULL;
1665 #endif /* LDAP_SLAPI */
1666 }
1667