]> git.sur5r.net Git - openldap/blob - servers/slapd/back-relay/op.c
ACIs almost entirely factored out of slapd
[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-2005 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 /*
51  * selects the backend if not enforced at config;
52  * in case of failure, behaves based on err:
53  *      -1                      don't send result
54  *      LDAP_SUCCESS            don't send result; may send referral
55  *      any valid error         send as error result
56  */
57 static BackendDB *
58 relay_back_select_backend( struct slap_op *op, struct slap_rep *rs, int err )
59 {
60         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
61         BackendDB               *bd = ri->ri_bd;
62
63         if ( bd == NULL ) {
64                 bd = select_backend( &op->o_req_ndn, 0, 1 );
65                 if ( bd == op->o_bd ) {
66                         if ( err > LDAP_SUCCESS ) {
67                                 send_ldap_error( op, rs,
68                                                 LDAP_UNWILLING_TO_PERFORM, 
69                                                 "back-relay would call self" );
70                         }
71                         return NULL;
72                 }
73         }
74
75         if ( bd == NULL && err > -1 ) {
76                 if ( default_referral ) {
77                         rs->sr_ref = referral_rewrite( default_referral,
78                                 NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
79                         if ( !rs->sr_ref ) {
80                                 rs->sr_ref = default_referral;
81                         }
82
83                         rs->sr_err = LDAP_REFERRAL;
84                         send_ldap_result( op, rs );
85
86                         if ( rs->sr_ref != default_referral ) {
87                                 ber_bvarray_free( rs->sr_ref );
88                         }
89
90                 } else {
91                         /* NOTE: err is LDAP_INVALID_CREDENTIALS for bind,
92                          * LDAP_NO_SUCH_OBJECT for other operations.
93                          * noSuchObject cannot be returned by bind */
94                         rs->sr_err = err;
95                         send_ldap_result( op, rs );
96                 }
97         }
98
99         return bd;
100 }
101
102 int
103 relay_back_op_bind( struct slap_op *op, struct slap_rep *rs )
104 {
105         BackendDB               *bd;
106         int                     rc = 1;
107
108         bd = relay_back_select_backend( op, rs, LDAP_INVALID_CREDENTIALS );
109         if ( bd == NULL ) {
110                 return rc;
111         }
112
113         if ( bd->be_bind ) {
114                 BackendDB       *be = op->o_bd;
115                 slap_callback   cb;
116
117                 relay_back_add_cb( &cb, op );
118
119                 op->o_bd = bd;
120                 rc = ( bd->be_bind )( op, rs );
121                 op->o_bd = be;
122
123                 if ( op->o_callback == &cb ) {
124                         op->o_callback = op->o_callback->sc_next;
125                 }
126
127         } else {
128                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
129                                 "operation not supported "
130                                 "within naming context" );
131         }
132
133         return rc;
134 }
135
136 int
137 relay_back_op_unbind( struct slap_op *op, struct slap_rep *rs )
138 {
139         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
140         BackendDB               *bd;
141         int                     rc = 1;
142
143         bd = ri->ri_bd;
144         if ( bd == NULL ) {
145                 bd = select_backend( &op->o_req_ndn, 0, 1 );
146         }
147
148         if ( bd && bd->be_unbind ) {
149                 BackendDB       *be = op->o_bd;
150                 slap_callback   cb;
151
152                 relay_back_add_cb( &cb, op );
153
154                 op->o_bd = bd;
155                 rc = ( bd->be_unbind )( op, rs );
156                 op->o_bd = be;
157
158                 if ( op->o_callback == &cb ) {
159                         op->o_callback = op->o_callback->sc_next;
160                 }
161         }
162
163         return 0;
164
165 }
166
167 int
168 relay_back_op_search( struct slap_op *op, struct slap_rep *rs )
169 {
170         BackendDB               *bd;
171         int                     rc = 1;
172
173         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
174         if ( bd == NULL ) {
175                 return 1;
176         }
177
178         if ( bd->be_search ) {
179                 BackendDB       *be = op->o_bd;
180                 slap_callback   cb;
181
182                 relay_back_add_cb( &cb, op );
183
184                 op->o_bd = bd;
185                 rc = ( bd->be_search )( op, rs );
186                 op->o_bd = be;
187
188                 if ( op->o_callback == &cb ) {
189                         op->o_callback = op->o_callback->sc_next;
190                 }
191
192         } else {
193                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
194                                 "operation not supported "
195                                 "within naming context" );
196         }
197
198         return rc;
199
200 }
201
202 int
203 relay_back_op_compare( struct slap_op *op, struct slap_rep *rs )
204 {
205         BackendDB               *bd;
206         int                     rc = 1;
207
208         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
209         if ( bd == NULL ) {
210                 return 1;
211         }
212
213         if ( bd->be_compare ) {
214                 BackendDB       *be = op->o_bd;
215                 slap_callback   cb;
216
217                 relay_back_add_cb( &cb, op );
218
219                 op->o_bd = bd;
220                 rc = ( bd->be_compare )( op, rs );
221                 op->o_bd = be;
222
223                 if ( op->o_callback == &cb ) {
224                         op->o_callback = op->o_callback->sc_next;
225                 }
226
227         } else {
228                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
229                                 "operation not supported "
230                                 "within naming context" );
231         }
232
233         return rc;
234
235 }
236
237 int
238 relay_back_op_modify( struct slap_op *op, struct slap_rep *rs )
239 {
240         BackendDB               *bd;
241         int                     rc = 1;
242
243         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
244         if ( bd == NULL ) {
245                 return 1;
246         }
247
248         if ( bd->be_modify ) {
249                 BackendDB       *be = op->o_bd;
250                 slap_callback   cb;
251
252                 relay_back_add_cb( &cb, op );
253
254                 op->o_bd = bd;
255                 rc = ( bd->be_modify )( op, rs );
256                 op->o_bd = be;
257
258                 if ( op->o_callback == &cb ) {
259                         op->o_callback = op->o_callback->sc_next;
260                 }
261
262         } else {
263                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
264                                 "operation not supported "
265                                 "within naming context" );
266         }
267
268         return rc;
269
270 }
271
272 int
273 relay_back_op_modrdn( struct slap_op *op, struct slap_rep *rs )
274 {
275         BackendDB               *bd;
276         int                     rc = 1;
277
278         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
279         if ( bd == NULL ) {
280                 return 1;
281         }
282
283         if ( bd->be_modrdn ) {
284                 BackendDB       *be = op->o_bd;
285                 slap_callback   cb;
286
287                 relay_back_add_cb( &cb, op );
288
289                 op->o_bd = bd;
290                 rc = ( bd->be_modrdn )( op, rs );
291                 op->o_bd = be;
292
293                 if ( op->o_callback == &cb ) {
294                         op->o_callback = op->o_callback->sc_next;
295                 }
296
297         } else {
298                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
299                                 "operation not supported "
300                                 "within naming context" );
301         }
302
303         return rc;
304
305 }
306
307 int
308 relay_back_op_add( struct slap_op *op, struct slap_rep *rs )
309 {
310         BackendDB               *bd;
311         int                     rc = 1;
312
313         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
314         if ( bd == NULL ) {
315                 return 1;
316         }
317
318         if ( bd->be_add ) {
319                 BackendDB       *be = op->o_bd;
320                 slap_callback   cb;
321
322                 relay_back_add_cb( &cb, op );
323
324                 op->o_bd = bd;
325                 rc = ( bd->be_add )( op, rs );
326                 op->o_bd = be;
327
328                 if ( op->o_callback == &cb ) {
329                         op->o_callback = op->o_callback->sc_next;
330                 }
331
332         } else {
333                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
334                                 "operation not supported "
335                                 "within naming context" );
336         }
337
338         return rc;
339
340 }
341
342 int
343 relay_back_op_delete( struct slap_op *op, struct slap_rep *rs )
344 {
345         BackendDB               *bd;
346         int                     rc = 1;
347
348         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
349         if ( bd == NULL ) {
350                 return 1;
351         }
352
353         if ( bd->be_delete ) {
354                 BackendDB       *be = op->o_bd;
355                 slap_callback   cb;
356
357                 relay_back_add_cb( &cb, op );
358
359                 op->o_bd = bd;
360                 rc = ( bd->be_delete )( op, rs );
361                 op->o_bd = be;
362
363                 if ( op->o_callback == &cb ) {
364                         op->o_callback = op->o_callback->sc_next;
365                 }
366         }
367
368         return rc;
369
370 }
371
372 int
373 relay_back_op_abandon( struct slap_op *op, struct slap_rep *rs )
374 {
375         BackendDB               *bd;
376         int                     rc = 1;
377
378         bd = relay_back_select_backend( op, rs, -1 );
379         if ( bd == NULL ) {
380                 return 1;
381         }
382
383         if ( bd->be_abandon ) {
384                 BackendDB       *be = op->o_bd;
385                 slap_callback   cb;
386
387                 relay_back_add_cb( &cb, op );
388
389                 op->o_bd = bd;
390                 rc = ( bd->be_abandon )( op, rs );
391                 op->o_bd = be;
392
393                 if ( op->o_callback == &cb ) {
394                         op->o_callback = op->o_callback->sc_next;
395                 }
396         }
397
398         return rc;
399
400 }
401
402 int
403 relay_back_op_cancel( struct slap_op *op, struct slap_rep *rs )
404 {
405         BackendDB               *bd;
406         int                     rc = 1;
407
408         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
409         if ( bd == NULL ) {
410                 return 1;
411         }
412
413         if ( bd->be_cancel ) {
414                 BackendDB       *be = op->o_bd;
415                 slap_callback   cb;
416
417                 relay_back_add_cb( &cb, op );
418
419                 op->o_bd = bd;
420                 rc = ( bd->be_cancel )( op, rs );
421                 op->o_bd = be;
422
423                 if ( op->o_callback == &cb ) {
424                         op->o_callback = op->o_callback->sc_next;
425                 }
426
427         } else {
428                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
429                                 "operation not supported "
430                                 "within naming context" );
431         }
432
433         return rc;
434
435 }
436
437 int
438 relay_back_op_extended( struct slap_op *op, struct slap_rep *rs )
439 {
440         BackendDB               *bd;
441         int                     rc = 1;
442
443         bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
444         if ( bd == NULL ) {
445                 return 1;
446         }
447
448         if ( bd->be_extended ) {
449                 BackendDB       *be = op->o_bd;
450                 slap_callback   cb;
451
452                 relay_back_add_cb( &cb, op );
453
454                 op->o_bd = bd;
455                 rc = ( bd->be_extended )( op, rs );
456                 op->o_bd = be;
457
458                 if ( op->o_callback == &cb ) {
459                         op->o_callback = op->o_callback->sc_next;
460                 }
461
462         } else {
463                 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
464                                 "operation not supported "
465                                 "within naming context" );
466         }
467
468         return rc;
469
470 }
471
472 int
473 relay_back_entry_release_rw( struct slap_op *op, Entry *e, int rw )
474 {
475         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
476         BackendDB               *bd;
477         int                     rc = 1;
478
479         bd = ri->ri_bd;
480         if ( bd == NULL) {
481                 bd = select_backend( &op->o_req_ndn, 0, 1 );
482                 if ( bd == NULL ) {
483                         return 1;
484                 }
485         }
486
487         if ( bd->be_release ) {
488                 BackendDB       *be = op->o_bd;
489
490                 op->o_bd = bd;
491                 rc = ( bd->be_release )( op, e, rw );
492                 op->o_bd = be;
493         }
494
495         return rc;
496
497 }
498
499 int
500 relay_back_entry_get_rw( struct slap_op *op, struct berval *ndn,
501         ObjectClass *oc, AttributeDescription *at, int rw, Entry **e )
502 {
503         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
504         BackendDB               *bd;
505         int                     rc = 1;
506
507         bd = ri->ri_bd;
508         if ( bd == NULL) {
509                 bd = select_backend( &op->o_req_ndn, 0, 1 );
510                 if ( bd == NULL ) {
511                         return 1;
512                 }
513         }
514
515         if ( bd->be_fetch ) {
516                 BackendDB       *be = op->o_bd;
517
518                 op->o_bd = bd;
519                 rc = ( bd->be_fetch )( op, ndn, oc, at, rw, e );
520                 op->o_bd = be;
521         }
522
523         return rc;
524
525 }
526
527 /*
528  * NOTE: even the existence of this function is questionable: we cannot
529  * pass the bi_chk_referrals() call thru the rwm overlay because there
530  * is no way to rewrite the req_dn back; but then relay_back_chk_referrals()
531  * is passing the target database a DN that likely does not belong to its
532  * naming context... mmmh.
533  */
534 int
535 relay_back_chk_referrals( struct slap_op *op, struct slap_rep *rs )
536 {
537         BackendDB               *bd;
538         int                     rc = 0;
539
540         bd = relay_back_select_backend( op, rs, LDAP_SUCCESS );
541         /* FIXME: this test only works if there are no overlays, so
542          * it is nearly useless; if made stricter, no nested back-relays
543          * can be instantiated... too bad. */
544         if ( bd == NULL || bd == op->o_bd ) {
545                 return 0;
546         }
547
548         /* no nested back-relays... */
549         if ( overlay_is_over( bd ) ) {
550                 slap_overinfo   *oi = (slap_overinfo *)bd->bd_info->bi_private;
551
552                 if ( oi->oi_orig == op->o_bd->bd_info ) {
553                         return 0;
554                 }
555         }
556
557         if ( bd->be_chk_referrals ) {
558                 BackendDB       *be = op->o_bd;
559                 slap_callback   cb;
560
561                 relay_back_add_cb( &cb, op );
562
563                 op->o_bd = bd;
564                 rc = ( bd->be_chk_referrals )( op, rs );
565                 op->o_bd = be;
566
567                 if ( op->o_callback == &cb ) {
568                         op->o_callback = op->o_callback->sc_next;
569                 }
570         }
571
572         return rc;
573
574 }
575
576 int
577 relay_back_operational( struct slap_op *op, struct slap_rep *rs )
578 {
579         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
580         BackendDB               *bd;
581         int                     rc = 1;
582
583         bd = ri->ri_bd;
584         if ( bd == NULL) {
585                 bd = select_backend( &op->o_req_ndn, 0, 1 );
586                 if ( bd == NULL ) {
587                         return 1;
588                 }
589         }
590
591         if ( bd->be_operational ) {
592                 BackendDB       *be = op->o_bd;
593                 slap_callback   cb;
594
595                 relay_back_add_cb( &cb, op );
596
597                 op->o_bd = bd;
598                 rc = ( bd->be_operational )( op, rs );
599                 op->o_bd = be;
600
601                 if ( op->o_callback == &cb ) {
602                         op->o_callback = op->o_callback->sc_next;
603                 }
604         }
605
606         return rc;
607
608 }
609
610 int
611 relay_back_has_subordinates( struct slap_op *op, Entry *e, int *hasSubs )
612 {
613         relay_back_info         *ri = (relay_back_info *)op->o_bd->be_private;
614         BackendDB               *bd;
615         int                     rc = 1;
616
617         bd = ri->ri_bd;
618         if ( bd == NULL) {
619                 bd = select_backend( &op->o_req_ndn, 0, 1 );
620                 if ( bd == NULL ) {
621                         return 1;
622                 }
623         }
624
625         if ( bd->be_has_subordinates ) {
626                 BackendDB       *be = op->o_bd;
627
628                 op->o_bd = bd;
629                 rc = ( bd->be_has_subordinates )( op, e, hasSubs );
630                 op->o_bd = be;
631         }
632
633         return rc;
634
635 }
636
637 int
638 relay_back_connection_init( BackendDB *bd, struct slap_conn *c )
639 {
640         relay_back_info         *ri = (relay_back_info *)bd->be_private;
641
642         bd = ri->ri_bd;
643         if ( bd == NULL ) {
644                 return 0;
645         }
646
647         if ( bd->be_connection_init ) {
648                 return ( bd->be_connection_init )( bd, c );
649         }
650
651         return 0;
652 }
653
654 int
655 relay_back_connection_destroy( BackendDB *bd, struct slap_conn *c )
656 {
657         relay_back_info         *ri = (relay_back_info *)bd->be_private;
658
659         bd = ri->ri_bd;
660         if ( bd == NULL) {
661                 return 0;
662         }
663
664         if ( bd->be_connection_destroy ) {
665                 return ( bd->be_connection_destroy )( bd, c );
666         }
667
668         return 0;
669
670 }
671
672 /*
673  * FIXME: must implement tools as well
674  */