From 8517e7199ae2902629368cbb6f77d013b087ab2e Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Wed, 16 Jan 2008 21:53:44 +0000 Subject: [PATCH] rework back-relay internals along Hallvard's suggestions (ITS#5328) --- servers/slapd/back-relay/op.c | 430 ++++++++++------------------------ 1 file changed, 130 insertions(+), 300 deletions(-) diff --git a/servers/slapd/back-relay/op.c b/servers/slapd/back-relay/op.c index bf02c6f0d5..7397ee40c4 100644 --- a/servers/slapd/back-relay/op.c +++ b/servers/slapd/back-relay/op.c @@ -25,6 +25,14 @@ #include "slap.h" #include "back-relay.h" +#define RB_ERR_MASK (0x00FFU) +#define RB_ERR (0x1000U) +#define RB_UNWILLING (0x2000U) +#define RB_REFERRAL (0x4000U) +#define RB_SEND (0x8000U) +#define RB_UNWILLING_SEND (RB_UNWILLING|RB_SEND) +#define RB_REFERRAL_SEND (RB_REFERRAL|RB_SEND) + static int relay_back_swap_bd( Operation *op, SlapReply *rs ) { @@ -37,45 +45,54 @@ relay_back_swap_bd( Operation *op, SlapReply *rs ) return SLAP_CB_CONTINUE; } -static void -relay_back_add_cb( slap_callback *cb, Operation *op ) -{ - cb->sc_next = op->o_callback; - cb->sc_response = relay_back_swap_bd; - cb->sc_cleanup = relay_back_swap_bd; - cb->sc_private = op->o_bd; - op->o_callback = cb; -} +#define relay_back_add_cb( cb, op ) \ + { \ + (cb)->sc_next = (op)->o_callback; \ + (cb)->sc_response = relay_back_swap_bd; \ + (cb)->sc_cleanup = relay_back_swap_bd; \ + (cb)->sc_private = (op)->o_bd; \ + (op)->o_callback = (cb); \ + } /* * selects the backend if not enforced at config; * in case of failure, behaves based on err: * -1 don't send result - * LDAP_SUCCESS don't send result; may send referral - * any valid error send as error result + * LDAP_SUCCESS don't send result; may send referral if dosend + * any valid error send as error result if dosend */ static BackendDB * -relay_back_select_backend( Operation *op, SlapReply *rs, int err, int dosend ) +relay_back_select_backend( Operation *op, SlapReply *rs, slap_mask_t fail_mode ) { relay_back_info *ri = (relay_back_info *)op->o_bd->be_private; BackendDB *bd = ri->ri_bd; + int rc = ( fail_mode & RB_ERR_MASK ); if ( bd == NULL && !BER_BVISNULL( &op->o_req_ndn ) ) { bd = select_backend( &op->o_req_ndn, 1 ); if ( bd == op->o_bd ) { - rs->sr_err = LDAP_UNWILLING_TO_PERFORM; - rs->sr_text = "back-relay would call self"; - if ( err > LDAP_SUCCESS && dosend ) { + Debug( LDAP_DEBUG_ANY, + "%s: back-relay for DN=\"%s\" would call self.\n", + op->o_log_prefix, op->o_req_dn.bv_val, 0 ); + if ( fail_mode & RB_UNWILLING ) { + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + + } else if ( fail_mode & RB_ERR ) { + rs->sr_err = rc; + } + + if ( fail_mode & RB_SEND ) { send_ldap_result( op, rs ); } + return NULL; } } - if ( bd == NULL && err > -1 ) { + if ( bd == NULL && fail_mode & RB_REFERRAL ) { if ( default_referral ) { rs->sr_err = LDAP_REFERRAL; - if ( dosend ) { + if ( fail_mode & RB_SEND ) { rs->sr_ref = referral_rewrite( default_referral, NULL, &op->o_req_dn, @@ -95,8 +112,8 @@ relay_back_select_backend( Operation *op, SlapReply *rs, int err, int dosend ) /* NOTE: err is LDAP_INVALID_CREDENTIALS for bind, * LDAP_NO_SUCH_OBJECT for other operations. * noSuchObject cannot be returned by bind */ - rs->sr_err = err; - if ( dosend ) { + rs->sr_err = rc; + if ( fail_mode & RB_SEND ) { send_ldap_result( op, rs ); } } @@ -105,35 +122,24 @@ relay_back_select_backend( Operation *op, SlapReply *rs, int err, int dosend ) return bd; } -int -relay_back_op_bind( Operation *op, SlapReply *rs ) +static int +relay_back_op( + Operation *op, + SlapReply *rs, + BackendDB *bd, + BI_op_func *func, + slap_mask_t fail_mode ) { - BackendDB *bd; - int rc = 1; + int rc = ( fail_mode & RB_ERR_MASK ); - /* allow rootdn as a means to auth without the need to actually - * contact the proxied DSA */ - switch ( be_rootdn_bind( op, rs ) ) { - case SLAP_CB_CONTINUE: - break; - - default: - return rs->sr_err; - } - - bd = relay_back_select_backend( op, rs, LDAP_INVALID_CREDENTIALS, 1 ); - if ( bd == NULL ) { - return rs->sr_err; - } - - if ( bd->be_bind ) { + if ( func ) { BackendDB *be = op->o_bd; slap_callback cb; relay_back_add_cb( &cb, op ); op->o_bd = bd; - rc = bd->be_bind( op, rs ); + rc = func( op, rs ); op->o_bd = be; if ( op->o_callback == &cb ) { @@ -141,346 +147,201 @@ relay_back_op_bind( Operation *op, SlapReply *rs ) } } else { - send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, - "operation not supported " - "within naming context" ); + if ( fail_mode & RB_ERR ) { + rs->sr_err = rc; + + } else if ( fail_mode & RB_UNWILLING ) { + rc = rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + rs->sr_text = "operation not supported within naming context"; + } + + if ( fail_mode & RB_SEND ) { + send_ldap_result( op, rs ); + } } return rc; } int -relay_back_op_unbind( Operation *op, SlapReply *rs ) +relay_back_op_bind( Operation *op, SlapReply *rs ) { - BackendDB *bd; - int rc = 1; + BackendDB *bd; - bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 0 ); - if ( bd == NULL ) { + /* allow rootdn as a means to auth without the need to actually + * contact the proxied DSA */ + switch ( be_rootdn_bind( op, rs ) ) { + case SLAP_CB_CONTINUE: + break; + + default: return rs->sr_err; } - if ( bd && bd->be_unbind ) { - BackendDB *be = op->o_bd; - slap_callback cb; + bd = relay_back_select_backend( op, rs, + ( LDAP_INVALID_CREDENTIALS | RB_ERR | RB_SEND ) ); + if ( bd == NULL ) { + return rs->sr_err; + } - relay_back_add_cb( &cb, op ); + return relay_back_op( op, rs, bd, bd->be_bind, + ( LDAP_INVALID_CREDENTIALS | RB_ERR | RB_SEND ) ); +} - op->o_bd = bd; - rc = bd->be_unbind( op, rs ); - op->o_bd = be; +int +relay_back_op_unbind( Operation *op, SlapReply *rs ) +{ + BackendDB *bd; - if ( op->o_callback == &cb ) { - op->o_callback = op->o_callback->sc_next; - } + bd = relay_back_select_backend( op, rs, 0 ); + if ( bd != NULL ) { + (void)relay_back_op( op, rs, bd, bd->be_unbind, 0 ); } return 0; - } int relay_back_op_search( Operation *op, SlapReply *rs ) { BackendDB *bd; - int rc = 1; - bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 ); + bd = relay_back_select_backend( op, rs, + ( LDAP_NO_SUCH_OBJECT | RB_ERR | RB_SEND ) ); if ( bd == NULL ) { return rs->sr_err; } - if ( bd->be_search ) { - BackendDB *be = op->o_bd; - slap_callback cb; - - relay_back_add_cb( &cb, op ); - - op->o_bd = bd; - rc = bd->be_search( op, rs ); - op->o_bd = be; - - if ( op->o_callback == &cb ) { - op->o_callback = op->o_callback->sc_next; - } - - } else { - send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, - "operation not supported " - "within naming context" ); - } - - return rc; - + return relay_back_op( op, rs, bd, bd->be_search, + RB_UNWILLING_SEND ); } int relay_back_op_compare( Operation *op, SlapReply *rs ) { BackendDB *bd; - int rc = 1; - bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 ); + bd = relay_back_select_backend( op, rs, + ( LDAP_NO_SUCH_OBJECT | RB_ERR | RB_SEND ) ); if ( bd == NULL ) { return rs->sr_err; } - if ( bd->be_compare ) { - BackendDB *be = op->o_bd; - slap_callback cb; - - relay_back_add_cb( &cb, op ); - - op->o_bd = bd; - rc = bd->be_compare( op, rs ); - op->o_bd = be; - - if ( op->o_callback == &cb ) { - op->o_callback = op->o_callback->sc_next; - } - - } else { - send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, - "operation not supported " - "within naming context" ); - } - - return rc; - + return relay_back_op( op, rs, bd, bd->be_compare, + RB_UNWILLING_SEND ); } int relay_back_op_modify( Operation *op, SlapReply *rs ) { BackendDB *bd; - int rc = 1; - bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 ); + bd = relay_back_select_backend( op, rs, + ( LDAP_NO_SUCH_OBJECT | RB_ERR | RB_SEND ) ); if ( bd == NULL ) { return rs->sr_err; } - if ( bd->be_modify ) { - BackendDB *be = op->o_bd; - slap_callback cb; - - relay_back_add_cb( &cb, op ); - - op->o_bd = bd; - rc = bd->be_modify( op, rs ); - op->o_bd = be; - - if ( op->o_callback == &cb ) { - op->o_callback = op->o_callback->sc_next; - } - - } else { - send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, - "operation not supported " - "within naming context" ); - } - - return rc; - + return relay_back_op( op, rs, bd, bd->be_modify, + RB_UNWILLING_SEND ); } int relay_back_op_modrdn( Operation *op, SlapReply *rs ) { BackendDB *bd; - int rc = 1; - bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 ); + bd = relay_back_select_backend( op, rs, + ( LDAP_NO_SUCH_OBJECT | RB_ERR | RB_SEND ) ); if ( bd == NULL ) { return rs->sr_err; } - if ( bd->be_modrdn ) { - BackendDB *be = op->o_bd; - slap_callback cb; - - relay_back_add_cb( &cb, op ); - - op->o_bd = bd; - rc = bd->be_modrdn( op, rs ); - op->o_bd = be; - - if ( op->o_callback == &cb ) { - op->o_callback = op->o_callback->sc_next; - } - - } else { - send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, - "operation not supported " - "within naming context" ); - } - - return rc; - + return relay_back_op( op, rs, bd, bd->be_modrdn, + RB_UNWILLING_SEND ); } int relay_back_op_add( Operation *op, SlapReply *rs ) { BackendDB *bd; - int rc = 1; - bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 ); + bd = relay_back_select_backend( op, rs, + ( LDAP_NO_SUCH_OBJECT | RB_ERR | RB_SEND ) ); if ( bd == NULL ) { return rs->sr_err; } - if ( bd->be_add ) { - BackendDB *be = op->o_bd; - slap_callback cb; - - relay_back_add_cb( &cb, op ); - - op->o_bd = bd; - rc = bd->be_add( op, rs ); - op->o_bd = be; - - if ( op->o_callback == &cb ) { - op->o_callback = op->o_callback->sc_next; - } - - } else { - send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, - "operation not supported " - "within naming context" ); - } - - return rc; - + return relay_back_op( op, rs, bd, bd->be_add, + RB_UNWILLING_SEND ); } int relay_back_op_delete( Operation *op, SlapReply *rs ) { BackendDB *bd; - int rc = 1; - bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 ); + bd = relay_back_select_backend( op, rs, + ( LDAP_NO_SUCH_OBJECT | RB_ERR | RB_SEND ) ); if ( bd == NULL ) { return rs->sr_err; } - if ( bd->be_delete ) { - BackendDB *be = op->o_bd; - slap_callback cb; - - relay_back_add_cb( &cb, op ); - - op->o_bd = bd; - rc = bd->be_delete( op, rs ); - op->o_bd = be; - - if ( op->o_callback == &cb ) { - op->o_callback = op->o_callback->sc_next; - } - } - - return rc; - + return relay_back_op( op, rs, bd, bd->be_delete, + RB_UNWILLING_SEND ); } int relay_back_op_abandon( Operation *op, SlapReply *rs ) { BackendDB *bd; - int rc = 1; - bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 0 ); + bd = relay_back_select_backend( op, rs, 0 ); if ( bd == NULL ) { return rs->sr_err; } - if ( bd->be_abandon ) { - BackendDB *be = op->o_bd; - slap_callback cb; - - relay_back_add_cb( &cb, op ); - - op->o_bd = bd; - rc = bd->be_abandon( op, rs ); - op->o_bd = be; - - if ( op->o_callback == &cb ) { - op->o_callback = op->o_callback->sc_next; - } - } - - return rc; - + return relay_back_op( op, rs, bd, bd->be_abandon, 0 ); } int relay_back_op_cancel( Operation *op, SlapReply *rs ) { BackendDB *bd; - int rc = 1; + int rc; - bd = relay_back_select_backend( op, rs, LDAP_CANNOT_CANCEL, 0 ); + bd = relay_back_select_backend( op, rs, + ( LDAP_CANNOT_CANCEL | RB_ERR ) ); if ( bd == NULL ) { + if ( op->o_cancel == SLAP_CANCEL_REQ ) { + op->o_cancel = LDAP_CANNOT_CANCEL; + } return rs->sr_err; } - if ( bd->be_cancel ) { - BackendDB *be = op->o_bd; - slap_callback cb; - - relay_back_add_cb( &cb, op ); - - op->o_bd = bd; - rc = bd->be_cancel( op, rs ); - op->o_bd = be; - - if ( op->o_callback == &cb ) { - op->o_callback = op->o_callback->sc_next; - } - - } else { - send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, - "operation not supported " - "within naming context" ); + rc = relay_back_op( op, rs, bd, bd->be_cancel, + ( LDAP_CANNOT_CANCEL | RB_ERR ) ); + if ( rc == LDAP_CANNOT_CANCEL && op->o_cancel == SLAP_CANCEL_REQ ) + { + op->o_cancel = LDAP_CANNOT_CANCEL; } return rc; - } int relay_back_op_extended( Operation *op, SlapReply *rs ) { BackendDB *bd; - int rc; - bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 0 ); + bd = relay_back_select_backend( op, rs, + ( LDAP_NO_SUCH_OBJECT | RB_ERR ) ); if ( bd == NULL ) { return rs->sr_err; } - if ( bd->be_extended ) { - BackendDB *be = op->o_bd; - slap_callback cb; - - relay_back_add_cb( &cb, op ); - - op->o_bd = bd; - rc = bd->be_extended( op, rs ); - op->o_bd = be; - - if ( op->o_callback == &cb ) { - op->o_callback = op->o_callback->sc_next; - } - - } else { - rc = rs->sr_err = LDAP_UNWILLING_TO_PERFORM; - rs->sr_text = "operation not supported within naming context"; - } - - return rc; - + return relay_back_op( op, rs, bd, bd->be_extended, + RB_UNWILLING ); } int @@ -549,9 +410,9 @@ int relay_back_chk_referrals( Operation *op, SlapReply *rs ) { BackendDB *bd; - int rc = 0; - bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 1 ); + bd = relay_back_select_backend( op, rs, + ( LDAP_SUCCESS | RB_ERR | RB_SEND ) ); /* FIXME: this test only works if there are no overlays, so * it is nearly useless; if made stricter, no nested back-relays * can be instantiated... too bad. */ @@ -568,32 +429,16 @@ relay_back_chk_referrals( Operation *op, SlapReply *rs ) } } - if ( bd->be_chk_referrals ) { - BackendDB *be = op->o_bd; - slap_callback cb; - - relay_back_add_cb( &cb, op ); - - op->o_bd = bd; - rc = bd->be_chk_referrals( op, rs ); - op->o_bd = be; - - if ( op->o_callback == &cb ) { - op->o_callback = op->o_callback->sc_next; - } - } - - return rc; - + return relay_back_op( op, rs, bd, bd->be_chk_referrals, 0 ); } int relay_back_operational( Operation *op, SlapReply *rs ) { BackendDB *bd; - int rc = 1; - bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 0 ); + bd = relay_back_select_backend( op, rs, + ( LDAP_SUCCESS | RB_ERR ) ); /* FIXME: this test only works if there are no overlays, so * it is nearly useless; if made stricter, no nested back-relays * can be instantiated... too bad. */ @@ -601,23 +446,7 @@ relay_back_operational( Operation *op, SlapReply *rs ) return 0; } - if ( bd->be_operational ) { - BackendDB *be = op->o_bd; - slap_callback cb; - - relay_back_add_cb( &cb, op ); - - op->o_bd = bd; - rc = bd->be_operational( op, rs ); - op->o_bd = be; - - if ( op->o_callback == &cb ) { - op->o_callback = op->o_callback->sc_next; - } - } - - return rc; - + return relay_back_op( op, rs, bd, bd->be_operational, 0 ); } int @@ -627,7 +456,8 @@ relay_back_has_subordinates( Operation *op, Entry *e, int *hasSubs ) BackendDB *bd; int rc = 1; - bd = relay_back_select_backend( op, &rs, LDAP_SUCCESS, 0 ); + bd = relay_back_select_backend( op, &rs, + ( LDAP_SUCCESS | RB_ERR ) ); /* FIXME: this test only works if there are no overlays, so * it is nearly useless; if made stricter, no nested back-relays * can be instantiated... too bad. */ -- 2.39.5