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