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