]> git.sur5r.net Git - openldap/blob - servers/slapd/back-relay/op.c
works in most cases ...
[openldap] / servers / slapd / back-relay / op.c
1 /* op.c - relay backend operations */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2004 The OpenLDAP Foundation.
5  * Portions Copyright 2004 Pierangelo Masarati.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16 /* ACKNOWLEDGEMENTS:
17  * This work was initially developed by Pierangelo Masarati for inclusion
18  * in OpenLDAP Software.
19  */
20
21 #include "portable.h"
22
23 #include <stdio.h>
24
25 #include "slap.h"
26 #include "back-relay.h"
27
28 static int
29 relay_back_swap_bd( struct slap_op *op, struct slap_rep *rs )
30 {
31         slap_callback   *cb = op->o_callback;
32         BackendDB       *be = op->o_bd;
33
34         op->o_bd = cb->sc_private;
35         cb->sc_private = be;
36
37         return SLAP_CB_CONTINUE;
38 }
39
40 static void
41 relay_back_add_cb( slap_callback *cb, struct slap_op *op )
42 {
43                 cb->sc_next = op->o_callback;
44                 cb->sc_response = relay_back_swap_bd;
45                 cb->sc_cleanup = relay_back_swap_bd;
46                 cb->sc_private = op->o_bd;
47                 op->o_callback = cb;
48 }
49
50 static BackendDB *
51 relay_back_select_backend( struct slap_op *op, struct slap_rep *rs, int err )
52 {
53         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
54         BackendDB               *bd = ri->ri_bd;
55
56         if ( bd == NULL ) {
57                 bd = select_backend( &op->o_req_ndn, 0, 1 );
58                 if ( bd == op->o_bd ) {
59                         if ( err != LDAP_SUCCESS ) {
60                                 send_ldap_error( op, rs,
61                                                 LDAP_UNWILLING_TO_PERFORM, 
62                                                 "would call self" );
63                         }
64                         return NULL;
65                 }
66         }
67
68         if ( bd == NULL ) {
69                 if ( default_referral ) {
70                         rs->sr_ref = referral_rewrite( default_referral,
71                                 NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
72                         if ( !rs->sr_ref ) {
73                                 rs->sr_ref = default_referral;
74                         }
75
76                         rs->sr_err = LDAP_REFERRAL;
77                         send_ldap_result( op, rs );
78
79                         if ( rs->sr_ref != default_referral ) {
80                                 ber_bvarray_free( rs->sr_ref );
81                         }
82
83                 } else {
84                         /* NOTE: err is LDAP_INVALID_CREDENTIALS for bind,
85                          * LDAP_NO_SUCH_OBJECT for other operations.
86                          * noSuchObject is not allowed to be returned by bind */
87                         rs->sr_err = err;
88                         send_ldap_result( op, rs );
89                 }
90         }
91
92         return bd;
93 }
94
95 int
96 relay_back_op_bind( struct slap_op *op, struct slap_rep *rs )
97 {
98         BackendDB               *bd;
99         int                     rc = 1;
100
101         bd = relay_back_select_backend( op, rs, LDAP_INVALID_CREDENTIALS );
102         if ( bd == NULL ) {
103                 return rc;
104         }
105
106         if ( bd->be_bind ) {
107                 BackendDB       *be = op->o_bd;
108                 slap_callback   cb;
109
110                 relay_back_add_cb( &cb, op );
111
112                 op->o_bd = bd;
113                 rc = ( bd->be_bind )( op, rs );
114                 op->o_bd = be;
115
116                 op->o_callback = op->o_callback->sc_next;
117
118         } else {
119                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
120                                 "operation not supported "
121                                 "within naming context" );
122         }
123
124         return rc;
125 }
126
127 int
128 relay_back_op_unbind( struct slap_op *op, struct slap_rep *rs )
129 {
130         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
131         BackendDB               *bd;
132         int                     rc = 1;
133
134         bd = ri->ri_bd;
135         if ( bd == NULL ) {
136                 bd = select_backend( &op->o_req_ndn, 0, 1 );
137         }
138
139         if ( bd && bd->be_unbind ) {
140                 BackendDB       *be = op->o_bd;
141                 slap_callback   cb;
142
143                 relay_back_add_cb( &cb, op );
144
145                 op->o_bd = bd;
146                 rc = ( bd->be_unbind )( op, rs );
147                 op->o_bd = be;
148
149                 op->o_callback = op->o_callback->sc_next;
150         }
151
152         return 0;
153
154 }
155
156 int
157 relay_back_op_search( struct slap_op *op, struct slap_rep *rs )
158 {
159         BackendDB               *bd;
160         int                     rc = 1;
161
162         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
163         if ( bd == NULL ) {
164                 return 1;
165         }
166
167         if ( bd->be_search ) {
168                 BackendDB       *be = op->o_bd;
169                 slap_callback   cb;
170
171                 relay_back_add_cb( &cb, op );
172
173                 op->o_bd = bd;
174                 rc = ( bd->be_search )( op, rs );
175                 op->o_bd = be;
176
177                 op->o_callback = op->o_callback->sc_next;
178
179         } else {
180                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
181                                 "operation not supported "
182                                 "within naming context" );
183         }
184
185         return rc;
186
187 }
188
189 int
190 relay_back_op_compare( struct slap_op *op, struct slap_rep *rs )
191 {
192         BackendDB               *bd;
193         int                     rc = 1;
194
195         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
196         if ( bd == NULL ) {
197                 return 1;
198         }
199
200         if ( bd->be_compare ) {
201                 BackendDB       *be = op->o_bd;
202                 slap_callback   cb;
203
204                 relay_back_add_cb( &cb, op );
205
206                 op->o_bd = bd;
207                 rc = ( bd->be_compare )( op, rs );
208                 op->o_bd = be;
209
210                 op->o_callback = op->o_callback->sc_next;
211
212         } else {
213                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
214                                 "operation not supported "
215                                 "within naming context" );
216         }
217
218         return rc;
219
220 }
221
222 int
223 relay_back_op_modify( struct slap_op *op, struct slap_rep *rs )
224 {
225         BackendDB               *bd;
226         int                     rc = 1;
227
228         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
229         if ( bd == NULL ) {
230                 return 1;
231         }
232
233         if ( bd->be_modify ) {
234                 BackendDB       *be = op->o_bd;
235                 slap_callback   cb;
236
237                 relay_back_add_cb( &cb, op );
238
239                 op->o_bd = bd;
240                 rc = ( bd->be_modify )( op, rs );
241                 op->o_bd = be;
242
243                 op->o_callback = op->o_callback->sc_next;
244
245         } else {
246                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
247                                 "operation not supported "
248                                 "within naming context" );
249         }
250
251         return rc;
252
253 }
254
255 int
256 relay_back_op_modrdn( struct slap_op *op, struct slap_rep *rs )
257 {
258         BackendDB               *bd;
259         int                     rc = 1;
260
261         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
262         if ( bd == NULL ) {
263                 return 1;
264         }
265
266         if ( bd->be_modrdn ) {
267                 BackendDB       *be = op->o_bd;
268                 slap_callback   cb;
269
270                 relay_back_add_cb( &cb, op );
271
272                 op->o_bd = bd;
273                 rc = ( bd->be_modrdn )( op, rs );
274                 op->o_bd = be;
275
276                 op->o_callback = op->o_callback->sc_next;
277
278         } else {
279                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
280                                 "operation not supported "
281                                 "within naming context" );
282         }
283
284         return rc;
285
286 }
287
288 int
289 relay_back_op_add( struct slap_op *op, struct slap_rep *rs )
290 {
291         BackendDB               *bd;
292         int                     rc = 1;
293
294         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
295         if ( bd == NULL ) {
296                 return 1;
297         }
298
299         if ( bd->be_add ) {
300                 BackendDB       *be = op->o_bd;
301                 slap_callback   cb;
302
303                 relay_back_add_cb( &cb, op );
304
305                 op->o_bd = bd;
306                 rc = ( bd->be_add )( op, rs );
307                 op->o_bd = be;
308
309                 op->o_callback = op->o_callback->sc_next;
310
311         } else {
312                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
313                                 "operation not supported "
314                                 "within naming context" );
315         }
316
317         return rc;
318
319 }
320
321 int
322 relay_back_op_delete( struct slap_op *op, struct slap_rep *rs )
323 {
324         BackendDB               *bd;
325         int                     rc = 1;
326
327         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
328         if ( bd == NULL ) {
329                 return 1;
330         }
331
332         if ( bd->be_delete ) {
333                 BackendDB       *be = op->o_bd;
334                 slap_callback   cb;
335
336                 relay_back_add_cb( &cb, op );
337
338                 op->o_bd = bd;
339                 rc = ( bd->be_delete )( op, rs );
340                 op->o_bd = be;
341
342                 op->o_callback = op->o_callback->sc_next;
343         }
344
345         return rc;
346
347 }
348
349 int
350 relay_back_op_abandon( struct slap_op *op, struct slap_rep *rs )
351 {
352         BackendDB               *bd;
353         int                     rc = 1;
354
355         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
356         if ( bd == NULL ) {
357                 return 1;
358         }
359
360         if ( bd->be_abandon ) {
361                 BackendDB       *be = op->o_bd;
362                 slap_callback   cb;
363
364                 relay_back_add_cb( &cb, op );
365
366                 op->o_bd = bd;
367                 rc = ( bd->be_abandon )( op, rs );
368                 op->o_bd = be;
369
370                 op->o_callback = op->o_callback->sc_next;
371
372         } else {
373                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
374                                 "operation not supported "
375                                 "within naming context" );
376         }
377
378         return rc;
379
380 }
381
382 int
383 relay_back_op_cancel( struct slap_op *op, struct slap_rep *rs )
384 {
385         BackendDB               *bd;
386         int                     rc = 1;
387
388         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
389         if ( bd == NULL ) {
390                 return 1;
391         }
392
393         if ( bd->be_cancel ) {
394                 BackendDB       *be = op->o_bd;
395                 slap_callback   cb;
396
397                 relay_back_add_cb( &cb, op );
398
399                 op->o_bd = bd;
400                 rc = ( bd->be_cancel )( op, rs );
401                 op->o_bd = be;
402
403                 op->o_callback = op->o_callback->sc_next;
404
405         } else {
406                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
407                                 "operation not supported "
408                                 "within naming context" );
409         }
410
411         return rc;
412
413 }
414
415 int
416 relay_back_op_extended( struct slap_op *op, struct slap_rep *rs )
417 {
418         BackendDB               *bd;
419         int                     rc = 1;
420
421         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
422         if ( bd == NULL ) {
423                 return 1;
424         }
425
426         if ( bd->be_extended ) {
427                 BackendDB       *be = op->o_bd;
428                 slap_callback   cb;
429
430                 relay_back_add_cb( &cb, op );
431
432                 op->o_bd = bd;
433                 rc = ( bd->be_extended )( op, rs );
434                 op->o_bd = be;
435
436                 op->o_callback = op->o_callback->sc_next;
437
438         } else {
439                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
440                                 "operation not supported "
441                                 "within naming context" );
442         }
443
444         return rc;
445
446 }
447
448 int
449 relay_back_entry_release_rw( struct slap_op *op, Entry *e, int rw )
450 {
451         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
452         BackendDB               *bd;
453         int                     rc = 1;
454
455         bd = ri->ri_bd;
456         if ( bd == NULL) {
457                 bd = select_backend( &op->o_req_ndn, 0, 1 );
458                 if ( bd == NULL ) {
459                         return 1;
460                 }
461         }
462
463         if ( bd->be_release ) {
464                 BackendDB       *be = op->o_bd;
465
466                 op->o_bd = bd;
467                 rc = ( bd->be_release )( op, e, rw );
468                 op->o_bd = be;
469         }
470
471         return rc;
472
473 }
474
475 int
476 relay_back_entry_get_rw( struct slap_op *op, struct berval *ndn,
477         ObjectClass *oc, AttributeDescription *at, int rw, Entry **e )
478 {
479         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
480         BackendDB               *bd;
481         int                     rc = 1;
482
483         bd = ri->ri_bd;
484         if ( bd == NULL) {
485                 bd = select_backend( &op->o_req_ndn, 0, 1 );
486                 if ( bd == NULL ) {
487                         return 1;
488                 }
489         }
490
491         if ( bd->be_fetch ) {
492                 BackendDB       *be = op->o_bd;
493
494                 op->o_bd = bd;
495                 rc = ( bd->be_fetch )( op, ndn, oc, at, rw, e );
496                 op->o_bd = be;
497         }
498
499         return rc;
500
501 }
502
503 int
504 relay_back_chk_referrals( struct slap_op *op, struct slap_rep *rs )
505 {
506         BackendDB               *bd;
507         int                     rc = 0;
508
509         bd = relay_back_select_backend( op, rs, LDAP_SUCCESS );
510         if ( bd == NULL ) {
511                 return 0;
512         }
513
514         if ( bd->be_chk_referrals ) {
515                 BackendDB       *be = op->o_bd;
516                 slap_callback   cb;
517
518                 relay_back_add_cb( &cb, op );
519
520                 op->o_bd = bd;
521                 rc = ( bd->be_chk_referrals )( op, rs );
522                 op->o_bd = be;
523
524                 op->o_callback = op->o_callback->sc_next;
525         }
526
527         return rc;
528
529 }
530
531 int
532 relay_back_operational( struct slap_op *op, struct slap_rep *rs, 
533                 int opattrs, Attribute **ap )
534 {
535         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
536         BackendDB               *bd;
537         int                     rc = 1;
538
539         bd = ri->ri_bd;
540         if ( bd == NULL) {
541                 bd = select_backend( &op->o_req_ndn, 0, 1 );
542                 if ( bd == NULL ) {
543                         return 1;
544                 }
545         }
546
547         if ( bd->be_operational ) {
548                 BackendDB       *be = op->o_bd;
549                 slap_callback   cb;
550
551                 relay_back_add_cb( &cb, op );
552
553                 op->o_bd = bd;
554                 rc = ( bd->be_operational )( op, rs, opattrs, ap );
555                 op->o_bd = be;
556
557                 op->o_callback = op->o_callback->sc_next;
558         }
559
560         return rc;
561
562 }
563
564 int
565 relay_back_has_subordinates( struct slap_op *op, Entry *e, int *hasSubs )
566 {
567         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
568         BackendDB               *bd;
569         int                     rc = 1;
570
571         bd = ri->ri_bd;
572         if ( bd == NULL) {
573                 bd = select_backend( &op->o_req_ndn, 0, 1 );
574                 if ( bd == NULL ) {
575                         return 1;
576                 }
577         }
578
579         if ( bd->be_has_subordinates ) {
580                 BackendDB       *be = op->o_bd;
581
582                 op->o_bd = bd;
583                 rc = ( bd->be_has_subordinates )( op, e, hasSubs );
584                 op->o_bd = be;
585         }
586
587         return rc;
588
589 }
590
591 int
592 relay_back_connection_init( BackendDB *bd, struct slap_conn *c )
593 {
594         relay_back_info         *ri = (relay_back_info *)bd->be_private;
595
596         bd = ri->ri_bd;
597         if ( bd == NULL ) {
598                 return 0;
599         }
600
601         if ( bd->be_connection_init ) {
602                 return ( bd->be_connection_init )( bd, c );
603         }
604
605         return 0;
606 }
607
608 int
609 relay_back_connection_destroy( BackendDB *bd, struct slap_conn *c )
610 {
611         relay_back_info         *ri = (relay_back_info *)bd->be_private;
612
613         bd = ri->ri_bd;
614         if ( bd == NULL) {
615                 return 0;
616         }
617
618         if ( bd->be_connection_destroy ) {
619                 return ( bd->be_connection_destroy )( bd, c );
620         }
621
622         return 0;
623
624 }
625
626 /*
627  * FIXME: must implement tools as well
628  */