1 /* op.c - relay backend operations */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 2004-2007 The OpenLDAP Foundation.
5 * Portions Copyright 2004 Pierangelo Masarati.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
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>.
17 * This work was initially developed by Pierangelo Masarati for inclusion
18 * in OpenLDAP Software.
26 #include "back-relay.h"
29 relay_back_swap_bd( Operation *op, SlapReply *rs )
31 slap_callback *cb = op->o_callback;
32 BackendDB *be = op->o_bd;
34 op->o_bd = cb->sc_private;
37 return SLAP_CB_CONTINUE;
41 relay_back_add_cb( slap_callback *cb, Operation *op )
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;
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
58 relay_back_select_backend( Operation *op, SlapReply *rs, int err, int dosend )
60 relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
61 BackendDB *bd = ri->ri_bd;
63 if ( bd == NULL && !BER_BVISNULL( &op->o_req_ndn ) ) {
64 bd = select_backend( &op->o_req_ndn, 1 );
65 if ( bd == op->o_bd ) {
66 if ( err > LDAP_SUCCESS && dosend ) {
67 send_ldap_error( op, rs,
68 LDAP_UNWILLING_TO_PERFORM,
69 "back-relay would call self" );
75 if ( bd == NULL && err > -1 ) {
76 if ( default_referral ) {
77 rs->sr_err = LDAP_REFERRAL;
79 rs->sr_ref = referral_rewrite(
84 rs->sr_ref = default_referral;
87 send_ldap_result( op, rs );
89 if ( rs->sr_ref != default_referral ) {
90 ber_bvarray_free( rs->sr_ref );
95 /* NOTE: err is LDAP_INVALID_CREDENTIALS for bind,
96 * LDAP_NO_SUCH_OBJECT for other operations.
97 * noSuchObject cannot be returned by bind */
100 send_ldap_result( op, rs );
109 relay_back_op_bind( Operation *op, SlapReply *rs )
114 /* allow rootdn as a means to auth without the need to actually
115 * contact the proxied DSA */
116 switch ( be_rootdn_bind( op, rs ) ) {
117 case SLAP_CB_CONTINUE:
124 bd = relay_back_select_backend( op, rs, LDAP_INVALID_CREDENTIALS, 1 );
130 BackendDB *be = op->o_bd;
133 relay_back_add_cb( &cb, op );
136 rc = bd->be_bind( op, rs );
139 if ( op->o_callback == &cb ) {
140 op->o_callback = op->o_callback->sc_next;
144 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
145 "operation not supported "
146 "within naming context" );
153 relay_back_op_unbind( Operation *op, SlapReply *rs )
158 bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 0 );
163 if ( bd && bd->be_unbind ) {
164 BackendDB *be = op->o_bd;
167 relay_back_add_cb( &cb, op );
170 rc = bd->be_unbind( op, rs );
173 if ( op->o_callback == &cb ) {
174 op->o_callback = op->o_callback->sc_next;
183 relay_back_op_search( Operation *op, SlapReply *rs )
188 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
193 if ( bd->be_search ) {
194 BackendDB *be = op->o_bd;
197 relay_back_add_cb( &cb, op );
200 rc = bd->be_search( op, rs );
203 if ( op->o_callback == &cb ) {
204 op->o_callback = op->o_callback->sc_next;
208 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
209 "operation not supported "
210 "within naming context" );
218 relay_back_op_compare( Operation *op, SlapReply *rs )
223 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
228 if ( bd->be_compare ) {
229 BackendDB *be = op->o_bd;
232 relay_back_add_cb( &cb, op );
235 rc = bd->be_compare( op, rs );
238 if ( op->o_callback == &cb ) {
239 op->o_callback = op->o_callback->sc_next;
243 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
244 "operation not supported "
245 "within naming context" );
253 relay_back_op_modify( Operation *op, SlapReply *rs )
258 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
263 if ( bd->be_modify ) {
264 BackendDB *be = op->o_bd;
267 relay_back_add_cb( &cb, op );
270 rc = bd->be_modify( op, rs );
273 if ( op->o_callback == &cb ) {
274 op->o_callback = op->o_callback->sc_next;
278 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
279 "operation not supported "
280 "within naming context" );
288 relay_back_op_modrdn( Operation *op, SlapReply *rs )
293 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
298 if ( bd->be_modrdn ) {
299 BackendDB *be = op->o_bd;
302 relay_back_add_cb( &cb, op );
305 rc = bd->be_modrdn( op, rs );
308 if ( op->o_callback == &cb ) {
309 op->o_callback = op->o_callback->sc_next;
313 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
314 "operation not supported "
315 "within naming context" );
323 relay_back_op_add( Operation *op, SlapReply *rs )
328 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
334 BackendDB *be = op->o_bd;
337 relay_back_add_cb( &cb, op );
340 rc = bd->be_add( op, rs );
343 if ( op->o_callback == &cb ) {
344 op->o_callback = op->o_callback->sc_next;
348 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
349 "operation not supported "
350 "within naming context" );
358 relay_back_op_delete( Operation *op, SlapReply *rs )
363 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
368 if ( bd->be_delete ) {
369 BackendDB *be = op->o_bd;
372 relay_back_add_cb( &cb, op );
375 rc = bd->be_delete( op, rs );
378 if ( op->o_callback == &cb ) {
379 op->o_callback = op->o_callback->sc_next;
388 relay_back_op_abandon( Operation *op, SlapReply *rs )
393 bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 0 );
398 if ( bd->be_abandon ) {
399 BackendDB *be = op->o_bd;
402 relay_back_add_cb( &cb, op );
405 rc = bd->be_abandon( op, rs );
408 if ( op->o_callback == &cb ) {
409 op->o_callback = op->o_callback->sc_next;
418 relay_back_op_cancel( Operation *op, SlapReply *rs )
423 bd = relay_back_select_backend( op, rs, LDAP_CANNOT_CANCEL, 0 );
428 if ( bd->be_cancel ) {
429 BackendDB *be = op->o_bd;
432 relay_back_add_cb( &cb, op );
435 rc = bd->be_cancel( op, rs );
438 if ( op->o_callback == &cb ) {
439 op->o_callback = op->o_callback->sc_next;
443 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
444 "operation not supported "
445 "within naming context" );
453 relay_back_op_extended( Operation *op, SlapReply *rs )
458 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 0 );
463 if ( bd->be_extended ) {
464 BackendDB *be = op->o_bd;
467 relay_back_add_cb( &cb, op );
470 rc = bd->be_extended( op, rs );
473 if ( op->o_callback == &cb ) {
474 op->o_callback = op->o_callback->sc_next;
478 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
479 "operation not supported "
480 "within naming context" );
488 relay_back_entry_release_rw( Operation *op, Entry *e, int rw )
490 relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
496 bd = select_backend( &op->o_req_ndn, 1 );
502 if ( bd->be_release ) {
503 BackendDB *be = op->o_bd;
506 rc = bd->be_release( op, e, rw );
515 relay_back_entry_get_rw( Operation *op, struct berval *ndn,
516 ObjectClass *oc, AttributeDescription *at, int rw, Entry **e )
518 relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
524 bd = select_backend( &op->o_req_ndn, 1 );
530 if ( bd->be_fetch ) {
531 BackendDB *be = op->o_bd;
534 rc = bd->be_fetch( op, ndn, oc, at, rw, e );
543 * NOTE: even the existence of this function is questionable: we cannot
544 * pass the bi_chk_referrals() call thru the rwm overlay because there
545 * is no way to rewrite the req_dn back; but then relay_back_chk_referrals()
546 * is passing the target database a DN that likely does not belong to its
547 * naming context... mmmh.
550 relay_back_chk_referrals( Operation *op, SlapReply *rs )
555 bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 1 );
556 /* FIXME: this test only works if there are no overlays, so
557 * it is nearly useless; if made stricter, no nested back-relays
558 * can be instantiated... too bad. */
559 if ( bd == NULL || bd == op->o_bd ) {
563 /* no nested back-relays... */
564 if ( overlay_is_over( bd ) ) {
565 slap_overinfo *oi = (slap_overinfo *)bd->bd_info->bi_private;
567 if ( oi->oi_orig == op->o_bd->bd_info ) {
572 if ( bd->be_chk_referrals ) {
573 BackendDB *be = op->o_bd;
576 relay_back_add_cb( &cb, op );
579 rc = bd->be_chk_referrals( op, rs );
582 if ( op->o_callback == &cb ) {
583 op->o_callback = op->o_callback->sc_next;
592 relay_back_operational( Operation *op, SlapReply *rs )
597 bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 0 );
598 /* FIXME: this test only works if there are no overlays, so
599 * it is nearly useless; if made stricter, no nested back-relays
600 * can be instantiated... too bad. */
601 if ( bd == NULL || bd == op->o_bd ) {
605 if ( bd->be_operational ) {
606 BackendDB *be = op->o_bd;
609 relay_back_add_cb( &cb, op );
612 rc = bd->be_operational( op, rs );
615 if ( op->o_callback == &cb ) {
616 op->o_callback = op->o_callback->sc_next;
625 relay_back_has_subordinates( Operation *op, Entry *e, int *hasSubs )
627 SlapReply rs = { 0 };
631 bd = relay_back_select_backend( op, &rs, LDAP_SUCCESS, 0 );
632 /* FIXME: this test only works if there are no overlays, so
633 * it is nearly useless; if made stricter, no nested back-relays
634 * can be instantiated... too bad. */
635 if ( bd == NULL || bd == op->o_bd ) {
639 if ( bd->be_has_subordinates ) {
640 BackendDB *be = op->o_bd;
643 rc = bd->be_has_subordinates( op, e, hasSubs );
652 relay_back_connection_init( BackendDB *bd, Connection *c )
654 relay_back_info *ri = (relay_back_info *)bd->be_private;
661 if ( bd->be_connection_init ) {
662 return bd->be_connection_init( bd, c );
669 relay_back_connection_destroy( BackendDB *bd, Connection *c )
671 relay_back_info *ri = (relay_back_info *)bd->be_private;
678 if ( bd->be_connection_destroy ) {
679 return bd->be_connection_destroy( bd, c );
687 * FIXME: must implement tools as well