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