]> git.sur5r.net Git - openldap/blob - servers/slapd/slapi/slapi_ops.c
quick fix to allow -DSLAP_NVALUES with -DLDAP_SLAPI
[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 #ifdef SLAP_NVALUES
296                 slapi_ch_free( (void **)&ml->sml_nvalues );
297 #endif
298                 slapi_ch_free( (void **)&ml );
299         }
300 }
301
302 /*
303  * Function : LDAPModToEntry 
304  * convert a dn plus an array of LDAPMod struct ptrs to an entry structure
305  * with a link list of the correspondent attributes.
306  * Return value : LDAP_SUCCESS
307  *                LDAP_NO_MEMORY
308  *                LDAP_OTHER
309 */
310 Entry *
311 LDAPModToEntry(
312         char *ldn, 
313         LDAPMod **mods )
314 {
315         struct berval           dn = { 0, NULL };
316         Entry                   *pEntry=NULL;
317         LDAPMod                 *pMod;
318         struct berval           *bv;
319         Backend                 *be;
320         Operation               *op;
321
322         Modifications           *modlist = NULL;
323         Modifications           **modtail = &modlist;
324         Modifications           tmp;
325
326         int                     rc = LDAP_SUCCESS;
327         int                     i;
328
329         const char              *text = NULL;
330
331
332         op = (Operation *) slapi_ch_calloc(1, sizeof(Operation));
333         if ( pEntry == NULL) {
334                 rc = LDAP_NO_MEMORY;
335                 goto cleanup;
336         }  
337         op->o_tag = LDAP_REQ_ADD;
338
339         pEntry = (Entry *) ch_calloc( 1, sizeof(Entry) );
340         if ( pEntry == NULL) {
341                 rc = LDAP_NO_MEMORY;
342                 goto cleanup;
343         } 
344
345         dn.bv_val = slapi_ch_strdup(ldn);
346         dn.bv_len = strlen(ldn);
347
348         rc = dnPrettyNormal( NULL, &dn, &pEntry->e_name, &pEntry->e_nname );
349         if (rc != LDAP_SUCCESS) goto cleanup;
350
351         if ( rc == LDAP_SUCCESS ) {
352                 for ( i=0, pMod=mods[0]; rc == LDAP_SUCCESS && pMod != NULL; pMod=mods[++i]) {
353                         Modifications *mod;
354                         if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {
355                                 /* attr values are in berval format */
356                                 /* convert an array of pointers to bervals to an array of bervals */
357                                 rc = bvptr2obj(pMod->mod_bvalues, &bv);
358                                 if (rc != LDAP_SUCCESS) goto cleanup;
359                                 tmp.sml_type.bv_val = pMod->mod_type;
360                                 tmp.sml_type.bv_len = strlen( pMod->mod_type );
361                                 tmp.sml_bvalues = bv;
362 #ifdef SLAP_NVALUES
363                                 tmp.sml_nvalues = NULL;
364 #endif
365                 
366                                 mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
367
368                                 mod->sml_op = LDAP_MOD_ADD;
369                                 mod->sml_next = NULL;
370                                 mod->sml_desc = NULL;
371                                 mod->sml_type = tmp.sml_type;
372                                 mod->sml_bvalues = tmp.sml_bvalues;
373 #ifdef SLAP_NVALUES
374                                 mod->sml_nvalues = tmp.sml_nvalues;
375 #endif
376
377                                 *modtail = mod;
378                                 modtail = &mod->sml_next;
379
380                         } else {
381                                 /* attr values are in string format, need to be converted */
382                                 /* to an array of bervals */ 
383                                 if ( pMod->mod_values == NULL ) {
384                                         rc = LDAP_OTHER;
385                                 } else {
386                                         rc = values2obj( pMod->mod_values, &bv );
387                                         if (rc != LDAP_SUCCESS) goto cleanup;
388                                         tmp.sml_type.bv_val = pMod->mod_type;
389                                         tmp.sml_type.bv_len = strlen( pMod->mod_type );
390                                         tmp.sml_bvalues = bv;
391 #ifdef SLAP_NVALUES
392                                         tmp.sml_nvalues = NULL;
393 #endif
394                 
395                                         mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
396
397                                         mod->sml_op = LDAP_MOD_ADD;
398                                         mod->sml_next = NULL;
399                                         mod->sml_desc = NULL;
400                                         mod->sml_type = tmp.sml_type;
401                                         mod->sml_bvalues = tmp.sml_bvalues;
402 #ifdef SLAP_NVALUES
403                                         mod->sml_nvalues = tmp.sml_nvalues;
404 #endif
405
406                                         *modtail = mod;
407                                         modtail = &mod->sml_next;
408                                 }
409                         }
410                 } /* for each LDAPMod */
411         }
412
413         be = select_backend(&pEntry->e_nname, 0, 0);
414         if ( be == NULL ) {
415                 rc =  LDAP_PARTIAL_RESULTS;
416                 goto cleanup;
417         }
418
419         if ( be ) {
420                 int repl_user = be_isupdate(be, &be->be_rootdn );
421                 if ( !be->be_update_ndn.bv_len || repl_user ) {
422                         int update = be->be_update_ndn.bv_len;
423                         char textbuf[SLAP_TEXT_BUFLEN];
424                         size_t textlen = sizeof textbuf;
425
426                         rc = slap_mods_check( modlist, update, &text, 
427                                         textbuf, textlen );
428                         if ( rc != LDAP_SUCCESS) {
429                                 goto cleanup;
430                         }
431
432                         if ( !repl_user ) {
433                                 rc = slap_mods_opattrs( be, op,
434                                                 modlist, modtail, &text, 
435                                                 textbuf, textlen );
436                                 if ( rc != LDAP_SUCCESS) {
437                                         goto cleanup;
438                                 }
439                         }
440
441                         /*
442                          * FIXME: slap_mods2entry is declared static 
443                          * in servers/slapd/add.c
444                          */
445                         rc = slap_mods2entry( modlist, &pEntry, repl_user,
446                                         &text, textbuf, textlen );
447                         if (rc != LDAP_SUCCESS) {
448                                 goto cleanup;
449                         }
450
451                 } else {
452                         rc = LDAP_REFERRAL;
453                 }
454         } else {
455                 rc = LDAP_UNWILLING_TO_PERFORM;
456         }
457
458 cleanup:
459
460         if ( dn.bv_val ) slapi_ch_free( (void **)&dn.bv_val );
461         if ( op ) slapi_ch_free( (void **)&op );
462         if ( modlist != NULL ) freeMods( modlist );
463         if ( rc != LDAP_SUCCESS ) {
464                 if ( pEntry != NULL ) {
465                         slapi_entry_free( pEntry );
466                 }
467                 pEntry = NULL;
468         }
469
470         return( pEntry );
471 }
472
473 /* Function : slapi_delete_internal
474  *
475  * Description : Plugin functions call this routine to delete an entry 
476  *               in the backend directly
477  * Return values : LDAP_SUCCESS
478  *                 LDAP_PARAM_ERROR
479  *                 LDAP_NO_MEMORY
480  *                 LDAP_OTHER
481  *                 LDAP_UNWILLING_TO_PERFORM
482 */
483 Slapi_PBlock *
484 slapi_delete_internal(
485         char *ldn, 
486         LDAPControl **controls, 
487         int log_change )
488 {
489 #if defined(LDAP_SLAPI)
490         Backend                 *be;
491         Connection              *pConn = NULL;
492         Operation               *op = NULL;
493         Slapi_PBlock            *pPB = NULL;
494         Slapi_PBlock            *pSavePB = NULL;
495
496         struct berval dn  = { 0, NULL };
497         struct berval pdn = { 0, NULL };
498         struct berval ndn = { 0, NULL };
499
500         int                             rc=LDAP_SUCCESS;
501         int                             manageDsaIt = 0;
502         int                             isCritical;
503
504         if ( ldn == NULL ) {
505                 rc = LDAP_PARAM_ERROR; 
506                 goto cleanup;
507         }
508
509         pConn = fakeConnection( NULL, LDAP_REQ_DELETE );
510         if (pConn == NULL) {
511                 rc = LDAP_NO_MEMORY;
512                 goto cleanup;
513         }
514
515         op = (Operation *)pConn->c_pending_ops.stqh_first;
516         pPB = (Slapi_PBlock *)op->o_pb;
517         op->o_ctrls = controls;
518
519         dn.bv_val = slapi_ch_strdup(ldn);
520         dn.bv_len = slapi_strlen(ldn);
521         rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
522         if ( rc != LDAP_SUCCESS ) goto cleanup;
523
524         if ( slapi_control_present( controls, 
525                         SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical) ) {
526                 manageDsaIt = 1; 
527         }
528
529         be = select_backend( &ndn, manageDsaIt, 0 );
530         if ( be == NULL ) {
531                 rc =  LDAP_PARTIAL_RESULTS;
532                 goto cleanup;
533         }
534
535         op->o_dn = pConn->c_dn = be->be_rootdn;
536         op->o_ndn = pConn->c_ndn = be->be_rootndn;
537
538         if ( be->be_delete ) {
539                 int repl_user = be_isupdate( be, &op->o_ndn );
540                 if ( !be->be_update_ndn.bv_len || repl_user ) {
541                         rc = (*be->be_delete)( be, pConn, op, &pdn, &ndn );
542                         if ( rc == 0 ) {
543                                 if (log_change) {
544                                         replog( be, op, &pdn, &ndn, NULL );
545                                 }
546                                 rc = LDAP_SUCCESS;
547                         } else {
548                                 rc = LDAP_OPERATIONS_ERROR;
549                         }
550                 } else {
551                         rc = LDAP_REFERRAL;
552                 }
553         } else {
554                 rc = LDAP_UNWILLING_TO_PERFORM;
555         }
556
557 cleanup:
558         if (pPB != NULL) 
559                 slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
560
561         if (dn.bv_val) slapi_ch_free( (void **)&dn.bv_val );
562         if (pdn.bv_val) slapi_ch_free( (void **)&pdn.bv_val );
563         if (ndn.bv_val) slapi_ch_free( (void **)&ndn.bv_val );
564
565         if ( pConn != NULL ) {
566                 if ( pConn->c_sb != NULL ) ber_sockbuf_free( pConn->c_sb );
567                 if ( op ) slapi_ch_free( (void **)&op );
568                 pSavePB = pPB;
569                 free( pConn );
570         }
571         
572         return (pSavePB);
573 #endif /* LDAP_SLAPI */
574         return NULL;
575 }
576
577 Slapi_PBlock * 
578 slapi_add_entry_internal(
579         Slapi_Entry *e, 
580         LDAPControl **controls, 
581         int log_changes ) 
582 {
583 #if defined(LDAP_SLAPI)
584         Connection              *pConn = NULL;
585         Operation               *op = NULL;
586         Slapi_PBlock            *pPB = NULL, *pSavePB = NULL;
587         Backend                 *be;
588
589         int                     manageDsaIt = 0;
590         int                     isCritical;
591         int                     rc = LDAP_SUCCESS;
592
593         if ( e == NULL ) {
594                 rc = LDAP_PARAM_ERROR;
595                 goto cleanup;
596         }
597         
598         pConn = fakeConnection( NULL, LDAP_REQ_ADD );
599         if ( pConn == NULL ) {
600                 rc = LDAP_NO_MEMORY;
601                 goto cleanup;
602         }
603
604         if ( slapi_control_present( controls, LDAP_CONTROL_MANAGEDSAIT,
605                                 NULL, &isCritical ) ) {
606                 manageDsaIt = 1; 
607         }
608
609         op = (Operation *)pConn->c_pending_ops.stqh_first;
610         pPB = (Slapi_PBlock *)op->o_pb;
611         op->o_ctrls = controls;
612
613         be = select_backend( &e->e_nname, manageDsaIt, 0 );
614         if ( be == NULL ) {
615                 rc = LDAP_PARTIAL_RESULTS;
616                 goto cleanup;
617         }
618
619         op->o_dn = pConn->c_dn = be->be_rootdn;
620         op->o_ndn = pConn->c_ndn = be->be_rootndn;
621
622         if ( be->be_add ) {
623                 int repl_user = be_isupdate( be, &op->o_ndn );
624                 if ( !be->be_update_ndn.bv_len || repl_user ){
625                         if ( (*be->be_add)( be, pConn, op, e ) == 0 ) {
626                                 if ( log_changes ) {
627                                         replog( be, op, &e->e_name, 
628                                                         &e->e_nname, e );
629                                 }
630                                 rc = LDAP_SUCCESS;
631                         }
632                 } else {
633                         rc = LDAP_REFERRAL;
634                 }
635         } else {
636                 rc = LDAP_UNWILLING_TO_PERFORM;
637         }
638
639 cleanup:
640
641         if ( pPB != NULL ) {
642                 slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
643         }
644
645         if ( pConn != NULL ) {
646                 if ( pConn->c_sb != NULL ) ber_sockbuf_free( pConn->c_sb );
647                 if ( op != NULL ) slapi_ch_free( (void **)&op );
648                 pSavePB = pPB;
649                 free( pConn );
650         }
651         return( pSavePB );
652 #endif /* LDAP_SLAPI */
653         return NULL;
654 }
655
656
657 Slapi_PBlock *
658 slapi_add_internal(
659         char *dn, 
660         LDAPMod **mods, 
661         LDAPControl **controls, 
662         int log_changes  ) 
663 {
664 #if defined(LDAP_SLAPI)
665         LDAPMod                 *pMod = NULL;
666         Slapi_PBlock            *pb = NULL;
667         Entry                   *pEntry = NULL;
668         int                     i, rc=LDAP_SUCCESS;
669
670         if ( mods == NULL || *mods == NULL || dn == NULL || *dn == '\0' ) {
671                 rc = LDAP_PARAM_ERROR ;
672         }
673
674         if ( rc == LDAP_SUCCESS ) {
675                 for ( i = 0, pMod = mods[0]; pMod != NULL; pMod = mods[++i] ) {
676                         if ( (pMod->mod_op & ~LDAP_MOD_BVALUES) != LDAP_MOD_ADD ) {
677                                 rc = LDAP_OTHER;
678                                 break;
679                         }
680                 }
681         }
682
683         if ( rc == LDAP_SUCCESS ) {
684                 if((pEntry = LDAPModToEntry( dn, mods )) == NULL) {
685                         rc = LDAP_OTHER;
686                 }
687         }
688
689         if ( rc != LDAP_SUCCESS ) {
690                 pb = slapi_pblock_new();
691                 slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
692         } else {
693                 pb = slapi_add_entry_internal( pEntry, controls, log_changes );
694         }
695
696         if ( pEntry ) {
697                 slapi_entry_free(pEntry);
698         }
699
700         return(pb);
701 #endif /* LDAP_SLAPI */
702         return NULL;
703 }
704
705 /* Function : slapi_modrdn_internal
706  *
707  * Description : Plugin functions call this routine to modify the rdn 
708  *                               of an entry in the backend directly
709  * Return values : LDAP_SUCCESS
710  *                 LDAP_PARAM_ERROR
711  *                 LDAP_OPERATIONS_ERROR
712  *                 LDAP_NO_MEMORY
713  *                 LDAP_OTHER
714  *                 LDAP_UNWILLING_TO_PERFORM
715  *
716  * NOTE: This function does not support the "newSuperior" option from LDAP V3.
717  */
718 Slapi_PBlock *
719 slapi_modrdn_internal(
720         char *olddn, 
721         char *lnewrdn, 
722         int deloldrdn, 
723         LDAPControl **controls, 
724         int log_change )
725 {
726 #if defined(LDAP_SLAPI)
727         int                     rc = LDAP_SUCCESS;
728
729         struct berval           dn = { 0, NULL };
730         struct berval           pdn = { 0, NULL };
731         struct berval           ndn = { 0, NULL };
732
733         struct berval           newrdn = { 0, NULL };
734         struct berval           pnewrdn = { 0, NULL };
735         struct berval           nnewrdn = { 0, NULL };
736
737 #if 0 /* currently unused */
738         struct berval           newSuperior = { 0, NULL };
739 #endif
740         struct berval           pnewSuperior = { 0, NULL }; 
741 #if 0 /* currently unused */
742         struct berval           nnewSuperior = { 0, NULL }; 
743 #endif
744
745         struct berval           *pnewS = NULL;
746         struct berval           *nnewS = NULL;
747
748         Connection              *pConn = NULL;
749         Operation               *op = NULL;
750         Slapi_PBlock            *pPB = NULL;
751         Slapi_PBlock            *pSavePB = NULL;
752
753         Backend                 *be;
754 #if 0 /* currently unused */
755         Backend                 *newSuperior_be = NULL;
756 #endif
757
758         int                     manageDsaIt = 0;
759         int                     isCritical;
760 #if 0 /* currently unused */
761         const char              *text = NULL;
762 #endif
763
764         dn.bv_val = slapi_ch_strdup(olddn);
765         dn.bv_len = slapi_ch_stlen(olddn);
766
767         rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
768
769         if ( rc != LDAP_SUCCESS ) goto cleanup;
770
771         if ( ndn.bv_len == 0 ) {
772                 rc = LDAP_UNWILLING_TO_PERFORM;
773                 goto cleanup;
774         }
775
776         newrdn.bv_val = slapi_ch_strdup( lnewrdn );
777         newrdn.bv_len = slapi_ch_stlen( lnewrdn );
778
779         rc = dnPrettyNormal( NULL, &newrdn, &pnewrdn, &nnewrdn );
780
781         if ( rc != LDAP_SUCCESS ) goto cleanup;
782
783         if ( rdnValidate( &pnewrdn ) != LDAP_SUCCESS ) goto cleanup;
784
785         pConn = fakeConnection( NULL,  LDAP_REQ_MODRDN);
786         if ( pConn == NULL) {
787                 rc = LDAP_NO_MEMORY;
788                 goto cleanup;
789         }
790
791         op = (Operation *)pConn->c_pending_ops.stqh_first;
792         pPB = (Slapi_PBlock *)op->o_pb;
793         op->o_ctrls = controls;
794
795         if ( slapi_control_present( controls, 
796                         SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical ) ) {
797                 manageDsaIt = 1;
798         }
799
800         be = select_backend( &ndn, manageDsaIt, 0 );
801         if ( be == NULL ) {
802                 rc =  LDAP_PARTIAL_RESULTS;
803                 goto cleanup;
804         }
805
806         op->o_dn = pConn->c_dn = be->be_rootdn;
807         op->o_ndn = pConn->c_ndn = be->be_rootndn;
808
809         if ( be->be_modrdn ) {
810                 int repl_user = be_isupdate( be, &op->o_ndn );
811                 if ( !be->be_update_ndn.bv_len || repl_user ) {
812                         rc = (*be->be_modrdn)( be, pConn, op, &pdn, &ndn,
813                                         &pnewrdn, &nnewrdn, deloldrdn, pnewS,
814                                         nnewS );
815                         if ( rc == 0 ) {
816                                 struct slap_replog_moddn moddn;
817                                 moddn.newrdn = &pnewrdn;
818                                 moddn.deloldrdn = deloldrdn;
819                                 moddn.newsup = &pnewSuperior;
820                                 if ( log_change ) {
821                                         replog( be, op, &pdn, &ndn, &moddn );
822                                 }
823                                 rc = LDAP_SUCCESS;
824
825                         } else {
826                                 rc = LDAP_OPERATIONS_ERROR;
827                         }
828
829                 } else {
830                         rc = LDAP_REFERRAL;
831                 }
832
833         } else {
834                 rc = LDAP_UNWILLING_TO_PERFORM;
835         }
836
837 cleanup:
838
839         if ( pPB != NULL ) {
840                 slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
841         }
842         
843         if ( dn.bv_val ) ch_free( dn.bv_val );
844         if ( pdn.bv_val ) ch_free( pdn.bv_val );
845         if ( ndn.bv_val ) ch_free( ndn.bv_val );
846
847         if ( newrdn.bv_val ) ch_free( newrdn.bv_val );
848         if ( pnewrdn.bv_val ) ch_free( newrdn.bv_val );
849         if ( nnewrdn.bv_val ) ch_free( newrdn.bv_val );
850
851         if ( pConn != NULL ) {
852                 if ( pConn->c_sb != NULL ) ber_sockbuf_free( pConn->c_sb );
853                 if ( op != NULL ) slapi_ch_free( (void **)&op );
854                 pSavePB = pPB;
855                 free( pConn );
856         }
857
858         return( pSavePB );
859 #endif /* LDAP_SLAPI */
860         return NULL;
861 }
862
863 /* Function : slapi_modify_internal
864  *
865  * Description: Plugin functions call this routine to modify an entry 
866  *                              in the backend directly
867  * Return values : LDAP_SUCCESS
868  *                 LDAP_PARAM_ERROR
869  *                 LDAP_NO_MEMORY
870  *                 LDAP_OPERATIONS_ERROR
871  *                 LDAP_OTHER
872  *                 LDAP_UNWILLING_TO_PERFORM
873 */
874 Slapi_PBlock *
875 slapi_modify_internal(
876         char *ldn,      
877         LDAPMod **mods, 
878         LDAPControl **controls, 
879         int log_change )
880 {
881 #if defined(LDAP_SLAPI)
882         int                     i, rc = LDAP_SUCCESS;
883         Connection              *pConn = NULL;
884         Operation               *op = NULL;
885         Slapi_PBlock            *pPB = NULL;
886         Slapi_PBlock            *pSavePB = NULL;
887
888         struct berval dn = { 0, NULL };
889         struct berval pdn = { 0, NULL };
890         struct berval ndn = { 0, NULL };
891
892         int                     manageDsaIt = 0;
893         int                     isCritical;
894         Backend                 *be;
895         struct berval           *bv;
896         LDAPMod                 *pMod;
897
898         Modifications           *modlist = NULL;
899         Modifications           **modtail = &modlist;
900         Modifications           tmp;
901
902         if ( mods == NULL || *mods == NULL || ldn == NULL ) {
903                 rc = LDAP_PARAM_ERROR ;
904                 goto cleanup;
905         }
906
907         pConn = fakeConnection( NULL,  LDAP_REQ_MODIFY );
908         if ( pConn == NULL ) {
909                 rc = LDAP_NO_MEMORY;
910                 goto cleanup;
911         }
912
913         op = (Operation *)pConn->c_pending_ops.stqh_first;
914         pPB = (Slapi_PBlock *)op->o_pb;
915         op->o_ctrls = controls;
916
917         dn.bv_val = slapi_ch_strdup( ldn );
918         dn.bv_len = slapi_strlen( ldn );
919         rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
920         if ( rc != LDAP_SUCCESS ) goto cleanup;
921
922         if ( slapi_control_present( controls, 
923                         SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical ) ) {
924                 manageDsaIt = 1;
925         }
926
927         be = select_backend( &ndn, manageDsaIt, 0 );
928         if ( be == NULL ) {
929                 rc =  LDAP_PARTIAL_RESULTS;
930                 goto cleanup;
931         }
932
933         op->o_dn = pConn->c_dn = be->be_rootdn;
934         op->o_ndn = pConn->c_ndn = be->be_rootndn;
935
936         for ( i = 0, pMod = mods[0]; rc == LDAP_SUCCESS && pMod != NULL; 
937                         pMod = mods[++i] ) {
938                 Modifications *mod;
939                 if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {
940                         /*
941                          * attr values are in berval format
942                          * convert an array of pointers to bervals
943                          * to an array of bervals
944                          */
945                         rc = bvptr2obj( pMod->mod_bvalues, &bv );
946                         if ( rc != LDAP_SUCCESS ) goto cleanup;
947                         tmp.sml_type.bv_val = pMod->mod_type;
948                         tmp.sml_type.bv_len = strlen( pMod->mod_type );
949                         tmp.sml_bvalues = bv;
950 #ifdef SLAP_NVALUES
951                         tmp.sml_nvalues = NULL;
952 #endif
953
954                         mod  = (Modifications *)ch_malloc( sizeof(Modifications) );
955
956                         mod->sml_op = pMod->mod_op;
957                         mod->sml_next = NULL;
958                         mod->sml_desc = NULL;
959                         mod->sml_type = tmp.sml_type;
960                         mod->sml_bvalues = tmp.sml_bvalues;
961 #ifdef SLAP_NVALUES
962                         mod->sml_nvalues = tmp.sml_nvalues;
963 #endif
964                 } else { 
965                         rc = values2obj( pMod->mod_values, &bv );
966                         if ( rc != LDAP_SUCCESS ) goto cleanup;
967                         tmp.sml_type.bv_val = pMod->mod_type;
968                         tmp.sml_type.bv_len = strlen( pMod->mod_type );
969                         tmp.sml_bvalues = bv;
970 #ifdef SLAP_NVALUES
971                         tmp.sml_nvalues = NULL;
972 #endif
973
974                         mod  = (Modifications *) ch_malloc( sizeof(Modifications) );
975
976                         mod->sml_op = pMod->mod_op;
977                         mod->sml_next = NULL;
978                         mod->sml_desc = NULL;
979                         mod->sml_type = tmp.sml_type;
980                         mod->sml_bvalues = tmp.sml_bvalues;
981 #ifdef SLAP_NVALUES
982                         mod->sml_nvalues = tmp.sml_nvalues;
983 #endif
984                 }
985                 *modtail = mod;
986                 modtail = &mod->sml_next;
987
988                 switch( pMod->mod_op ) {
989                 case LDAP_MOD_ADD:
990                 if ( mod->sml_bvalues == NULL ) {
991                         rc = LDAP_PROTOCOL_ERROR;
992                         goto cleanup;
993                 }
994
995                 /* fall through */
996                 case LDAP_MOD_DELETE:
997                 case LDAP_MOD_REPLACE:
998                 break;
999
1000                 default:
1001                         rc = LDAP_PROTOCOL_ERROR;
1002                         goto cleanup;
1003                 }
1004         } 
1005         *modtail = NULL;
1006
1007         if ( ndn.bv_len == 0 ) {
1008                 rc = LDAP_UNWILLING_TO_PERFORM;
1009                 goto cleanup;
1010         }
1011
1012         if ( be->be_modify ) {
1013                 int repl_user = be_isupdate( be, &op->o_ndn );
1014                 if ( !be->be_update_ndn.bv_len || repl_user ) {
1015                         int update = be->be_update_ndn.bv_len;
1016                         const char *text = NULL;
1017                         char textbuf[SLAP_TEXT_BUFLEN];
1018                         size_t textlen = sizeof( textbuf );
1019
1020                         rc = slap_mods_check( modlist, update,
1021                                         &text, textbuf, textlen );
1022                         if (rc != LDAP_SUCCESS) {
1023                                 goto cleanup;
1024                         }
1025
1026                         if ( !repl_user ) {
1027                                 rc = slap_mods_opattrs( be, op, modlist,
1028                                                 modtail, &text, textbuf, 
1029                                                 textlen );
1030                                 if (rc != LDAP_SUCCESS) {
1031                                         goto cleanup;
1032                                 }
1033                         }
1034                         rc = (*be->be_modify)( be, pConn, op,
1035                                         &pdn, &ndn, modlist );
1036                         if ( rc == 0 ) {
1037                                 if ( log_change ) {
1038                                         replog( be, op, &pdn, &ndn, modlist );
1039                                 }
1040                                 rc = LDAP_SUCCESS;
1041                         } else {
1042                                 rc = LDAP_OPERATIONS_ERROR;
1043                         }
1044                 } else {
1045                         rc = LDAP_REFERRAL;
1046                 }
1047         } else {
1048                 rc = LDAP_UNWILLING_TO_PERFORM;
1049         }
1050
1051 cleanup:
1052
1053         if ( pPB != NULL ) 
1054                 slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
1055
1056         if ( dn.bv_val ) ch_free( dn.bv_val );
1057         if ( pdn.bv_val ) ch_free( pdn.bv_val );
1058         if ( ndn.bv_val ) ch_free( ndn.bv_val );
1059
1060         if ( modlist != NULL ) freeMods( modlist );
1061
1062         if ( pConn != NULL ) {
1063                 if ( pConn->c_sb != NULL ) ber_sockbuf_free( pConn->c_sb );
1064                 if ( op != NULL ) slapi_ch_free( (void **)&op );
1065                 pSavePB = pPB;
1066                 free( pConn );
1067         }
1068
1069         return ( pSavePB );
1070
1071 #endif /* LDAP_SLAPI */
1072         return NULL;
1073 }
1074
1075 Slapi_PBlock *
1076 slapi_search_internal_bind(
1077         char *bindDN, 
1078         char *ldn, 
1079         int scope, 
1080         char *filStr, 
1081         LDAPControl **controls, 
1082         char **attrs, 
1083         int attrsonly ) 
1084 {       
1085 #if defined(LDAP_SLAPI)
1086         Backend                 *be;
1087         Connection              *c;
1088         Operation               *op = NULL;
1089         Slapi_PBlock            *ptr = NULL;            
1090         Slapi_PBlock            *pSavePB = NULL;                
1091         struct berval           dn = { 0, NULL };
1092         struct berval           pdn = { 0, NULL };
1093         struct berval           ndn = { 0, NULL };
1094         Filter                  *filter=NULL;
1095         struct berval           fstr = { 0, NULL };
1096         AttributeName           *an = NULL;
1097         const char              *text = NULL;
1098
1099         int                     deref=0;
1100         int                     sizelimit=-1, timelimit=-1;
1101
1102         int                     manageDsaIt = 0; 
1103         int                     isCritical;
1104
1105         int                     i, rc = LDAP_SUCCESS;
1106         
1107         c = fakeConnection( NULL, LDAP_REQ_SEARCH );
1108         if (c == NULL) {
1109                 rc = LDAP_NO_MEMORY;
1110                 goto cleanup;
1111         }
1112
1113         op = (Operation *)c->c_pending_ops.stqh_first;
1114         ptr = (Slapi_PBlock *)op->o_pb;
1115         op->o_ctrls = controls;
1116
1117         dn.bv_val = slapi_ch_strdup(ldn);
1118         dn.bv_len = slapi_strlen(ldn);
1119
1120         rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );
1121         if (rc != LDAP_SUCCESS) goto cleanup;
1122
1123         if ( scope != LDAP_SCOPE_BASE && 
1124                         scope != LDAP_SCOPE_ONELEVEL && 
1125                         scope != LDAP_SCOPE_SUBTREE ) {
1126                 rc = LDAP_PROTOCOL_ERROR;
1127                 goto cleanup;
1128         }
1129
1130         filter = slapi_str2filter(filStr);
1131         if ( filter == NULL ) {
1132                 rc = LDAP_PROTOCOL_ERROR;
1133                 goto cleanup;
1134         }
1135
1136         filter2bv( filter, &fstr );
1137
1138         for ( i = 0; attrs != NULL && attrs[i] != NULL; i++ ) {
1139                 ; /* count the number of attributes */
1140         }
1141
1142         if (i > 0) {
1143                 an = (AttributeName *)slapi_ch_calloc( (i + 1), sizeof(AttributeName) );
1144                 for (i = 0; attrs[i] != 0; i++) {
1145                         an[i].an_desc = NULL;
1146                         an[i].an_oc = NULL;
1147                         an[i].an_name.bv_val = slapi_ch_strdup(attrs[i]);
1148                         an[i].an_name.bv_len = slapi_strlen(attrs[i]);
1149                         slap_bv2ad( &an[i].an_name, &an[i].an_desc, &text );
1150                 }
1151                 an[i].an_name.bv_val = NULL;
1152         }
1153
1154         if ( scope == LDAP_SCOPE_BASE ) {
1155                 Entry *entry = NULL;
1156
1157                 if ( ndn.bv_len == 0 ) {
1158                         rc = root_dse_info( c, &entry, &text );
1159                 }
1160
1161                 if( rc != LDAP_SUCCESS ) {
1162                         send_ldap_result( c, op, rc, NULL, text, NULL, NULL );
1163                         goto cleanup;
1164                 } else if ( entry != NULL ) {
1165                         rc = test_filter( NULL, c, op, entry, filter );
1166
1167                         if( rc == LDAP_COMPARE_TRUE ) {
1168                                 send_search_entry( NULL, c, op, entry,
1169                                                 an, attrsonly, NULL );
1170                         }
1171
1172                         entry_free( entry );
1173
1174                         send_ldap_result( c, op, LDAP_SUCCESS, 
1175                                         NULL, NULL, NULL, NULL );
1176
1177                         rc = LDAP_SUCCESS;
1178
1179                         goto cleanup;
1180                 }
1181         }
1182
1183         if ( !ndn.bv_len && default_search_nbase.bv_len ) {
1184                 ch_free( pdn.bv_val );
1185                 ch_free( ndn.bv_val );
1186
1187                 ber_dupbv( &pdn, &default_search_base );
1188                 ber_dupbv( &ndn, &default_search_nbase );
1189         }
1190
1191         if ( slapi_control_present( controls,
1192                         LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) {
1193                 manageDsaIt = 1;
1194         }
1195
1196         be = select_backend( &ndn, manageDsaIt, 0 );
1197         if ( be == NULL ) {
1198                 if ( manageDsaIt == 1 ) {
1199                         rc = LDAP_NO_SUCH_OBJECT;
1200                 } else {
1201                         rc = LDAP_PARTIAL_RESULTS;
1202                 }
1203                 goto cleanup;
1204         } 
1205
1206         op->o_dn = c->c_dn = be->be_rootdn;
1207         op->o_ndn = c->c_ndn = be->be_rootndn;
1208
1209         if ( be->be_search ) {
1210                 rc = (*be->be_search)( be, c, op, &pdn, &ndn,
1211                         scope, deref, sizelimit, timelimit,
1212                         filter, &fstr, an, attrsonly );
1213                 if ( rc == 0 ) {
1214                         rc = LDAP_SUCCESS;
1215                 } else {
1216                         rc = LDAP_OPERATIONS_ERROR;
1217                 }
1218         } else {
1219                 rc = LDAP_UNWILLING_TO_PERFORM;
1220         }
1221
1222 cleanup:
1223
1224         if ( ptr != NULL )
1225                 slapi_pblock_set( ptr, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );
1226
1227         if ( dn.bv_val ) free( dn.bv_val );
1228         if ( ndn.bv_val ) free( ndn.bv_val );
1229         if ( pdn.bv_val ) free( pdn.bv_val );
1230
1231         if ( filter ) slapi_filter_free( filter, 1 );
1232         if ( fstr.bv_val ) free ( fstr.bv_val );
1233
1234         if ( an != NULL ) free( an );
1235
1236         if ( c != NULL ) {
1237                 if ( c->c_sb != NULL ) ber_sockbuf_free( c->c_sb );
1238                 if ( op != NULL ) slapi_ch_free( (void **)&op );
1239                 pSavePB = ptr;
1240                 free( c );
1241         }
1242         return( pSavePB );
1243 #endif /* LDAP_SLAPI */
1244         return NULL;
1245 }
1246
1247 Slapi_PBlock * 
1248 slapi_search_internal(
1249         char *base,
1250         int scope,
1251         char *filStr, 
1252         LDAPControl **controls,
1253         char **attrs,
1254         int attrsonly ) 
1255 {
1256 #if defined(LDAP_SLAPI)
1257         return slapi_search_internal_bind( NULL, base, scope, filStr,
1258                         controls, attrs, attrsonly );
1259 #else
1260         return NULL;
1261 #endif /* LDAP_SLAPI */
1262 }
1263