]> git.sur5r.net Git - openldap/blob - servers/slapd/slapi/slapi_ops.c
Fix dangling mutex in SLAPI bind preop handler
[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;
422
423         if ( conn == NULL ) {
424                 return;
425         }
426
427         op = (Operation *)conn->c_pending_ops.stqh_first;
428         pb = SLAPI_OPERATION_PBLOCK( op );
429
430         slap_graduate_commit_csn( op );
431
432         if ( op->o_req_dn.bv_val != NULL ) {
433                 slapi_ch_free( (void **)&op->o_req_dn.bv_val );
434         }
435         if ( op->o_req_ndn.bv_val != NULL ) {
436                 slapi_ch_free( (void **)&op->o_req_ndn.bv_val );
437         }
438
439         if ( conn->c_sb != NULL ) {
440                 ber_sockbuf_free( conn->c_sb );
441         }
442
443         slapi_pblock_set( pb, SLAPI_OPERATION, NULL );
444         slapi_pblock_set( pb, SLAPI_CONNECTION, NULL );
445
446         if ( op != NULL ) {
447                 slapi_ch_free( (void **)&op );
448         }
449
450         slapi_ch_free( (void **)pConn );
451 }
452
453 /*
454  * Function : values2obj
455  * Convert an array of strings into a BerVarray.
456  * the strings.
457  */
458 static int
459 values2obj_copy(
460         char **ppValue,
461         BerVarray *bvobj )
462 {
463         int i;
464         BerVarray tmpberval;
465
466         if ( ppValue == NULL ) {
467                 *bvobj = NULL;
468                 return LDAP_SUCCESS;
469         }
470
471         for ( i = 0; ppValue[i] != NULL; i++ )
472                 ; /* EMPTY */
473
474         tmpberval = (BerVarray)slapi_ch_malloc( (i+1) * (sizeof(struct berval)) );
475         if ( tmpberval == NULL ) {
476                 return LDAP_NO_MEMORY;
477         }
478         for ( i = 0; ppValue[i] != NULL; i++ ) {
479                 size_t len = strlen( ppValue[i] );
480
481                 tmpberval[i].bv_val = slapi_ch_malloc( len + 1 );
482                 AC_MEMCPY( tmpberval[i].bv_val, ppValue[i], len + 1 );
483                 tmpberval[i].bv_len = len;
484         }
485         tmpberval[i].bv_val = NULL;
486         tmpberval[i].bv_len = 0;
487
488         *bvobj = tmpberval;
489
490         return LDAP_SUCCESS;
491 }
492
493 static int
494 bvptr2obj_copy(
495         struct berval   **bvptr, 
496         BerVarray       *bvobj )
497 {
498         int             i;
499         BerVarray       tmpberval;
500
501         if ( bvptr == NULL ) {
502                 *bvobj = NULL;
503                 return LDAP_SUCCESS;
504         }
505
506         for ( i = 0; bvptr[i] != NULL; i++ )
507                 ; /* EMPTY */
508
509         tmpberval = (BerVarray)slapi_ch_malloc( (i + 1) * sizeof(struct berval));
510         if ( tmpberval == NULL ) {
511                 return LDAP_NO_MEMORY;
512         } 
513
514         for ( i = 0; bvptr[i] != NULL; i++ ) {
515                 tmpberval[i].bv_val = slapi_ch_malloc( bvptr[i]->bv_len );
516                 tmpberval[i].bv_len = bvptr[i]->bv_len;
517                 AC_MEMCPY( tmpberval[i].bv_val, bvptr[i]->bv_val, bvptr[i]->bv_len );
518         }
519
520         tmpberval[i].bv_val = NULL;
521         tmpberval[i].bv_len = 0;
522
523         *bvobj = tmpberval;
524
525         return LDAP_SUCCESS;
526 }
527
528 /*
529  * Function : slapi_int_ldapmod_to_entry 
530  * convert a dn plus an array of LDAPMod struct ptrs to an entry structure
531  * with a link list of the correspondent attributes.
532  * Return value : LDAP_SUCCESS
533  *                LDAP_NO_MEMORY
534  *                LDAP_OTHER
535 */
536 static Entry *
537 slapi_int_ldapmod_to_entry(
538         Connection *pConn,
539         char *ldn, 
540         LDAPMod **mods )
541 {
542         struct berval           dn = BER_BVNULL;
543         Entry                   *pEntry=NULL;
544         LDAPMod                 *pMod;
545         struct berval           *bv;
546         Operation               *op;
547
548         Modifications           *modlist = NULL;
549         Modifications           **modtail = &modlist;
550         Modifications           tmp;
551
552         int                     rc = LDAP_SUCCESS;
553         int                     i;
554
555         const char              *text = NULL;
556
557         op = (Operation *)pConn->c_pending_ops.stqh_first;
558
559         pEntry = (Entry *) ch_calloc( 1, sizeof(Entry) );
560         if ( pEntry == NULL) {
561                 rc = LDAP_NO_MEMORY;
562                 goto cleanup;
563         } 
564
565         dn.bv_val = ldn;
566         dn.bv_len = strlen( ldn );
567
568         rc = dnPrettyNormal( NULL, &dn, &pEntry->e_name, &pEntry->e_nname, NULL );
569         if ( rc != LDAP_SUCCESS ) {
570                 goto cleanup;
571         }
572
573         if ( rc == LDAP_SUCCESS ) {
574                 for ( i = 0, pMod = mods[0]; rc == LDAP_SUCCESS && pMod != NULL; pMod = mods[++i]) {
575                         Modifications *mod;
576
577                         if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {
578                                 /*
579                                  * Convert an array of pointers to bervals to
580                                  * an array of bervals. Note that we need to copy the
581                                  * values too, as the slap_mods_check() will free the
582                                  * original values after prettying; the modifications
583                                  * being passed in may not have been allocated on the
584                                  * heap.
585                                  */
586                                 rc = bvptr2obj_copy( pMod->mod_bvalues, &bv );
587                                 if ( rc != LDAP_SUCCESS ) goto cleanup;
588                                 tmp.sml_type.bv_val = pMod->mod_type;
589                                 tmp.sml_type.bv_len = strlen( pMod->mod_type );
590                                 tmp.sml_values = bv;
591                                 tmp.sml_nvalues = NULL;
592                 
593                                 mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
594
595                                 mod->sml_op = LDAP_MOD_ADD;
596                                 mod->sml_flags = 0;
597                                 mod->sml_next = NULL;
598                                 mod->sml_desc = NULL;
599                                 mod->sml_type = tmp.sml_type;
600                                 mod->sml_values = tmp.sml_values;
601                                 mod->sml_nvalues = tmp.sml_nvalues;
602
603                                 *modtail = mod;
604                                 modtail = &mod->sml_next;
605
606                         } else {
607                                 /* attr values are in string format, need to be converted */
608                                 /* to an array of bervals */ 
609                                 if ( pMod->mod_values == NULL ) {
610                                         rc = LDAP_OTHER;
611                                 } else {
612                                         rc = values2obj_copy( pMod->mod_values, &bv );
613                                         if ( rc != LDAP_SUCCESS ) goto cleanup;
614                                         tmp.sml_type.bv_val = pMod->mod_type;
615                                         tmp.sml_type.bv_len = strlen( pMod->mod_type );
616                                         tmp.sml_values = bv;
617                                         tmp.sml_nvalues = NULL;
618                 
619                                         mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
620
621                                         mod->sml_op = LDAP_MOD_ADD;
622                                         mod->sml_flags = 0;
623                                         mod->sml_next = NULL;
624                                         mod->sml_desc = NULL;
625                                         mod->sml_type = tmp.sml_type;
626                                         mod->sml_values = tmp.sml_values;
627                                         mod->sml_nvalues = tmp.sml_nvalues;
628
629                                         *modtail = mod;
630                                         modtail = &mod->sml_next;
631                                 }
632                         }
633                 } /* for each LDAPMod */
634         }
635
636         op->o_bd = select_backend( &pEntry->e_nname, 0, 0 );
637         if ( op->o_bd == NULL ) {
638                 rc = LDAP_PARTIAL_RESULTS;
639         } else {
640                 int repl_user = be_isupdate_dn( op->o_bd, &op->o_bd->be_rootdn );
641                 if ( !op->o_bd->be_update_ndn.bv_len || repl_user ) {
642                         int     update = !BER_BVISNULL( &op->o_bd->be_update_ndn );
643                         char    textbuf[ SLAP_TEXT_BUFLEN ];
644                         size_t  textlen = sizeof( textbuf );
645
646                         rc = slap_mods_check( modlist, &text, 
647                                 textbuf, textlen, NULL );
648
649                         if ( rc != LDAP_SUCCESS) {
650                                 goto cleanup;
651                         }
652
653                         if ( !update ) {
654                                 rc = slap_mods_no_user_mod_check( op, modlist,
655                                         &text, textbuf, textlen );
656                                 if ( rc != LDAP_SUCCESS) {
657                                         goto cleanup;
658                                 }
659                         }
660
661                         if ( !repl_user ) {
662                                 rc = slap_mods_opattrs( op, modlist, modtail,
663                                         &text, textbuf, textlen, 1 );
664                                 if ( rc != LDAP_SUCCESS) {
665                                         goto cleanup;
666                                 }
667                         }
668
669                         rc = slap_mods2entry( modlist, &pEntry, repl_user,
670                                               0, &text, textbuf, textlen );
671                         if (rc != LDAP_SUCCESS) {
672                                 goto cleanup;
673                         }
674
675                 } else {
676                         rc = LDAP_REFERRAL;
677                 }
678         }
679
680 cleanup:;
681         if ( modlist != NULL )
682                 slap_mods_free( modlist );
683         if ( rc != LDAP_SUCCESS ) {
684                 if ( pEntry != NULL ) {
685                         slapi_entry_free( pEntry );
686                 }
687                 pEntry = NULL;
688         }
689
690         return( pEntry );
691 }
692
693 int
694 slapi_delete_internal_pb( Slapi_PBlock *pb )
695 {
696 #ifdef LDAP_SLAPI
697         Connection              *conn = NULL;
698         Operation               *op = NULL;
699         int                     operation_flags = 0;
700
701         SlapReply               rs = { REP_RESULT };
702
703         if ( pb == NULL ) {
704                 return -1;
705         }
706
707         slapi_pblock_get( pb, SLAPI_X_INTOP_FLAGS, &operation_flags );
708
709         rs.sr_err = slapi_int_init_connection( pb, &rs, LDAP_REQ_DELETE, &conn );
710         if ( rs.sr_err != LDAP_SUCCESS ) {
711                 goto cleanup;
712         }
713
714         op = conn->c_pending_ops.stqh_first;
715
716         if ( op->o_bd->be_delete != NULL ) {
717                 int repl_user = be_isupdate( op );
718                 if ( !op->o_bd->be_update_ndn.bv_len || repl_user ) {
719                         slap_callback cb = { NULL, slap_replog_cb, NULL, NULL };
720                         if ( operation_flags & SLAPI_OP_FLAG_LOG_CHANGE )
721                                 op->o_callback = &cb;
722
723                         op->o_bd->be_delete( op, &rs );
724                 } else {
725                         rs.sr_err = LDAP_REFERRAL;
726                 }
727         } else {
728                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
729         }
730
731 cleanup:
732         slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rs.sr_err );
733         slapi_int_connection_destroy( &conn );
734
735         return 0;
736 #else
737         return -1;
738 #endif /* LDAP_SLAPI */
739 }
740
741 int
742 slapi_add_internal_pb( Slapi_PBlock *pb )
743 {
744 #ifdef LDAP_SLAPI
745         Connection              *conn = NULL;
746         Slapi_Entry             *entry = NULL;
747         Slapi_Entry             *argEntry = NULL;
748         char                    *dn = NULL;
749         LDAPMod                 **mods = NULL;
750         int                     operation_flags = 0;
751         Operation               *op = NULL;
752         int                     i;
753
754         SlapReply               rs = { REP_RESULT };
755
756         if ( pb == NULL ) {
757                 return -1;
758         }
759
760         slapi_pblock_get( pb, SLAPI_ADD_ENTRY,     (void **)&argEntry );
761         slapi_pblock_get( pb, SLAPI_ADD_TARGET,    (void **)&dn );
762         slapi_pblock_get( pb, SLAPI_MODIFY_MODS,   (void **)&mods );
763         slapi_pblock_get( pb, SLAPI_X_INTOP_FLAGS, (void **)&operation_flags );
764
765         if ( argEntry != NULL ) {
766                 /*
767                  * The caller can specify a new entry, or a target DN and set
768                  * of modifications, but not both.
769                  */
770                 if ( dn != NULL ) {
771                         rs.sr_err = LDAP_PARAM_ERROR;
772                         goto cleanup;
773                 }
774
775                 /*
776                  * Set the DN here so that slapi_int_init_backend() will select
777                  * correct backend.
778                  */
779                 dn = slapi_entry_get_dn( argEntry );
780                 slapi_pblock_set( pb, SLAPI_ADD_TARGET, &entry->e_nname.bv_val );
781         }
782
783         rs.sr_err = slapi_int_init_connection( pb, &rs, LDAP_REQ_ADD, &conn );
784         if ( rs.sr_err != LDAP_SUCCESS ) {
785                 goto cleanup;
786         }
787
788         if ( argEntry != NULL ) {
789                 entry = slapi_entry_dup( argEntry );
790         } else {
791                 if ( mods == NULL || dn == NULL ) {
792                         rs.sr_err = LDAP_PARAM_ERROR;
793                         goto cleanup;
794                 }
795
796                 for ( i = 0; mods[i] != NULL; i++ ) {
797                         if ( (mods[i]->mod_op & LDAP_MOD_OP ) != LDAP_MOD_ADD ) {
798                                 rs.sr_err = LDAP_PARAM_ERROR;
799                                 goto cleanup;
800                         }
801                 }
802
803                 entry = slapi_int_ldapmod_to_entry( conn, dn, mods );
804                 if ( entry == NULL ) {
805                         rs.sr_err = LDAP_OTHER;
806                         goto cleanup;
807                 }
808         }
809
810         op = (Operation *)conn->c_pending_ops.stqh_first;
811         op->oq_add.rs_e = entry;
812
813         if ( op->o_bd->be_add != NULL ) {
814                 int repl_user = be_isupdate( op );
815                 if ( !op->o_bd->be_update_ndn.bv_len || repl_user ) {
816                         slap_callback cb = { NULL, slap_replog_cb, NULL, NULL };
817
818                         if ( operation_flags & SLAPI_OP_FLAG_LOG_CHANGE )
819                                 op->o_callback = &cb;
820
821                         if ( op->o_bd->be_add( op, &rs ) == LDAP_SUCCESS ) {
822                                 be_entry_release_w( op, entry );
823                                 entry = NULL;
824                         }
825                 } else {
826                         rs.sr_err = LDAP_REFERRAL;
827                 }
828         } else {
829                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
830         }
831
832 cleanup:
833         slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rs.sr_err );
834
835         if ( entry != NULL ) {
836                 slapi_entry_free( entry );
837         }
838         if ( argEntry != NULL ) {
839                 slapi_pblock_set( pb, SLAPI_ADD_TARGET, NULL );
840         }
841
842         slapi_int_connection_destroy( &conn );
843
844         return 0;
845 #else
846         return -1;
847 #endif /* LDAP_SLAPI */
848 }
849
850 int
851 slapi_modrdn_internal_pb( Slapi_PBlock *pb )
852 {
853 #ifdef LDAP_SLAPI
854         struct berval           dn = BER_BVNULL;
855         struct berval           newrdn = BER_BVNULL;
856         struct berval           newsupdn = BER_BVNULL;
857         struct berval           newSuperiorPretty = BER_BVNULL;
858         struct berval           newSuperiorNormalized = BER_BVNULL;
859         Connection              *conn = NULL;
860         Operation               *op = NULL;
861         int                     manageDsaIt = SLAP_CONTROL_NONE;
862         int                     isCritical;
863
864         char                    *lnewrdn;
865         char                    *newsuperior;
866         int                     deloldrdn;
867         int                     operation_flags;
868
869         SlapReply               rs = { REP_RESULT };
870
871         if ( pb == NULL ) {
872                 return -1;
873         }
874
875         slapi_pblock_get( pb, SLAPI_MODRDN_NEWRDN,      (void **)&lnewrdn );
876         slapi_pblock_get( pb, SLAPI_MODRDN_NEWSUPERIOR, (void **)&newsuperior );
877         slapi_pblock_get( pb, SLAPI_MODRDN_DELOLDRDN,   (void **)&deloldrdn );
878         slapi_pblock_get( pb, SLAPI_X_INTOP_FLAGS,      (void **)&operation_flags );
879
880         rs.sr_err = slapi_int_init_connection( pb, &rs, LDAP_REQ_MODRDN, &conn );
881         if ( rs.sr_err != LDAP_SUCCESS ) {
882                 goto cleanup;
883         }
884
885         op = (Operation *)conn->c_pending_ops.stqh_first;
886
887         if ( op->o_req_dn.bv_len == 0 ) {
888                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
889                 goto cleanup;
890         }
891
892         newrdn.bv_val = lnewrdn;
893         newrdn.bv_len = strlen( lnewrdn );
894
895         rs.sr_err = dnPrettyNormal( NULL, &newrdn, &op->oq_modrdn.rs_newrdn, &op->oq_modrdn.rs_nnewrdn, NULL );
896         if ( rs.sr_err != LDAP_SUCCESS ) {
897                 goto cleanup;
898         }
899
900         if ( rdn_validate( &op->oq_modrdn.rs_nnewrdn ) != LDAP_SUCCESS ) {
901                 goto cleanup;
902         }
903
904         if ( newsuperior != NULL ) {
905                 newsupdn.bv_val = (char *)newsuperior;
906                 newsupdn.bv_len = strlen( newsuperior );
907
908                 rs.sr_err = dnPrettyNormal( NULL, &newsupdn, &newSuperiorPretty, &newSuperiorNormalized, NULL );
909                 if ( rs.sr_err != LDAP_SUCCESS )
910                         goto cleanup;
911
912                 op->oq_modrdn.rs_newSup = &newSuperiorPretty;
913                 op->oq_modrdn.rs_nnewSup = &newSuperiorNormalized;
914         } else {
915                 op->oq_modrdn.rs_newSup = NULL;
916                 op->oq_modrdn.rs_nnewSup = NULL;
917         }
918
919         op->oq_modrdn.rs_deleteoldrdn = deloldrdn;
920
921         if ( op->o_bd->be_modrdn != NULL ) {
922                 int repl_user = be_isupdate( op );
923                 if ( !op->o_bd->be_update_ndn.bv_len || repl_user ) {
924                         slap_callback cb = { NULL, slap_replog_cb, NULL, NULL };
925
926                         if ( operation_flags & SLAPI_OP_FLAG_LOG_CHANGE )
927                                 op->o_callback = &cb;
928
929                         op->o_bd->be_modrdn( op, &rs );
930                 } else {
931                         rs.sr_err = LDAP_REFERRAL;
932                 }
933         } else {
934                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
935         }
936
937 cleanup:
938         slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rs.sr_err );
939
940         if ( op->oq_modrdn.rs_newrdn.bv_val != NULL )
941                 slapi_ch_free_string( &op->oq_modrdn.rs_newrdn.bv_val );
942         if ( op->oq_modrdn.rs_nnewrdn.bv_val != NULL )
943                 slapi_ch_free_string( &op->oq_modrdn.rs_nnewrdn.bv_val );
944         if ( newSuperiorPretty.bv_val != NULL )
945                 slapi_ch_free_string( &newSuperiorPretty.bv_val );
946         if ( newSuperiorNormalized.bv_val != NULL )
947                 slapi_ch_free_string( &newSuperiorNormalized.bv_val );
948
949         slapi_int_connection_destroy( &conn );
950
951         return 0;
952 #else
953         return -1;
954 #endif /* LDAP_SLAPI */
955 }
956
957 int slapi_modify_internal_pb( Slapi_PBlock *pb )
958 {
959 #ifdef LDAP_SLAPI
960         int                     i;
961         Connection              *conn = NULL;
962         Operation               *op = NULL;
963
964         struct berval dn = BER_BVNULL;
965
966         int                     manageDsaIt = SLAP_CONTROL_NONE;
967         int                     isCritical;
968         struct berval           *bv;
969         LDAPMod                 *pMod;
970
971         Modifications           *modlist = NULL;
972         Modifications           **modtail = &modlist;
973         Modifications           tmp;
974
975         LDAPMod                 **mods = NULL;
976         int                     operation_flags = 0;
977
978         SlapReply               rs = { REP_RESULT };
979
980         if ( pb == NULL ) {
981                 return -1;
982         }
983
984         slapi_pblock_get( pb, SLAPI_MODIFY_MODS,   (void **)&mods );
985         slapi_pblock_get( pb, SLAPI_X_INTOP_FLAGS, (void **)&operation_flags );
986
987         if ( mods == NULL || mods[0] == NULL ) {
988                 rs.sr_err = LDAP_PARAM_ERROR ;
989                 goto cleanup;
990         }
991
992         rs.sr_err = slapi_int_init_connection( pb, &rs, LDAP_REQ_MODIFY, &conn );
993         if ( rs.sr_err != LDAP_SUCCESS ) {
994                 goto cleanup;
995         }
996
997         for ( i = 0, pMod = mods[0];
998                 rs.sr_err == LDAP_SUCCESS && pMod != NULL; 
999                 pMod = mods[++i] )
1000         {
1001                 Modifications *mod;
1002
1003                 if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {
1004                         /*
1005                          * attr values are in berval format
1006                          * convert an array of pointers to bervals
1007                          * to an array of bervals
1008                          */
1009                         rs.sr_err = bvptr2obj_copy( pMod->mod_bvalues, &bv );
1010                         if ( rs.sr_err != LDAP_SUCCESS )
1011                                 goto cleanup;
1012                         tmp.sml_type.bv_val = pMod->mod_type;
1013                         tmp.sml_type.bv_len = strlen( pMod->mod_type );
1014                         tmp.sml_values = bv;
1015                         tmp.sml_nvalues = NULL;
1016
1017                         mod  = (Modifications *)ch_malloc( sizeof(Modifications) );
1018
1019                         mod->sml_op = pMod->mod_op & LDAP_MOD_OP;
1020                         mod->sml_flags = 0;
1021                         mod->sml_next = NULL;
1022                         mod->sml_desc = NULL;
1023                         mod->sml_type = tmp.sml_type;
1024                         mod->sml_values = tmp.sml_values;
1025                         mod->sml_nvalues = tmp.sml_nvalues;
1026                 } else { 
1027                         rs.sr_err = values2obj_copy( pMod->mod_values, &bv );
1028                         if ( rs.sr_err != LDAP_SUCCESS )
1029                                 goto cleanup;
1030                         tmp.sml_type.bv_val = pMod->mod_type;
1031                         tmp.sml_type.bv_len = strlen( pMod->mod_type );
1032                         tmp.sml_values = bv;
1033                         tmp.sml_nvalues = NULL;
1034
1035                         mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
1036
1037                         mod->sml_op = pMod->mod_op & LDAP_MOD_OP;
1038                         mod->sml_flags = 0;
1039                         mod->sml_next = NULL;
1040                         mod->sml_desc = NULL;
1041                         mod->sml_type = tmp.sml_type;
1042                         mod->sml_values = tmp.sml_values;
1043                         mod->sml_nvalues = tmp.sml_nvalues;
1044                 }
1045                 *modtail = mod;
1046                 modtail = &mod->sml_next;
1047
1048                 switch( pMod->mod_op & LDAP_MOD_OP ) {
1049                 case LDAP_MOD_ADD:
1050                 if ( mod->sml_values == NULL ) {
1051                         rs.sr_err = LDAP_PROTOCOL_ERROR;
1052                         goto cleanup;
1053                 }
1054
1055                 /* fall through */
1056                 case LDAP_MOD_DELETE:
1057                 case LDAP_MOD_REPLACE:
1058                 case LDAP_MOD_INCREMENT:
1059                 break;
1060
1061                 default:
1062                         rs.sr_err = LDAP_PROTOCOL_ERROR;
1063                         goto cleanup;
1064                 }
1065         } 
1066         *modtail = NULL;
1067
1068         op = (Operation *)conn->c_pending_ops.stqh_first;
1069
1070         if ( op->o_req_ndn.bv_len == 0 ) {
1071                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
1072                 goto cleanup;
1073         }
1074
1075         op->oq_modify.rs_modlist = modlist;
1076
1077         if ( op->o_bd->be_modify != NULL ) {
1078                 int repl_user = be_isupdate( op );
1079                 if ( !op->o_bd->be_update_ndn.bv_len || repl_user ) {
1080                         int             update = !BER_BVISEMPTY( &op->o_bd->be_update_ndn );
1081                         const char      *text = NULL;
1082                         char            textbuf[ SLAP_TEXT_BUFLEN ];
1083                         size_t          textlen = sizeof( textbuf );
1084                         slap_callback   cb = { NULL, slap_replog_cb, NULL, NULL };
1085
1086                         rs.sr_err = slap_mods_check( modlist,
1087                                 &text, textbuf, textlen, NULL );
1088                         if ( rs.sr_err != LDAP_SUCCESS ) {
1089                                 goto cleanup;
1090                         }
1091
1092                         if ( !update ) {
1093                                 rs.sr_err = slap_mods_no_user_mod_check( op, modlist,
1094                                         &text, textbuf, textlen );
1095                                 if ( rs.sr_err != LDAP_SUCCESS ) {
1096                                         goto cleanup;
1097                                 }
1098                         }
1099
1100                         if ( !repl_user ) {
1101                                 rs.sr_err = slap_mods_opattrs( op, modlist,
1102                                                 modtail, &text, textbuf, 
1103                                                 textlen, 1 );
1104                                 if ( rs.sr_err != LDAP_SUCCESS ) {
1105                                         goto cleanup;
1106                                 }
1107                         }
1108
1109                         if ( operation_flags & SLAPI_OP_FLAG_LOG_CHANGE )
1110                                 op->o_callback = &cb;
1111
1112                         op->o_bd->be_modify( op, &rs );
1113                 } else {
1114                         rs.sr_err = LDAP_REFERRAL;
1115                 }
1116         } else {
1117                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
1118         }
1119
1120 cleanup:
1121         slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rs.sr_err );
1122
1123         if ( modlist != NULL )
1124                 slap_mods_free( modlist );
1125
1126         slapi_int_connection_destroy( &conn );
1127
1128         return 0;
1129 #else
1130         return -1;
1131 #endif /* LDAP_SLAPI */
1132 }
1133
1134 #ifdef LDAP_SLAPI
1135 static int
1136 slapi_int_search_entry_callback( Slapi_Entry *entry, void *callback_data )
1137 {
1138         int nentries = 0, i = 0;
1139         Slapi_Entry **head = NULL, **tp;
1140         Slapi_PBlock *pb = (Slapi_PBlock *)callback_data;
1141
1142         entry = slapi_entry_dup( entry );
1143         if ( entry == NULL ) {
1144                 return 1;
1145         }
1146
1147         slapi_pblock_get( pb, SLAPI_NENTRIES, &nentries );
1148         slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &head );
1149         
1150         i = nentries + 1;
1151         if ( nentries == 0 ) {
1152                 tp = (Slapi_Entry **)slapi_ch_malloc( 2 * sizeof(Slapi_Entry *) );
1153                 if ( tp == NULL ) {
1154                         slapi_entry_free( entry );
1155                         return 1;
1156                 }
1157
1158                 tp[ 0 ] = entry;
1159         } else {
1160                 tp = (Slapi_Entry **)slapi_ch_realloc( (char *)head,
1161                                 sizeof(Slapi_Entry *) * ( i + 1 ) );
1162                 if ( tp == NULL ) {
1163                         slapi_entry_free( entry );
1164                         return 1;
1165                 }
1166                 tp[ i - 1 ] = entry;
1167         }
1168         tp[ i ] = NULL;
1169                   
1170         slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, (void *)tp );
1171         slapi_pblock_set( pb, SLAPI_NENTRIES, (void *)i );
1172
1173         return LDAP_SUCCESS;
1174 }
1175 #endif /* LDAP_SLAPI */
1176
1177 int slapi_search_internal_pb( Slapi_PBlock *pb )
1178 {
1179 #ifdef LDAP_SLAPI
1180         return slapi_search_internal_callback_pb( pb,
1181                 (void *)pb,
1182                 NULL,
1183                 slapi_int_search_entry_callback,
1184                 NULL );
1185 #else
1186         return -1;
1187 #endif
1188 }
1189
1190 int slapi_search_internal_callback_pb( Slapi_PBlock *pb,
1191         void *callback_data,
1192         plugin_result_callback prc,
1193         plugin_search_entry_callback psec,
1194         plugin_referral_entry_callback prec )
1195 {
1196 #ifdef LDAP_SLAPI
1197         Connection              *conn = NULL;
1198         Operation               *op = NULL;
1199         struct berval           dn = BER_BVNULL;
1200         Filter                  *filter = NULL;
1201         struct berval           fstr = BER_BVNULL;
1202         AttributeName           *an = NULL;
1203         const char              *text = NULL;
1204
1205         int                     manageDsaIt = SLAP_CONTROL_NONE;
1206         int                     isCritical;
1207         int                     i;
1208
1209         int                     scope = LDAP_SCOPE_BASE;
1210         char                    *filStr = NULL;
1211         LDAPControl             **controls = NULL;
1212         char                    **attrs = NULL;
1213         char                    *uniqueid = NULL;
1214         int                     attrsonly = 0;
1215         int                     operation_flags = 0;
1216         int                     freeFilter = 0;
1217
1218         SlapReply               rs = { REP_RESULT };
1219
1220         if ( pb == NULL ) {
1221                 return -1;
1222         }
1223
1224         slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE,     (void **)&scope );
1225         slapi_pblock_get( pb, SLAPI_SEARCH_FILTER,    (void **)&filter );
1226         slapi_pblock_get( pb, SLAPI_SEARCH_STRFILTER, (void **)&filStr );
1227         slapi_pblock_get( pb, SLAPI_SEARCH_ATTRS,     (void **)&attrs );
1228         slapi_pblock_get( pb, SLAPI_SEARCH_ATTRSONLY, (void **)&attrsonly );
1229         slapi_pblock_get( pb, SLAPI_REQCONTROLS,      (void **)&controls );
1230         slapi_pblock_get( pb, SLAPI_TARGET_UNIQUEID,  (void **)&uniqueid );
1231         slapi_pblock_get( pb, SLAPI_X_INTOP_FLAGS,    (void **)&operation_flags );
1232
1233         rs.sr_err = slapi_int_init_connection( pb, &rs, LDAP_REQ_SEARCH, &conn );
1234         if ( rs.sr_err != LDAP_SUCCESS ) {
1235                 goto cleanup;
1236         }
1237
1238         /* search callback and arguments */
1239         slapi_pblock_set( pb, SLAPI_X_INTOP_RESULT_CALLBACK,         (void *)prc );
1240         slapi_pblock_set( pb, SLAPI_X_INTOP_SEARCH_ENTRY_CALLBACK,   (void *)psec );
1241         slapi_pblock_set( pb, SLAPI_X_INTOP_REFERRAL_ENTRY_CALLBACK, (void *)prec );
1242         slapi_pblock_set( pb, SLAPI_X_INTOP_CALLBACK_DATA,           (void *)callback_data );
1243
1244         op = (Operation *)conn->c_pending_ops.stqh_first;
1245
1246         switch ( scope ) {
1247                 case LDAP_SCOPE_BASE:
1248                 case LDAP_SCOPE_ONELEVEL:
1249                 case LDAP_SCOPE_SUBTREE:
1250 #ifdef LDAP_SCOPE_SUBORDINATE
1251                 case LDAP_SCOPE_SUBORDINATE:
1252 #endif
1253                         break;
1254                 default:
1255                         rs.sr_err = LDAP_PROTOCOL_ERROR;
1256                         goto cleanup;
1257         }
1258
1259         if ( filter == NULL ) {
1260                 if ( filStr == NULL ) {
1261                         rs.sr_err = LDAP_PARAM_ERROR;
1262                         goto cleanup;
1263                 }
1264
1265                 filter = slapi_str2filter( filStr );
1266                 if ( filter == NULL ) {
1267                         rs.sr_err = LDAP_PROTOCOL_ERROR;
1268                         goto cleanup;
1269                 }
1270
1271                 freeFilter = 1;
1272         }
1273
1274         filter2bv( filter, &fstr );
1275
1276         for ( i = 0; attrs != NULL && attrs[i] != NULL; i++ ) {
1277                 ; /* count the number of attributes */
1278         }
1279
1280         if ( i > 0 ) {
1281                 an = (AttributeName *)slapi_ch_calloc( (i + 1), sizeof(AttributeName) );
1282                 for (i = 0; attrs[i] != 0; i++) {
1283                         an[i].an_desc = NULL;
1284                         an[i].an_oc = NULL;
1285                         an[i].an_oc_exclude = 0;
1286                         an[i].an_name.bv_val = slapi_ch_strdup(attrs[i]);
1287                         an[i].an_name.bv_len = strlen(attrs[i]);
1288                         slap_bv2ad( &an[i].an_name, &an[i].an_desc, &text );
1289                 }
1290                 an[i].an_name.bv_val = NULL;
1291         }
1292
1293         rs.sr_type = REP_RESULT;
1294         rs.sr_err = LDAP_SUCCESS;
1295         rs.sr_entry = NULL; /* paranoia */
1296
1297         if ( scope == LDAP_SCOPE_BASE ) {
1298                 rs.sr_entry = NULL;
1299
1300                 if ( op->o_req_ndn.bv_len == 0 ) {
1301                         rs.sr_err = root_dse_info( conn, &rs.sr_entry, &rs.sr_text );
1302                 }
1303
1304                 if( rs.sr_err != LDAP_SUCCESS ) {
1305                         send_ldap_result( op, &rs );
1306                         goto cleanup;
1307                 } else if ( rs.sr_entry != NULL ) {
1308                         rs.sr_err = test_filter( op, rs.sr_entry, filter );
1309
1310                         if ( rs.sr_err == LDAP_COMPARE_TRUE ) {
1311                                 rs.sr_type = REP_SEARCH;
1312                                 rs.sr_err = LDAP_SUCCESS;
1313                                 rs.sr_attrs = an;
1314                                 rs.sr_operational_attrs = NULL;
1315                                 rs.sr_flags = REP_ENTRY_MODIFIABLE;
1316
1317                                 send_search_entry( op, &rs );
1318                         }
1319
1320                         entry_free( rs.sr_entry );
1321
1322                         rs.sr_type = REP_RESULT;
1323                         rs.sr_err = LDAP_SUCCESS;
1324
1325                         send_ldap_result( op, &rs );
1326
1327                         goto cleanup;
1328                 }
1329         }
1330
1331         op->oq_search.rs_scope = scope;
1332         op->oq_search.rs_deref = 0;
1333         op->oq_search.rs_slimit = SLAP_NO_LIMIT;
1334         op->oq_search.rs_tlimit = SLAP_NO_LIMIT;
1335         op->oq_search.rs_attrsonly = attrsonly;
1336         op->oq_search.rs_attrs = an;
1337         op->oq_search.rs_filter = filter;
1338         op->oq_search.rs_filterstr = fstr;
1339
1340         if ( BER_BVISEMPTY( &op->o_req_ndn ) &&
1341              !BER_BVISEMPTY( &default_search_nbase ) ) {
1342                 slapi_ch_free( (void **)&op->o_req_dn.bv_val );
1343                 slapi_ch_free( (void **)&op->o_req_ndn.bv_val );
1344
1345                 ber_dupbv( &op->o_req_dn, &default_search_base );
1346                 ber_dupbv( &op->o_req_ndn, &default_search_nbase );
1347
1348                 rs.sr_err = slapi_int_pblock_get_backend( pb, op );
1349                 if ( rs.sr_err != LDAP_SUCCESS )
1350                         goto cleanup;
1351         }
1352
1353         if ( op->o_bd->be_search != NULL ) {
1354                 (*op->o_bd->be_search)( op, &rs );
1355         } else {
1356                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
1357         }
1358
1359 cleanup:
1360         slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_RESULT,            (void *)rs.sr_err );
1361         slapi_pblock_set( pb, SLAPI_X_INTOP_RESULT_CALLBACK,         NULL );
1362         slapi_pblock_set( pb, SLAPI_X_INTOP_SEARCH_ENTRY_CALLBACK,   NULL );
1363         slapi_pblock_set( pb, SLAPI_X_INTOP_REFERRAL_ENTRY_CALLBACK, NULL );
1364         slapi_pblock_set( pb, SLAPI_X_INTOP_CALLBACK_DATA,           NULL );
1365
1366         if ( freeFilter && filter != NULL )
1367                 slapi_filter_free( filter, 1 );
1368         if ( fstr.bv_val )
1369                 slapi_ch_free( (void **)&fstr.bv_val );
1370         if ( an != NULL )
1371                 slapi_ch_free( (void **)&an );
1372
1373         slapi_int_connection_destroy( &conn );
1374
1375         return 0;
1376 #else
1377         return -1;
1378 #endif /* LDAP_SLAPI */
1379 }
1380
1381 /* Wrappers for old API */
1382
1383 void slapi_search_internal_set_pb( Slapi_PBlock *pb,
1384         const char *base,
1385         int scope,
1386         const char *filter,
1387         char **attrs,
1388         int attrsonly,
1389         LDAPControl **controls,
1390         const char *uniqueid,
1391         Slapi_ComponentId *plugin_identity,
1392         int operation_flags )
1393 {
1394 #ifdef LDAP_SLAPI
1395         slapi_pblock_set( pb, SLAPI_SEARCH_TARGET,    (void *)base );
1396         slapi_pblock_set( pb, SLAPI_SEARCH_SCOPE,     (void *)scope );
1397         slapi_pblock_set( pb, SLAPI_SEARCH_FILTER,     NULL );
1398         slapi_pblock_set( pb, SLAPI_SEARCH_STRFILTER, (void *)filter );
1399         slapi_pblock_set( pb, SLAPI_SEARCH_ATTRS,     (void *)attrs );
1400         slapi_pblock_set( pb, SLAPI_SEARCH_ATTRSONLY, (void *)attrsonly );
1401         slapi_pblock_set( pb, SLAPI_REQCONTROLS,      (void *)controls );
1402         slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID,  (void *)uniqueid );
1403         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY,  (void *)plugin_identity );
1404         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,    (void *)operation_flags );
1405 #endif /* LDAP_SLAPI */
1406 }
1407
1408 Slapi_PBlock *
1409 slapi_search_internal(
1410         char *ldn, 
1411         int scope, 
1412         char *filStr, 
1413         LDAPControl **controls, 
1414         char **attrs, 
1415         int attrsonly ) 
1416 {
1417 #ifdef LDAP_SLAPI
1418         Slapi_PBlock *pb;
1419
1420         pb = slapi_pblock_new();
1421         if ( pb == NULL ) {
1422                 return NULL;
1423         }
1424
1425         slapi_search_internal_set_pb( pb, ldn, scope, filStr, attrs, attrsonly,
1426                 controls, NULL, NULL, 0 );
1427
1428         slapi_search_internal_pb( pb );
1429
1430         return pb;
1431 #else
1432         return NULL;
1433 #endif /* LDAP_SLAPI */
1434 }
1435
1436 void slapi_modify_internal_set_pb( Slapi_PBlock *pb,
1437         const char *dn,
1438         LDAPMod **mods,
1439         LDAPControl **controls,
1440         const char *uniqueid,
1441         Slapi_ComponentId *plugin_identity,
1442         int operation_flags )
1443 {
1444 #ifdef LDAP_SLAPI
1445         slapi_pblock_set( pb, SLAPI_MODIFY_TARGET,   (void *)dn );
1446         slapi_pblock_set( pb, SLAPI_MODIFY_MODS,     (void *)mods );
1447         slapi_pblock_set( pb, SLAPI_REQCONTROLS,     (void *)controls );
1448         slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID, (void *)uniqueid );
1449         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
1450         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,   (void *)operation_flags );
1451 #endif /* LDAP_SLAPI */
1452 }
1453
1454 /* Function : slapi_modify_internal
1455  *
1456  * Description: Plugin functions call this routine to modify an entry 
1457  *                              in the backend directly
1458  * Return values : LDAP_SUCCESS
1459  *                 LDAP_PARAM_ERROR
1460  *                 LDAP_NO_MEMORY
1461  *                 LDAP_OTHER
1462  *                 LDAP_UNWILLING_TO_PERFORM
1463 */
1464 Slapi_PBlock *
1465 slapi_modify_internal(
1466         char *ldn,      
1467         LDAPMod **mods, 
1468         LDAPControl **controls, 
1469         int log_change )
1470 {
1471 #ifdef LDAP_SLAPI
1472         Slapi_PBlock *pb;
1473
1474         pb = slapi_pblock_new();
1475         if ( pb == NULL ) {
1476                 return NULL;
1477         }
1478
1479         slapi_modify_internal_set_pb( pb, ldn, mods, controls, NULL, NULL,
1480                 log_change ? SLAPI_OP_FLAG_LOG_CHANGE : 0 );
1481
1482         slapi_modify_internal_pb( pb );
1483
1484         return pb;
1485 #else
1486         return NULL;
1487 #endif /* LDAP_SLAPI */
1488 }
1489
1490 int slapi_add_internal_set_pb( Slapi_PBlock *pb,
1491         const char *dn,
1492         LDAPMod **attrs,
1493         LDAPControl **controls,
1494         Slapi_ComponentId *plugin_identity,
1495         int operation_flags )
1496 {
1497 #ifdef LDAP_SLAPI
1498         slapi_pblock_set( pb, SLAPI_ADD_TARGET,      (void *)dn );
1499         slapi_pblock_set( pb, SLAPI_MODIFY_MODS,     (void *)attrs );
1500         slapi_pblock_set( pb, SLAPI_REQCONTROLS,     (void *)controls );
1501         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
1502         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,   (void *)operation_flags );
1503
1504         return 0;
1505 #else
1506         return -1;
1507 #endif /* LDAP_SLAPI */
1508 }
1509
1510 Slapi_PBlock *slapi_add_internal(
1511         char * dn,
1512         LDAPMod **attrs,
1513         LDAPControl **controls,
1514         int log_changes )
1515 {
1516 #ifdef LDAP_SLAPI
1517         Slapi_PBlock *pb;
1518
1519         pb = slapi_pblock_new();
1520         if ( pb == NULL )
1521                 return NULL;
1522
1523         slapi_add_internal_set_pb( pb, dn, attrs, controls, NULL,
1524                 log_changes ? SLAPI_OP_FLAG_LOG_CHANGE : 0 );
1525         
1526         slapi_add_internal_pb( pb );
1527
1528         return pb;
1529 #else
1530         return NULL;
1531 #endif /* LDAP_SLAPI */
1532 }
1533
1534 void slapi_add_entry_internal_set_pb( Slapi_PBlock *pb,
1535         Slapi_Entry *e,
1536         LDAPControl **controls,
1537         Slapi_ComponentId *plugin_identity,
1538         int operation_flags )
1539 {
1540 #ifdef LDAP_SLAPI
1541         slapi_pblock_set( pb, SLAPI_ADD_ENTRY,       (void *)e );
1542         slapi_pblock_set( pb, SLAPI_REQCONTROLS,     (void *)controls );
1543         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
1544         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,   (void *)operation_flags );
1545 #endif /* LDAP_SLAPI */
1546 }
1547
1548 Slapi_PBlock * 
1549 slapi_add_entry_internal(
1550         Slapi_Entry *e, 
1551         LDAPControl **controls, 
1552         int log_changes )
1553 {
1554 #ifdef LDAP_SLAPI
1555         Slapi_PBlock *pb;
1556
1557         pb = slapi_pblock_new();
1558         if ( pb == NULL )
1559                 return NULL;
1560
1561         slapi_add_entry_internal_set_pb( pb, e, controls, NULL,
1562                 log_changes ? SLAPI_OP_FLAG_LOG_CHANGE : 0 );
1563         
1564         slapi_add_internal_pb( pb );
1565
1566         return pb;
1567 #else
1568         return NULL;
1569 #endif /* LDAP_SLAPI */
1570 }
1571
1572 void slapi_rename_internal_set_pb( Slapi_PBlock *pb,
1573         const char *olddn,
1574         const char *newrdn,
1575         const char *newsuperior,
1576         int deloldrdn,
1577         LDAPControl **controls,
1578         const char *uniqueid,
1579         Slapi_ComponentId *plugin_identity,
1580         int operation_flags )
1581 {
1582 #ifdef LDAP_SLAPI
1583         slapi_pblock_set( pb, SLAPI_MODRDN_TARGET,      (void *)olddn );
1584         slapi_pblock_set( pb, SLAPI_MODRDN_NEWRDN,      (void *)newrdn );
1585         slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR, (void *)newsuperior );
1586         slapi_pblock_set( pb, SLAPI_MODRDN_DELOLDRDN,   (void *)deloldrdn );
1587         slapi_pblock_set( pb, SLAPI_REQCONTROLS,        (void *)controls );
1588         slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID,    (void *)uniqueid );
1589         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY,    (void *)plugin_identity );
1590         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,      (void *)operation_flags );
1591 #endif /* LDAP_SLAPI */
1592 }
1593
1594 /* Function : slapi_modrdn_internal
1595  *
1596  * Description : Plugin functions call this routine to modify the rdn 
1597  *                               of an entry in the backend directly
1598  * Return values : LDAP_SUCCESS
1599  *                 LDAP_PARAM_ERROR
1600  *                 LDAP_NO_MEMORY
1601  *                 LDAP_OTHER
1602  *                 LDAP_UNWILLING_TO_PERFORM
1603  *
1604  * NOTE: This function does not support the "newSuperior" option from LDAP V3.
1605  */
1606 Slapi_PBlock *
1607 slapi_modrdn_internal(
1608         char *olddn, 
1609         char *lnewrdn, 
1610         int deloldrdn, 
1611         LDAPControl **controls, 
1612         int log_change )
1613 {
1614 #ifdef LDAP_SLAPI
1615         Slapi_PBlock *pb;
1616
1617         pb = slapi_pblock_new();
1618         if ( pb == NULL ) {
1619                 return NULL;
1620         }
1621
1622         slapi_rename_internal_set_pb( pb, olddn, lnewrdn, NULL,
1623                 deloldrdn, controls, NULL, NULL,
1624                 log_change ? SLAPI_OP_FLAG_LOG_CHANGE : 0 );
1625
1626         slapi_modrdn_internal_pb( pb );
1627
1628         return pb;
1629 #else
1630         return NULL;
1631 #endif /* LDAP_SLAPI */
1632 }
1633
1634 void slapi_delete_internal_set_pb( Slapi_PBlock *pb,
1635         const char *dn,
1636         LDAPControl **controls,
1637         const char *uniqueid,
1638         Slapi_ComponentId *plugin_identity,
1639         int operation_flags )
1640 {
1641 #ifdef LDAP_SLAPI
1642         slapi_pblock_set( pb, SLAPI_TARGET_DN,       (void *)dn );
1643         slapi_pblock_set( pb, SLAPI_REQCONTROLS,     (void *)controls );
1644         slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID, (void *)uniqueid );
1645         slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
1646         slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,   (void *)operation_flags );
1647 #endif /* LDAP_SLAPI */
1648 }
1649
1650 /* Function : slapi_delete_internal
1651  *
1652  * Description : Plugin functions call this routine to delete an entry 
1653  *               in the backend directly
1654  * Return values : LDAP_SUCCESS
1655  *                 LDAP_PARAM_ERROR
1656  *                 LDAP_NO_MEMORY
1657  *                 LDAP_OTHER
1658  *                 LDAP_UNWILLING_TO_PERFORM
1659 */
1660 Slapi_PBlock *
1661 slapi_delete_internal(
1662         char *ldn, 
1663         LDAPControl **controls, 
1664         int log_change )
1665 {
1666 #ifdef LDAP_SLAPI
1667         Slapi_PBlock *pb;
1668
1669         pb = slapi_pblock_new();
1670         if ( pb == NULL )
1671                 return NULL;
1672
1673         slapi_delete_internal_set_pb( pb, ldn, controls, NULL, NULL,
1674                 log_change ? SLAPI_OP_FLAG_LOG_CHANGE : 0 );
1675
1676         slapi_delete_internal_pb( pb );
1677
1678         return pb;
1679 #else
1680         return NULL;
1681 #endif /* LDAP_SLAPI */
1682 }
1683