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