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