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