From d5f65267bd1b2108e06e088e2f920345ae4b5a04 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Tue, 4 Jan 2011 16:19:51 +0000 Subject: [PATCH] also works for multi-stage binds (ITS#6771; needs ITS#6773 patch) --- contrib/slapd-modules/authzid/authzid.c | 245 +++++++++++++++++------- 1 file changed, 178 insertions(+), 67 deletions(-) diff --git a/contrib/slapd-modules/authzid/authzid.c b/contrib/slapd-modules/authzid/authzid.c index ef9d6d87a6..2a028ad0d6 100644 --- a/contrib/slapd-modules/authzid/authzid.c +++ b/contrib/slapd-modules/authzid/authzid.c @@ -28,72 +28,131 @@ #include "lutil.h" #include "ac/string.h" +typedef struct ConnExtraAuthzID { + ConnExtra ce; + char authzid_flag; +} ConnExtraAuthzID; + static int authzid_cid; +static slap_overinst authzid; + +static ConnExtraAuthzID * +authzid_extra_find( Connection *c ) +{ + ConnExtra *cex; + + LDAP_SLIST_FOREACH( cex, &c->c_extra, ce_next ) { + if ( cex->ce_key == (void *)&authzid_cid ) + break; + } + + return (ConnExtraAuthzID *)cex; +} + +static ConnExtraAuthzID * +authzid_extra_insert( Connection *c ) +{ + ConnExtraAuthzID *cex; + + cex = SLAP_CALLOC( 1, sizeof( ConnExtraAuthzID ) ); + cex->ce.ce_key = (void *)&authzid_cid; + + LDAP_SLIST_INSERT_HEAD( &c->c_extra, &cex->ce, ce_next ); + + return cex; +} + +static int +authzid_extra_remove( Connection *c ) +{ + ConnExtra *cex; + int found = 0; + + cex = (ConnExtra *)authzid_extra_find( c ); + if ( cex ) { + found = 1; + LDAP_SLIST_REMOVE( &c->c_extra, cex, ConnExtra, ce_next ); + SLAP_FREE( cex ); + } + + return found; +} static int authzid_response( Operation *op, SlapReply *rs ) { - if ( rs->sr_tag == LDAP_RES_BIND ) { - LDAPControl **ctrls; - ber_len_t len = 0; - int n = 0; + ConnExtraAuthzID *cex; + LDAPControl **ctrls; + struct berval edn = BER_BVNULL; + ber_len_t len = 0; + int n = 0; + + assert( rs->sr_tag = LDAP_RES_BIND ); + + cex = authzid_extra_find( op->o_conn ); + if ( rs->sr_err == LDAP_SASL_BIND_IN_PROGRESS ) { + if ( !cex ) { + cex = authzid_extra_insert( op->o_conn ); + cex->authzid_flag = op->o_ctrlflag[ authzid_cid ]; + } - /* TEMPORARY! */ - if ( rs->sr_err == LDAP_SASL_BIND_IN_PROGRESS ) { - if ( op->o_ctrlflag[ authzid_cid ] == SLAP_CONTROL_CRITICAL ) { - return rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; - } + return SLAP_CB_CONTINUE; - op->o_ctrlflag[ authzid_cid ] = SLAP_CONTROL_IGNORED; + } - return SLAP_CB_CONTINUE; - } - /* end of TEMPORARY! */ + if ( cex ) { + authzid_extra_remove( op->o_conn ); + } - if ( rs->sr_err != LDAP_SUCCESS ) { - return SLAP_CB_CONTINUE; - } + if ( rs->sr_err != LDAP_SUCCESS ) { + return SLAP_CB_CONTINUE; + } - if ( !BER_BVISEMPTY( &op->o_conn->c_dn ) ) { - len = STRLENOF("dn:") + op->o_conn->c_dn.bv_len; - } + if ( !BER_BVISEMPTY( &op->orb_edn ) ) { + edn = op->orb_edn; + } else if ( !BER_BVISEMPTY( &op->o_conn->c_dn ) ) { + edn = op->o_conn->c_dn; + } - /* save original controls in sc_private; - * will be restored by sc_cleanup - */ - if ( rs->sr_ctrls != NULL ) { - op->o_callback->sc_private = rs->sr_ctrls; - for ( ; rs->sr_ctrls[n] != NULL; n++ ) - ; - } + if ( !BER_BVISEMPTY( &edn ) ) { + len = STRLENOF("dn:") + edn.bv_len; + } - ctrls = op->o_tmpalloc( sizeof( LDAPControl * )*( n + 2 ), op->o_tmpmemctx ); - n = 0; - if ( rs->sr_ctrls ) { - for ( ; rs->sr_ctrls[n] != NULL; n++ ) { - ctrls[n] = rs->sr_ctrls[n]; - } - } + /* save original controls in sc_private; + * will be restored by sc_cleanup + */ + if ( rs->sr_ctrls != NULL ) { + op->o_callback->sc_private = rs->sr_ctrls; + for ( ; rs->sr_ctrls[n] != NULL; n++ ) + ; + } - /* anonymous: "", otherwise "dn:" */ - ctrls[n] = op->o_tmpalloc( sizeof( LDAPControl ) + len + 1, op->o_tmpmemctx ); - ctrls[n]->ldctl_oid = LDAP_CONTROL_AUTHZID_RESPONSE; - ctrls[n]->ldctl_iscritical = 0; - ctrls[n]->ldctl_value.bv_len = len; - ctrls[n]->ldctl_value.bv_val = (char *)&ctrls[n][1]; - if ( len ) { - char *ptr; - - ptr = lutil_strcopy( ctrls[n]->ldctl_value.bv_val, "dn:" ); - ptr = lutil_strncopy( ptr, op->o_conn->c_dn.bv_val, op->o_conn->c_dn.bv_len ); + ctrls = op->o_tmpalloc( sizeof( LDAPControl * )*( n + 2 ), op->o_tmpmemctx ); + n = 0; + if ( rs->sr_ctrls ) { + for ( ; rs->sr_ctrls[n] != NULL; n++ ) { + ctrls[n] = rs->sr_ctrls[n]; } - ctrls[n]->ldctl_value.bv_val[len] = '\0'; - ctrls[n + 1] = NULL; + } - rs->sr_ctrls = ctrls; + /* anonymous: "", otherwise "dn:" */ + ctrls[n] = op->o_tmpalloc( sizeof( LDAPControl ) + len + 1, op->o_tmpmemctx ); + ctrls[n]->ldctl_oid = LDAP_CONTROL_AUTHZID_RESPONSE; + ctrls[n]->ldctl_iscritical = 0; + ctrls[n]->ldctl_value.bv_len = len; + ctrls[n]->ldctl_value.bv_val = (char *)&ctrls[n][1]; + if ( len ) { + char *ptr; + + ptr = lutil_strcopy( ctrls[n]->ldctl_value.bv_val, "dn:" ); + ptr = lutil_strncopy( ptr, edn.bv_val, edn.bv_len ); } + ctrls[n]->ldctl_value.bv_val[len] = '\0'; + ctrls[n + 1] = NULL; + + rs->sr_ctrls = ctrls; return SLAP_CB_CONTINUE; } @@ -125,14 +184,38 @@ authzid_cleanup( return SLAP_CB_CONTINUE; } +static int +authzid_op_bind( + Operation *op, + SlapReply *rs ) +{ + slap_callback *sc; + + if ( op->o_ctrlflag[ authzid_cid ] <= SLAP_CONTROL_IGNORED ) { + ConnExtraAuthzID *cex = authzid_extra_find( op->o_conn ); + if ( cex ) { + op->o_ctrlflag[ authzid_cid ] = cex->authzid_flag; + } + } + + if ( op->o_ctrlflag[ authzid_cid ] > SLAP_CONTROL_IGNORED ) { + sc = op->o_callback; + op->o_callback = op->o_tmpalloc( sizeof( slap_callback ), op->o_tmpmemctx ); + op->o_callback->sc_response = authzid_response; + op->o_callback->sc_cleanup = authzid_cleanup; + op->o_callback->sc_private = NULL; + op->o_callback->sc_next = sc; + } + + return SLAP_CB_CONTINUE; +} + static int parse_authzid_ctrl( Operation *op, SlapReply *rs, LDAPControl *ctrl ) { - slap_callback *sc; - if ( op->o_ctrlflag[ authzid_cid ] != SLAP_CONTROL_NONE ) { rs->sr_text = "authzid control specified multiple times"; return LDAP_PROTOCOL_ERROR; @@ -143,34 +226,62 @@ parse_authzid_ctrl( return LDAP_PROTOCOL_ERROR; } + /* drop ongoing requests */ + (void)authzid_extra_remove( op->o_conn ); + op->o_ctrlflag[ authzid_cid ] = ctrl->ldctl_iscritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; - sc = op->o_callback; - op->o_callback = op->o_tmpalloc( sizeof( slap_callback ), op->o_tmpmemctx ); - op->o_callback->sc_response = authzid_response; - op->o_callback->sc_cleanup = authzid_cleanup; - op->o_callback->sc_private = NULL; - op->o_callback->sc_next = sc; + return LDAP_SUCCESS; +} + +static int authzid_cnt; + +static int +authzid_db_init( BackendDB *be, ConfigReply *cr) +{ + if ( authzid_cnt++ == 0 ) { + int rc; + + rc = register_supported_control( LDAP_CONTROL_AUTHZID_REQUEST, + SLAP_CTRL_GLOBAL|SLAP_CTRL_BIND|SLAP_CTRL_HIDE, NULL, + parse_authzid_ctrl, &authzid_cid ); + if ( rc != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_ANY, + "authzid_initialize: Failed to register control '%s' (%d)\n", + LDAP_CONTROL_AUTHZID_REQUEST, rc, 0 ); + return rc; + } + } return LDAP_SUCCESS; } static int -authzid_initialize( void ) +authzid_db_destroy( BackendDB *be, ConfigReply *cr ) { - int rc; + assert( authzid_cnt > 0 ); - rc = register_supported_control( LDAP_CONTROL_AUTHZID_REQUEST, - SLAP_CTRL_GLOBAL|SLAP_CTRL_BIND|SLAP_CTRL_HIDE, NULL, - parse_authzid_ctrl, &authzid_cid ); - if ( rc != LDAP_SUCCESS ) { - Debug( LDAP_DEBUG_ANY, - "authzid_initialize: failed to register control %s (%d)\n", - LDAP_CONTROL_AUTHZID_REQUEST, rc, 0 ); - return rc; +#ifdef SLAP_CONFIG_DELETE + overlay_unregister_control( be, LDAP_CONTROL_AUTHZID_REQUEST ); +#endif /* SLAP_CONFIG_DELETE */ + + if ( --authzid_cnt == 0 ) { + unregister_supported_control( LDAP_CONTROL_AUTHZID_REQUEST ); } - return rc; + return 0; +} + +static int +authzid_initialize( void ) +{ + authzid.on_bi.bi_type = "authzid"; + + authzid.on_bi.bi_db_init = authzid_db_init; + authzid.on_bi.bi_db_destroy = authzid_db_destroy; + authzid.on_bi.bi_op_bind = authzid_op_bind; + + return overlay_register( &authzid ); } int -- 2.39.5