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