]> git.sur5r.net Git - openldap/blob - servers/slapd/slapi/slapi_ops.c
Consolidated slap_callbacks into one function. Removed send_search_result.
[openldap] / servers / slapd / slapi / slapi_ops.c
1 /*
2  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5 /*
6  * (C) Copyright IBM Corp. 1997,2002
7  * Redistribution and use in source and binary forms are permitted
8  * provided that this notice is preserved and that due credit is
9  * given to IBM Corporation. This software is provided ``as is''
10  * without express or implied warranty.
11  */
12 /*
13  * Portions (C) Copyright PADL Software Pty Ltd. 2003
14  * Redistribution and use in source and binary forms are permitted
15  * provided that this notice is preserved and that due credit is 
16  * given to PADL Software Pty Ltd. This software is provided ``as is'' 
17  * without express or implied warranty.
18  */
19
20 #include "portable.h"
21 #include <slap.h>
22 #include <lber_pvt.h>
23 #include <slapi.h>
24
25 /*
26  * use a fake listener when faking a connection,
27  * so it can be used in ACLs
28  */
29 static struct slap_listener slap_unknown_listener = {
30         BER_BVC("unknown"),     /* FIXME: use a URI form? */
31         BER_BVC("UNKNOWN")
32 };
33
34 int bvptr2obj( struct berval **bvptr, struct berval **bvobj );
35
36 static void
37 internal_result_v3(
38         Operation       *op, 
39         SlapReply       *rs )
40 {
41         if (op->o_tag == LDAP_REQ_SEARCH)
42                 slapi_pblock_set( (Slapi_PBlock *)op->o_pb,
43                         SLAPI_NENTRIES, (void *)sr->sr_nentries );
44
45         return;
46 }
47
48 static int
49 internal_search_entry(
50         Operation       *op,
51         SlapReply       *rs )
52 {
53         char *ent2str = NULL;
54         int nentries = 0, len = 0, i = 0;
55         Slapi_Entry **head = NULL, **tp;
56         
57         ent2str = slapi_entry2str( rs->sr_entry, &len );
58         if ( ent2str == NULL ) {
59                 return 1;
60         }
61
62         slapi_pblock_get( (Slapi_PBlock *)op->o_pb,
63                         SLAPI_NENTRIES, &nentries );
64         slapi_pblock_get( (Slapi_PBlock *)op->o_pb,
65                         SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &head );
66         
67         i = nentries + 1;
68         if ( nentries == 0 ) {
69                 tp = (Slapi_Entry **)slapi_ch_malloc( 2 * sizeof(Slapi_Entry *) );
70                 if ( tp == NULL ) {
71                         return 1;
72                 }
73
74                 tp[ 0 ] = (Slapi_Entry *)str2entry( ent2str );
75                 if ( tp[ 0 ] == NULL ) { 
76                         return 1;
77                 }
78
79         } else {
80                 tp = (Slapi_Entry **)slapi_ch_realloc( (char *)head,
81                                 sizeof(Slapi_Entry *) * ( i + 1 ) );
82                 if ( tp == NULL ) {
83                         return 1;
84                 }
85                 tp[ i - 1 ] = (Slapi_Entry *)str2entry( ent2str );
86                 if ( tp[ i - 1 ] == NULL ) { 
87                         return 1;
88                 }
89         }
90         tp[ i ] = NULL;
91                   
92         slapi_pblock_set( (Slapi_PBlock *)op->o_pb,
93                         SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, (void *)tp );
94         slapi_pblock_set( (Slapi_PBlock *)op->o_pb,
95                         SLAPI_NENTRIES, (void *)i );
96
97         return LDAP_SUCCESS;
98 }
99
100 static void
101 internal_result_ext(
102         Operation       *op,    
103         SlapReply       *sr )
104 {
105         return;
106 }
107
108 static int
109 internal_search_reference(
110         Operation       *op,    
111         SlapReply       *sr )
112 {
113         return LDAP_SUCCESS;
114 }
115
116 static Connection *
117 slapiConnectionInit(
118         char *DN, 
119         int OpType ) 
120
121         Connection *pConn, *c;
122         ber_len_t max = sockbuf_max_incoming;
123
124         pConn = (Connection *) slapi_ch_calloc(1, sizeof(Connection));
125         if (pConn == NULL) {
126                 return (Connection *)NULL;
127         }
128
129         LDAP_STAILQ_INIT( &pConn->c_pending_ops );
130
131         pConn->c_pending_ops.stqh_first =
132                 (Operation *) slapi_ch_calloc( 1, sizeof(Operation) );
133         if ( pConn->c_pending_ops.stqh_first == NULL ) { 
134                 slapi_ch_free( (void **)&pConn );
135                 return (Connection *)NULL;
136         }
137
138         pConn->c_pending_ops.stqh_first->o_pb = 
139                 (Slapi_PBlock *) slapi_pblock_new();
140         if ( pConn->c_pending_ops.stqh_first->o_pb == NULL ) {
141                 slapi_ch_free( (void **)&pConn->c_pending_ops.stqh_first );
142                 slapi_ch_free( (void **)&pConn );
143                 return (Connection *)NULL;
144         }
145
146         c = pConn;
147
148         /* operation object */
149         c->c_pending_ops.stqh_first->o_tag = OpType;
150         c->c_pending_ops.stqh_first->o_protocol = LDAP_VERSION3; 
151         c->c_pending_ops.stqh_first->o_authmech.bv_val = NULL; 
152         c->c_pending_ops.stqh_first->o_authmech.bv_len = 0; 
153         c->c_pending_ops.stqh_first->o_time = slap_get_time();
154         c->c_pending_ops.stqh_first->o_do_not_cache = 1;
155         c->c_pending_ops.stqh_first->o_threadctx = ldap_pvt_thread_pool_context( &connection_pool );
156
157         /* connection object */
158         c->c_authmech.bv_val = NULL;
159         c->c_authmech.bv_len = 0;
160         c->c_dn.bv_val = NULL;
161         c->c_dn.bv_len = 0;
162         c->c_ndn.bv_val = NULL;
163         c->c_ndn.bv_len = 0;
164         c->c_groups = NULL;
165
166         c->c_listener = &slap_unknown_listener;
167         ber_dupbv( &c->c_peer_domain, (struct berval *)&slap_unknown_bv );
168         ber_dupbv( &c->c_peer_name, (struct berval *)&slap_unknown_bv );
169
170         LDAP_STAILQ_INIT( &c->c_ops );
171
172         c->c_sasl_bind_mech.bv_val = NULL;
173         c->c_sasl_bind_mech.bv_len = 0;
174         c->c_sasl_context = NULL;
175         c->c_sasl_extra = NULL;
176
177         c->c_sb = ber_sockbuf_alloc( );
178
179         ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
180
181         c->c_currentber = NULL;
182
183         /* should check status of thread calls */
184         ldap_pvt_thread_mutex_init( &c->c_mutex );
185         ldap_pvt_thread_mutex_init( &c->c_write_mutex );
186         ldap_pvt_thread_cond_init( &c->c_write_cv );
187
188         c->c_n_ops_received = 0;
189         c->c_n_ops_executing = 0;
190         c->c_n_ops_pending = 0;
191         c->c_n_ops_completed = 0;
192
193         c->c_n_get = 0;
194         c->c_n_read = 0;
195         c->c_n_write = 0;
196
197         c->c_protocol = LDAP_VERSION3; 
198
199         c->c_activitytime = c->c_starttime = slap_get_time();
200
201         c->c_connid = 0;
202
203         c->c_conn_state  = 0x01;        /* SLAP_C_ACTIVE */
204         c->c_struct_state = 0x02;       /* SLAP_C_USED */
205
206         c->c_ssf = c->c_transport_ssf = 0;
207         c->c_tls_ssf = 0;
208
209         backend_connection_init( c );
210
211         pConn->c_send_ldap_result = internal_result_v3;
212         pConn->c_send_search_entry = internal_search_entry;
213         pConn->c_send_ldap_extended = internal_result_ext;
214         pConn->c_send_search_reference = internal_search_reference;
215
216         return pConn;
217 }
218
219 static void slapiConnectionDestroy( Connection **pConn )
220 {
221         Connection *conn = *pConn;
222         Operation *op;
223
224         if ( pConn == NULL ) {
225                 return;
226         }
227
228         op = (Operation *)conn->c_pending_ops.stqh_first;
229
230         if ( op->o_req_dn.bv_val != NULL ) {
231                 slapi_ch_free( (void **)&op->o_req_dn.bv_val );
232         }
233         if ( op->o_req_ndn.bv_val != NULL ) {
234                 slapi_ch_free( (void **)&op->o_req_ndn.bv_val );
235         }
236
237         if ( conn->c_sb != NULL ) {
238                 ber_sockbuf_free( conn->c_sb );
239         }
240         if ( op != NULL ) {
241                 slapi_ch_free( (void **)&op );
242         }
243         slapi_ch_free( (void **)pConn );
244 }
245
246 /*
247  * Function : values2obj
248  * Convert an array of strings into a BerVarray.
249  * the strings.
250  */
251 static int
252 values2obj(
253         char **ppValue,
254         BerVarray *bvobj)
255 {
256         int i;
257         BerVarray tmpberval;
258
259         if ( ppValue == NULL ) {
260                 *bvobj = NULL;
261                 return LDAP_SUCCESS;
262         }
263
264         for ( i = 0; ppValue[i] != NULL; i++ )
265                 ;
266
267         tmpberval = (BerVarray)slapi_ch_malloc( (i+1) * (sizeof(struct berval)) );
268         if ( tmpberval == NULL ) {
269                 return LDAP_NO_MEMORY;
270         }
271         for ( i = 0; ppValue[i] != NULL; i++ ) {
272                 tmpberval[i].bv_val = ppValue[i];
273                 tmpberval[i].bv_len = strlen( ppValue[i] );
274         }
275         tmpberval[i].bv_val = NULL;
276         tmpberval[i].bv_len = 0;
277
278         *bvobj = tmpberval;
279
280         return LDAP_SUCCESS;
281 }
282
283 static void
284 freeMods( Modifications *ml )
285 {
286         /*
287          * Free a modification list whose values have been 
288          * set with bvptr2obj() or values2obj() (ie. they
289          * do not own the pointer to the underlying values)
290          */
291         Modifications *next;
292
293         for ( ; ml != NULL; ml = next ) {
294                 next = ml->sml_next;
295
296                 slapi_ch_free( (void **)&ml->sml_bvalues );
297 #ifdef SLAP_NVALUES
298                 slapi_ch_free( (void **)&ml->sml_nvalues );
299 #endif
300                 slapi_ch_free( (void **)&ml );
301         }
302 }
303
304 /*
305  * Function : LDAPModToEntry 
306  * convert a dn plus an array of LDAPMod struct ptrs to an entry structure
307  * with a link list of the correspondent attributes.
308  * Return value : LDAP_SUCCESS
309  *                LDAP_NO_MEMORY
310  *                LDAP_OTHER
311 */
312 Entry *
313 LDAPModToEntry(
314         char *ldn, 
315         LDAPMod **mods )
316 {
317         struct berval           dn = { 0, NULL };
318         Entry                   *pEntry=NULL;
319         LDAPMod                 *pMod;
320         struct berval           *bv;
321         Backend                 *be;
322         Operation               *op;
323
324         Modifications           *modlist = NULL;
325         Modifications           **modtail = &modlist;
326         Modifications           tmp;
327
328         int                     rc = LDAP_SUCCESS;
329         int                     i;
330
331         const char              *text = NULL;
332
333
334         op = (Operation *) slapi_ch_calloc(1, sizeof(Operation));
335         if ( pEntry == NULL) {
336                 rc = LDAP_NO_MEMORY;
337                 goto cleanup;
338         }  
339         op->o_tag = LDAP_REQ_ADD;
340
341         pEntry = (Entry *) ch_calloc( 1, sizeof(Entry) );
342         if ( pEntry == NULL) {
343                 rc = LDAP_NO_MEMORY;
344                 goto cleanup;
345         } 
346
347         dn.bv_val = slapi_ch_strdup(ldn);
348         dn.bv_len = strlen(ldn);
349
350         rc = dnPrettyNormal( NULL, &dn, &pEntry->e_name, &pEntry->e_nname );
351         if ( rc != LDAP_SUCCESS )
352                 goto cleanup;
353
354         if ( rc == LDAP_SUCCESS ) {
355                 for ( i=0, pMod=mods[0]; rc == LDAP_SUCCESS && pMod != NULL; pMod=mods[++i]) {
356                         Modifications *mod;
357                         if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {
358                                 /* attr values are in berval format */
359                                 /* convert an array of pointers to bervals to an array of bervals */
360                                 rc = bvptr2obj(pMod->mod_bvalues, &bv);
361                                 if (rc != LDAP_SUCCESS) goto cleanup;
362                                 tmp.sml_type.bv_val = pMod->mod_type;
363                                 tmp.sml_type.bv_len = strlen( pMod->mod_type );
364                                 tmp.sml_bvalues = bv;
365 #ifdef SLAP_NVALUES
366                                 tmp.sml_nvalues = NULL;
367 #endif
368                 
369                                 mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
370
371                                 mod->sml_op = LDAP_MOD_ADD;
372                                 mod->sml_next = NULL;
373                                 mod->sml_desc = NULL;
374                                 mod->sml_type = tmp.sml_type;
375                                 mod->sml_bvalues = tmp.sml_bvalues;
376 #ifdef SLAP_NVALUES
377                                 mod->sml_nvalues = tmp.sml_nvalues;
378 #endif
379
380                                 *modtail = mod;
381                                 modtail = &mod->sml_next;
382
383                         } else {
384                                 /* attr values are in string format, need to be converted */
385                                 /* to an array of bervals */ 
386                                 if ( pMod->mod_values == NULL ) {
387                                         rc = LDAP_OTHER;
388                                 } else {
389                                         rc = values2obj( pMod->mod_values, &bv );
390                                         if (rc != LDAP_SUCCESS) goto cleanup;
391                                         tmp.sml_type.bv_val = pMod->mod_type;
392                                         tmp.sml_type.bv_len = strlen( pMod->mod_type );
393                                         tmp.sml_bvalues = bv;
394 #ifdef SLAP_NVALUES
395                                         tmp.sml_nvalues = NULL;
396 #endif
397                 
398                                         mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
399
400                                         mod->sml_op = LDAP_MOD_ADD;
401                                         mod->sml_next = NULL;
402                                         mod->sml_desc = NULL;
403                                         mod->sml_type = tmp.sml_type;
404                                         mod->sml_bvalues = tmp.sml_bvalues;
405 #ifdef SLAP_NVALUES
406                                         mod->sml_nvalues = tmp.sml_nvalues;
407 #endif
408
409                                         *modtail = mod;
410                                         modtail = &mod->sml_next;
411                                 }
412                         }
413                 } /* for each LDAPMod */
414         }
415
416         be = select_backend(&pEntry->e_nname, 0, 0);
417         if ( be == NULL ) {
418                 rc =  LDAP_PARTIAL_RESULTS;
419                 goto cleanup;
420         }
421
422         if ( be ) {
423                 int repl_user = be_isupdate(be, &be->be_rootdn );
424                 if ( !be->be_update_ndn.bv_len || repl_user ) {
425                         int update = be->be_update_ndn.bv_len;
426                         char textbuf[SLAP_TEXT_BUFLEN];
427                         size_t textlen = sizeof textbuf;
428
429                         rc = slap_mods_check( modlist, update, &text, 
430                                         textbuf, textlen );
431                         if ( rc != LDAP_SUCCESS) {
432                                 goto cleanup;
433                         }
434
435                         if ( !repl_user ) {
436                                 rc = slap_mods_opattrs( op,
437                                                 modlist, modtail, &text, 
438                                                 textbuf, textlen );
439                                 if ( rc != LDAP_SUCCESS) {
440                                         goto cleanup;
441                                 }
442                         }
443
444                         /*
445                          * FIXME: slap_mods2entry is declared static 
446                          * in servers/slapd/add.c
447                          */
448                         rc = slap_mods2entry( modlist, &pEntry, repl_user,
449                                         &text, textbuf, textlen );
450                         if (rc != LDAP_SUCCESS) {
451                                 goto cleanup;
452                         }
453
454                 } else {
455                         rc = LDAP_REFERRAL;
456                 }
457         } else {
458                 rc = LDAP_UNWILLING_TO_PERFORM;
459         }
460
461 cleanup:
462
463         if ( dn.bv_val )
464                 slapi_ch_free( (void **)&dn.bv_val );
465         if ( op )
466                 slapi_ch_free( (void **)&op );
467         if ( modlist != NULL )
468                 freeMods( modlist );
469         if ( rc != LDAP_SUCCESS ) {
470                 if ( pEntry != NULL ) {
471                         slapi_entry_free( pEntry );
472                 }
473                 pEntry = NULL;
474         }
475
476         return( pEntry );
477 }
478
479 /* Function : slapi_delete_internal
480  *
481  * Description : Plugin functions call this routine to delete an entry 
482  *               in the backend directly
483  * Return values : LDAP_SUCCESS
484  *                 LDAP_PARAM_ERROR
485  *                 LDAP_NO_MEMORY
486  *                 LDAP_OTHER
487  *                 LDAP_UNWILLING_TO_PERFORM
488 */
489 Slapi_PBlock *
490 slapi_delete_internal(
491         char *ldn, 
492         LDAPControl **controls, 
493         int log_change )
494 {
495 #ifdef LDAP_SLAPI
496         Backend                 *be;
497         Connection              *pConn = NULL;
498         Operation               *op = NULL;
499         Slapi_PBlock            *pPB = NULL;
500         Slapi_PBlock            *pSavePB = NULL;
501         SlapReply               rs = { REP_RESULT };
502         struct berval           dn = { 0, NULL };
503
504         int                     manageDsaIt = 0;
505         int                     isCritical;
506
507         if ( ldn == NULL ) {
508                 rs.sr_err = LDAP_PARAM_ERROR; 
509                 goto cleanup;
510         }
511
512         pConn = slapiConnectionInit( NULL, LDAP_REQ_DELETE );
513         if (pConn == NULL) {
514                 rs.sr_err = LDAP_NO_MEMORY;
515                 goto cleanup;
516         }
517
518         op = (Operation *)pConn->c_pending_ops.stqh_first;
519         pPB = (Slapi_PBlock *)op->o_pb;
520         op->o_ctrls = controls;
521
522         dn.bv_val = slapi_ch_strdup(ldn);
523         dn.bv_len = strlen(ldn);
524         rs.sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn );
525         if ( rs.sr_err != LDAP_SUCCESS )
526                 goto cleanup;
527
528         if ( slapi_control_present( controls, 
529                         SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical) ) {
530                 manageDsaIt = 1; 
531         }
532
533         be = select_backend( &op->o_req_ndn, manageDsaIt, 0 );
534         if ( be == NULL ) {
535                 rs.sr_err = LDAP_PARTIAL_RESULTS;
536                 goto cleanup;
537         }
538
539         op->o_dn = pConn->c_dn = be->be_rootdn;
540         op->o_ndn = pConn->c_ndn = be->be_rootndn;
541
542         if ( be->be_delete ) {
543                 int repl_user = be_isupdate( be, &op->o_ndn );
544                 if ( !be->be_update_ndn.bv_len || repl_user ) {
545                         if ( (*be->be_delete)( op, &rs ) == 0 ) {
546                                 if ( log_change ) {
547                                         replog( op );
548                                 }
549                         } else {
550                                 rs.sr_err = LDAP_OTHER;
551                         }
552                 } else {
553                         rs.sr_err = LDAP_REFERRAL;
554                 }
555         } else {
556                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
557         }
558
559 cleanup:
560         if ( pPB != NULL ) {
561                 slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rs.sr_err );
562         }
563         if ( dn.bv_val ) {
564                 slapi_ch_free( (void **)&dn.bv_val );
565         }
566         if ( pConn != NULL ) {
567                 pSavePB = pPB;
568         }
569
570         slapiConnectionDestroy( &pConn );
571
572         return (pSavePB);
573 #else
574         return NULL;
575 #endif /* LDAP_SLAPI */
576 }
577
578 Slapi_PBlock * 
579 slapi_add_entry_internal(
580         Slapi_Entry *e, 
581         LDAPControl **controls, 
582         int log_changes ) 
583 {
584 #ifdef LDAP_SLAPI
585         Connection              *pConn = NULL;
586         Operation               *op = NULL;
587         Slapi_PBlock            *pPB = NULL, *pSavePB = NULL;
588         Backend                 *be;
589
590         int                     manageDsaIt = 0;
591         int                     isCritical;
592         SlapReply               rs = { REP_RESULT };
593
594         if ( e == NULL ) {
595                 rs.sr_err = LDAP_PARAM_ERROR;
596                 goto cleanup;
597         }
598         
599         pConn = slapiConnectionInit( NULL, LDAP_REQ_ADD );
600         if ( pConn == NULL ) {
601                 rs.sr_err = LDAP_NO_MEMORY;
602                 goto cleanup;
603         }
604
605         if ( slapi_control_present( controls, LDAP_CONTROL_MANAGEDSAIT,
606                                 NULL, &isCritical ) ) {
607                 manageDsaIt = 1; 
608         }
609
610         op = (Operation *)pConn->c_pending_ops.stqh_first;
611         pPB = (Slapi_PBlock *)op->o_pb;
612         op->o_ctrls = controls;
613
614         be = select_backend( &e->e_nname, manageDsaIt, 0 );
615         if ( be == NULL ) {
616                 rs.sr_err = LDAP_PARTIAL_RESULTS;
617                 goto cleanup;
618         }
619
620         op->o_dn = pConn->c_dn = be->be_rootdn;
621         op->o_ndn = pConn->c_ndn = be->be_rootndn;
622         op->oq_add.rs_e = e;
623
624         if ( be->be_add ) {
625                 int repl_user = be_isupdate( be, &op->o_ndn );
626                 if ( !be->be_update_ndn.bv_len || repl_user ){
627                         if ( (*be->be_add)( op, &rs ) == 0 ) {
628                                 if ( log_changes ) {
629                                         replog( op );
630                                 }
631                         }
632                 } else {
633                         rs.sr_err = LDAP_REFERRAL;
634                 }
635         } else {
636                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
637         }
638
639 cleanup:
640
641         if ( pPB != NULL ) {
642                 slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rs.sr_err );
643         }
644
645         if ( pConn != NULL ) {
646                 pSavePB = pPB;
647         }
648
649         slapiConnectionDestroy( &pConn );
650
651         return( pSavePB );
652 #else
653         return NULL;
654 #endif /* LDAP_SLAPI */
655 }
656
657
658 Slapi_PBlock *
659 slapi_add_internal(
660         char *dn, 
661         LDAPMod **mods, 
662         LDAPControl **controls, 
663         int log_changes  ) 
664 {
665 #ifdef LDAP_SLAPI
666         LDAPMod                 *pMod = NULL;
667         Slapi_PBlock            *pb = NULL;
668         Entry                   *pEntry = NULL;
669         int                     i, rc = LDAP_SUCCESS;
670
671         if ( mods == NULL || *mods == NULL || dn == NULL || *dn == '\0' ) {
672                 rc = LDAP_PARAM_ERROR ;
673         }
674
675         if ( rc == LDAP_SUCCESS ) {
676                 for ( i = 0, pMod = mods[0]; pMod != NULL; pMod = mods[++i] ) {
677                         if ( (pMod->mod_op & ~LDAP_MOD_BVALUES) != LDAP_MOD_ADD ) {
678                                 rc = LDAP_OTHER;
679                                 break;
680                         }
681                 }
682         }
683
684         if ( rc == LDAP_SUCCESS ) {
685                 if((pEntry = LDAPModToEntry( dn, mods )) == NULL) {
686                         rc = LDAP_OTHER;
687                 }
688         }
689
690         if ( rc != LDAP_SUCCESS ) {
691                 pb = slapi_pblock_new();
692                 slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
693         } else {
694                 pb = slapi_add_entry_internal( pEntry, controls, log_changes );
695         }
696
697         if ( pEntry ) {
698                 slapi_entry_free(pEntry);
699         }
700
701         return(pb);
702 #else
703         return NULL;
704 #endif /* LDAP_SLAPI */
705 }
706
707 /* Function : slapi_modrdn_internal
708  *
709  * Description : Plugin functions call this routine to modify the rdn 
710  *                               of an entry in the backend directly
711  * Return values : LDAP_SUCCESS
712  *                 LDAP_PARAM_ERROR
713  *                 LDAP_NO_MEMORY
714  *                 LDAP_OTHER
715  *                 LDAP_UNWILLING_TO_PERFORM
716  *
717  * NOTE: This function does not support the "newSuperior" option from LDAP V3.
718  */
719 Slapi_PBlock *
720 slapi_modrdn_internal(
721         char *olddn, 
722         char *lnewrdn, 
723         int deloldrdn, 
724         LDAPControl **controls, 
725         int log_change )
726 {
727 #ifdef LDAP_SLAPI
728         struct berval           dn = { 0, NULL };
729         struct berval           newrdn = { 0, NULL };
730         Connection              *pConn = NULL;
731         Operation               *op = NULL;
732         Slapi_PBlock            *pPB = NULL;
733         Slapi_PBlock            *pSavePB = NULL;
734         Backend                 *be;
735         int                     manageDsaIt = 0;
736         int                     isCritical;
737         SlapReply               rs = { REP_RESULT };
738
739         pConn = slapiConnectionInit( NULL,  LDAP_REQ_MODRDN);
740         if ( pConn == NULL) {
741                 rs.sr_err = LDAP_NO_MEMORY;
742                 goto cleanup;
743         }
744
745         op = (Operation *)pConn->c_pending_ops.stqh_first;
746         pPB = (Slapi_PBlock *)op->o_pb;
747         op->o_ctrls = controls;
748
749         if ( slapi_control_present( controls, 
750                         SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical ) ) {
751                 manageDsaIt = 1;
752         }
753
754         be = select_backend( &op->o_req_ndn, manageDsaIt, 0 );
755         if ( be == NULL ) {
756                 rs.sr_err =  LDAP_PARTIAL_RESULTS;
757                 goto cleanup;
758         }
759
760         op->o_dn = pConn->c_dn = be->be_rootdn;
761         op->o_ndn = pConn->c_ndn = be->be_rootndn;
762
763         dn.bv_val = slapi_ch_strdup( olddn );
764         dn.bv_len = strlen( olddn );
765
766         rs.sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn );
767         if ( rs.sr_err != LDAP_SUCCESS ) {
768                 goto cleanup;
769         }
770
771         if ( op->o_req_dn.bv_len == 0 ) {
772                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
773                 goto cleanup;
774         }
775
776         newrdn.bv_val = slapi_ch_strdup( lnewrdn );
777         newrdn.bv_len = strlen( lnewrdn );
778
779         rs.sr_err = dnPrettyNormal( NULL, &newrdn, &op->oq_modrdn.rs_newrdn, &op->oq_modrdn.rs_nnewrdn );
780         if ( rs.sr_err != LDAP_SUCCESS ) {
781                 goto cleanup;
782         }
783
784         if ( rdnValidate( &op->oq_modrdn.rs_nnewrdn ) != LDAP_SUCCESS ) {
785                 goto cleanup;
786         }
787
788         op->oq_modrdn.rs_newSup = NULL;
789         op->oq_modrdn.rs_nnewSup = NULL;
790         op->oq_modrdn.rs_deleteoldrdn = deloldrdn;
791
792         if ( be->be_modrdn ) {
793                 int repl_user = be_isupdate( be, &op->o_ndn );
794                 if ( !be->be_update_ndn.bv_len || repl_user ) {
795                         if ( (*be->be_modrdn)( op, &rs ) == 0 ) {
796                                 if ( log_change ) {
797                                         replog( op );
798                                 }
799                         } else {
800                                 rs.sr_err = LDAP_OTHER;
801                         }
802                 } else {
803                         rs.sr_err = LDAP_REFERRAL;
804                 }
805         } else {
806                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
807         }
808
809 cleanup:
810
811         if ( pPB != NULL ) {
812                 slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rs.sr_err );
813         }
814         
815         if ( dn.bv_val )
816                 slapi_ch_free( (void **)&dn.bv_val );
817
818         if ( newrdn.bv_val )
819                 slapi_ch_free( (void **)&newrdn.bv_val );
820         if ( op->oq_modrdn.rs_newrdn.bv_val )
821                 slapi_ch_free( (void **)&op->oq_modrdn.rs_newrdn.bv_val );
822         if ( op->oq_modrdn.rs_nnewrdn.bv_val )
823                 slapi_ch_free( (void **)&op->oq_modrdn.rs_nnewrdn.bv_val );
824
825         if ( pConn != NULL ) {
826                 pSavePB = pPB;
827         }
828
829         slapiConnectionDestroy( &pConn );
830
831         return( pSavePB );
832 #else
833         return NULL;
834 #endif /* LDAP_SLAPI */
835 }
836
837 /* Function : slapi_modify_internal
838  *
839  * Description: Plugin functions call this routine to modify an entry 
840  *                              in the backend directly
841  * Return values : LDAP_SUCCESS
842  *                 LDAP_PARAM_ERROR
843  *                 LDAP_NO_MEMORY
844  *                 LDAP_OTHER
845  *                 LDAP_UNWILLING_TO_PERFORM
846 */
847 Slapi_PBlock *
848 slapi_modify_internal(
849         char *ldn,      
850         LDAPMod **mods, 
851         LDAPControl **controls, 
852         int log_change )
853 {
854 #ifdef LDAP_SLAPI
855         int                     i;
856         Connection              *pConn = NULL;
857         Operation               *op = NULL;
858         Slapi_PBlock            *pPB = NULL;
859         Slapi_PBlock            *pSavePB = NULL;
860
861         struct berval dn = { 0, NULL };
862
863         int                     manageDsaIt = 0;
864         int                     isCritical;
865         Backend                 *be;
866         struct berval           *bv;
867         LDAPMod                 *pMod;
868
869         Modifications           *modlist = NULL;
870         Modifications           **modtail = &modlist;
871         Modifications           tmp;
872
873         SlapReply               rs = { REP_RESULT };
874
875         if ( mods == NULL || *mods == NULL || ldn == NULL ) {
876                 rs.sr_err = LDAP_PARAM_ERROR ;
877                 goto cleanup;
878         }
879
880         pConn = slapiConnectionInit( NULL,  LDAP_REQ_MODIFY );
881         if ( pConn == NULL ) {
882                 rs.sr_err = LDAP_NO_MEMORY;
883                 goto cleanup;
884         }
885
886         op = (Operation *)pConn->c_pending_ops.stqh_first;
887         pPB = (Slapi_PBlock *)op->o_pb;
888         op->o_ctrls = controls;
889
890         dn.bv_val = slapi_ch_strdup( ldn );
891         dn.bv_len = strlen( ldn );
892         rs.sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn );
893         if ( rs.sr_err != LDAP_SUCCESS ) {
894                 goto cleanup;
895         }
896
897         if ( slapi_control_present( controls, 
898                         SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical ) ) {
899                 manageDsaIt = 1;
900         }
901
902         be = select_backend( &op->o_req_ndn, manageDsaIt, 0 );
903         if ( be == NULL ) {
904                 rs.sr_err = LDAP_PARTIAL_RESULTS;
905                 goto cleanup;
906         }
907
908         op->o_dn = pConn->c_dn = be->be_rootdn;
909         op->o_ndn = pConn->c_ndn = be->be_rootndn;
910
911         for ( i = 0, pMod = mods[0];
912                 rs.sr_err == LDAP_SUCCESS && pMod != NULL; 
913                 pMod = mods[++i] )
914         {
915                 Modifications *mod;
916
917                 if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {
918                         /*
919                          * attr values are in berval format
920                          * convert an array of pointers to bervals
921                          * to an array of bervals
922                          */
923                         rs.sr_err = bvptr2obj( pMod->mod_bvalues, &bv );
924                         if ( rs.sr_err != LDAP_SUCCESS )
925                                 goto cleanup;
926                         tmp.sml_type.bv_val = pMod->mod_type;
927                         tmp.sml_type.bv_len = strlen( pMod->mod_type );
928                         tmp.sml_bvalues = bv;
929 #ifdef SLAP_NVALUES
930                         tmp.sml_nvalues = NULL;
931 #endif
932
933                         mod  = (Modifications *)ch_malloc( sizeof(Modifications) );
934
935                         mod->sml_op = pMod->mod_op;
936                         mod->sml_next = NULL;
937                         mod->sml_desc = NULL;
938                         mod->sml_type = tmp.sml_type;
939                         mod->sml_bvalues = tmp.sml_bvalues;
940 #ifdef SLAP_NVALUES
941                         mod->sml_nvalues = tmp.sml_nvalues;
942 #endif
943                 } else { 
944                         rs.sr_err = values2obj( pMod->mod_values, &bv );
945                         if ( rs.sr_err != LDAP_SUCCESS )
946                                 goto cleanup;
947                         tmp.sml_type.bv_val = pMod->mod_type;
948                         tmp.sml_type.bv_len = strlen( pMod->mod_type );
949                         tmp.sml_bvalues = bv;
950 #ifdef SLAP_NVALUES
951                         tmp.sml_nvalues = NULL;
952 #endif
953
954                         mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
955
956                         mod->sml_op = pMod->mod_op;
957                         mod->sml_next = NULL;
958                         mod->sml_desc = NULL;
959                         mod->sml_type = tmp.sml_type;
960                         mod->sml_bvalues = tmp.sml_bvalues;
961 #ifdef SLAP_NVALUES
962                         mod->sml_nvalues = tmp.sml_nvalues;
963 #endif
964                 }
965                 *modtail = mod;
966                 modtail = &mod->sml_next;
967
968                 switch( pMod->mod_op ) {
969                 case LDAP_MOD_ADD:
970                 if ( mod->sml_bvalues == NULL ) {
971                         rs.sr_err = LDAP_PROTOCOL_ERROR;
972                         goto cleanup;
973                 }
974
975                 /* fall through */
976                 case LDAP_MOD_DELETE:
977                 case LDAP_MOD_REPLACE:
978                 break;
979
980                 default:
981                         rs.sr_err = LDAP_PROTOCOL_ERROR;
982                         goto cleanup;
983                 }
984         } 
985         *modtail = NULL;
986
987         if ( op->o_req_ndn.bv_len == 0 ) {
988                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
989                 goto cleanup;
990         }
991
992         op->oq_modify.rs_modlist = modlist;
993
994         if ( be->be_modify ) {
995                 int repl_user = be_isupdate( be, &op->o_ndn );
996                 if ( !be->be_update_ndn.bv_len || repl_user ) {
997                         int update = be->be_update_ndn.bv_len;
998                         const char *text = NULL;
999                         char textbuf[SLAP_TEXT_BUFLEN];
1000                         size_t textlen = sizeof( textbuf );
1001
1002                         rs.sr_err = slap_mods_check( modlist, update,
1003                                         &text, textbuf, textlen );
1004                         if ( rs.sr_err != LDAP_SUCCESS ) {
1005                                 goto cleanup;
1006                         }
1007
1008                         if ( !repl_user ) {
1009                                 rs.sr_err = slap_mods_opattrs( op, modlist,
1010                                                 modtail, &text, textbuf, 
1011                                                 textlen );
1012                                 if ( rs.sr_err != LDAP_SUCCESS ) {
1013                                         goto cleanup;
1014                                 }
1015                         }
1016                         if ( (*be->be_modify)( op, &rs ) == 0 ) {
1017                                 if ( log_change ) {
1018                                         replog( op );
1019                                 }
1020                         } else {
1021                                 rs.sr_err = LDAP_OTHER;
1022                         }
1023                 } else {
1024                         rs.sr_err = LDAP_REFERRAL;
1025                 }
1026         } else {
1027                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
1028         }
1029
1030 cleanup:
1031
1032         if ( pPB != NULL ) 
1033                 slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rs.sr_err );
1034
1035         if ( dn.bv_val )
1036                 slapi_ch_free( (void **)&dn.bv_val );
1037
1038         if ( modlist != NULL )
1039                 freeMods( modlist );
1040
1041         if ( pConn != NULL ) {
1042                 pSavePB = pPB;
1043         }
1044
1045         slapiConnectionDestroy( &pConn );
1046
1047         return ( pSavePB );
1048 #else
1049         return NULL;
1050 #endif /* LDAP_SLAPI */
1051 }
1052
1053 Slapi_PBlock *
1054 slapi_search_internal_bind(
1055         char *bindDN, 
1056         char *ldn, 
1057         int scope, 
1058         char *filStr, 
1059         LDAPControl **controls, 
1060         char **attrs, 
1061         int attrsonly ) 
1062 {       
1063 #ifdef LDAP_SLAPI
1064         Backend                 *be;
1065         Connection              *c;
1066         Operation               *op = NULL;
1067         Slapi_PBlock            *ptr = NULL;            
1068         Slapi_PBlock            *pSavePB = NULL;                
1069         struct berval           dn = { 0, NULL };
1070         Filter                  *filter=NULL;
1071         struct berval           fstr = { 0, NULL };
1072         AttributeName           *an = NULL;
1073         const char              *text = NULL;
1074
1075         int                     manageDsaIt = 0; 
1076         int                     isCritical;
1077         int                     i;
1078
1079         SlapReply               rs = { REP_RESULT };
1080
1081         c = slapiConnectionInit( NULL, LDAP_REQ_SEARCH );
1082         if ( c == NULL ) {
1083                 rs.sr_err = LDAP_NO_MEMORY;
1084                 goto cleanup;
1085         }
1086
1087         op = (Operation *)c->c_pending_ops.stqh_first;
1088         ptr = (Slapi_PBlock *)op->o_pb;
1089         op->o_ctrls = controls;
1090
1091         dn.bv_val = slapi_ch_strdup(ldn);
1092         dn.bv_len = strlen(ldn);
1093
1094         rs.sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn );
1095         if ( rs.sr_err != LDAP_SUCCESS ) {
1096                 goto cleanup;
1097         }
1098
1099         if ( scope != LDAP_SCOPE_BASE && 
1100                         scope != LDAP_SCOPE_ONELEVEL && 
1101                         scope != LDAP_SCOPE_SUBTREE ) {
1102                 rs.sr_err = LDAP_PROTOCOL_ERROR;
1103                 goto cleanup;
1104         }
1105
1106         filter = slapi_str2filter(filStr);
1107         if ( filter == NULL ) {
1108                 rs.sr_err = LDAP_PROTOCOL_ERROR;
1109                 goto cleanup;
1110         }
1111
1112         filter2bv( filter, &fstr );
1113
1114         for ( i = 0; attrs != NULL && attrs[i] != NULL; i++ ) {
1115                 ; /* count the number of attributes */
1116         }
1117
1118         if (i > 0) {
1119                 an = (AttributeName *)slapi_ch_calloc( (i + 1), sizeof(AttributeName) );
1120                 for (i = 0; attrs[i] != 0; i++) {
1121                         an[i].an_desc = NULL;
1122                         an[i].an_oc = NULL;
1123                         an[i].an_name.bv_val = slapi_ch_strdup(attrs[i]);
1124                         an[i].an_name.bv_len = strlen(attrs[i]);
1125                         slap_bv2ad( &an[i].an_name, &an[i].an_desc, &text );
1126                 }
1127                 an[i].an_name.bv_val = NULL;
1128         }
1129
1130         memset( &rs, 0, sizeof(rs) );
1131         rs.sr_type = REP_RESULT;
1132         rs.sr_err = LDAP_SUCCESS;
1133         rs.sr_entry = NULL; /* paranoia */
1134
1135         if ( scope == LDAP_SCOPE_BASE ) {
1136                 rs.sr_entry = NULL;
1137
1138                 if ( op->o_req_ndn.bv_len == 0 ) {
1139                         rs.sr_err = root_dse_info( c, &rs.sr_entry, &rs.sr_text );
1140                 }
1141
1142                 if( rs.sr_err != LDAP_SUCCESS ) {
1143                         send_ldap_result( op, &rs );
1144                         goto cleanup;
1145                 } else if ( rs.sr_entry != NULL ) {
1146                         rs.sr_err = test_filter( op, rs.sr_entry, filter );
1147
1148                         if ( rs.sr_err == LDAP_COMPARE_TRUE ) {
1149                                 rs.sr_type = REP_SEARCH;
1150                                 rs.sr_err = LDAP_SUCCESS;
1151                                 rs.sr_attrs = an;
1152
1153                                 send_search_entry( op, &rs );
1154                         }
1155
1156                         entry_free( rs.sr_entry );
1157
1158                         rs.sr_type = REP_RESULT;
1159                         rs.sr_err = LDAP_SUCCESS;
1160
1161                         send_ldap_result( op, &rs );
1162
1163                         goto cleanup;
1164                 }
1165         }
1166
1167         if ( !op->o_req_ndn.bv_len && default_search_nbase.bv_len ) {
1168                 slapi_ch_free( (void **)op->o_req_dn.bv_val );
1169                 slapi_ch_free( (void **)op->o_req_ndn.bv_val );
1170
1171                 ber_dupbv( &op->o_req_dn, &default_search_base );
1172                 ber_dupbv( &op->o_req_ndn, &default_search_nbase );
1173         }
1174
1175         if ( slapi_control_present( controls,
1176                         LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) {
1177                 manageDsaIt = 1;
1178         }
1179
1180         be = select_backend( &op->o_req_ndn, manageDsaIt, 0 );
1181         if ( be == NULL ) {
1182                 if ( manageDsaIt == 1 ) {
1183                         rs.sr_err = LDAP_NO_SUCH_OBJECT;
1184                 } else {
1185                         rs.sr_err = LDAP_PARTIAL_RESULTS;
1186                 }
1187                 goto cleanup;
1188         } 
1189
1190         op->o_dn = c->c_dn = be->be_rootdn;
1191         op->o_ndn = c->c_ndn = be->be_rootndn;
1192
1193         op->oq_search.rs_scope = scope;
1194         op->oq_search.rs_deref = 0;
1195         op->oq_search.rs_slimit = LDAP_NO_LIMIT;
1196         op->oq_search.rs_tlimit = LDAP_NO_LIMIT;
1197         op->oq_search.rs_attrsonly = attrsonly;
1198         op->oq_search.rs_attrs = an;
1199         op->oq_search.rs_filter = filter;
1200         op->oq_search.rs_filterstr = fstr;
1201
1202         if ( be->be_search ) {
1203                 if ( (*be->be_search)( op, &rs ) != 0 ) {
1204                         rs.sr_err = LDAP_OTHER;
1205                 }
1206         } else {
1207                 rs.sr_err = LDAP_UNWILLING_TO_PERFORM;
1208         }
1209
1210 cleanup:
1211
1212         if ( ptr != NULL )
1213                 slapi_pblock_set( ptr, SLAPI_PLUGIN_INTOP_RESULT, (void *)rs.sr_err );
1214
1215         if ( dn.bv_val )
1216                 slapi_ch_free( (void **)&dn.bv_val );
1217         if ( filter )
1218                 slapi_filter_free( filter, 1 );
1219         if ( fstr.bv_val )
1220                 slapi_ch_free( (void **)&fstr.bv_val );
1221         if ( an != NULL )
1222                 slapi_ch_free( (void **)&an );
1223
1224         if ( c != NULL ) {
1225                 pSavePB = ptr;
1226         }
1227
1228         slapiConnectionDestroy( &c );
1229
1230         return( pSavePB );
1231 #else
1232         return NULL;
1233 #endif /* LDAP_SLAPI */
1234 }
1235
1236 Slapi_PBlock * 
1237 slapi_search_internal(
1238         char *base,
1239         int scope,
1240         char *filStr, 
1241         LDAPControl **controls,
1242         char **attrs,
1243         int attrsonly ) 
1244 {
1245 #ifdef LDAP_SLAPI
1246         return slapi_search_internal_bind( NULL, base, scope, filStr,
1247                         controls, attrs, attrsonly );
1248 #else
1249         return NULL;
1250 #endif /* LDAP_SLAPI */
1251 }
1252