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