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