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