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