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