From b6b3f35aac31c9721ba5828c95b7e3dc672a319f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Kuzn=C3=ADk?= Date: Fri, 14 Apr 2017 09:36:42 +0100 Subject: [PATCH] Fix proxyauthz handling --- servers/lloadd/bind.c | 111 +++++++++++++++++++++++-------------- servers/lloadd/operation.c | 35 +++++++----- servers/lloadd/upstream.c | 9 ++- 3 files changed, 95 insertions(+), 60 deletions(-) diff --git a/servers/lloadd/bind.c b/servers/lloadd/bind.c index a0359ab132..bcdb3e1119 100644 --- a/servers/lloadd/bind.c +++ b/servers/lloadd/bind.c @@ -24,22 +24,25 @@ #include "lutil.h" #include "slap.h" +/* + * We hold op->o_upstream->c_io_mutex on entering the function. + */ static int request_bind( Operation *op ) { - Connection *c = op->o_upstream; + Connection *client = op->o_client, *upstream = op->o_upstream; BerElement *ber, *copy = NULL; BerValue binddn; ber_tag_t tag; ber_int_t version; - ber = c->c_pendingber; + ber = upstream->c_pendingber; if ( ber == NULL && (ber = ber_alloc()) == NULL ) { Debug( LDAP_DEBUG_ANY, "request_bind: " "ber_alloc failed\n" ); goto fail; } - c->c_pendingber = ber; + upstream->c_pendingber = ber; if ( (copy = ber_alloc()) == NULL ) { goto fail; @@ -50,7 +53,7 @@ request_bind( Operation *op ) if ( tag == LBER_ERROR ) { goto fail; } else if ( version != LDAP_VERSION3 ) { - /* TODO: result code and message */ + ldap_pvt_thread_mutex_unlock( &upstream->c_io_mutex ); operation_send_reject( op, LDAP_PROTOCOL_ERROR, "LDAP version unsupported" ); ber_free( copy, 0 ); @@ -62,55 +65,61 @@ request_bind( Operation *op ) goto fail; } - ldap_pvt_thread_mutex_lock( &c->c_mutex ); - if ( !BER_BVISNULL( &c->c_auth ) ) { - ber_memfree( c->c_auth.bv_val ); + ldap_pvt_thread_mutex_lock( &client->c_mutex ); + if ( !BER_BVISNULL( &client->c_auth ) ) { + ch_free( client->c_auth.bv_val ); } if ( !BER_BVISEMPTY( &binddn ) ) { char *ptr; - c->c_auth.bv_len = STRLENOF("dn:") + binddn.bv_len; - c->c_auth.bv_val = ch_malloc( c->c_auth.bv_len + 1 ); + client->c_auth.bv_len = STRLENOF("dn:") + binddn.bv_len; + client->c_auth.bv_val = ch_malloc( client->c_auth.bv_len + 1 ); - ptr = lutil_strcopy( c->c_auth.bv_val, "dn:" ); + ptr = lutil_strcopy( client->c_auth.bv_val, "dn:" ); ptr = lutil_strncopy( ptr, binddn.bv_val, binddn.bv_len ); *ptr = '\0'; } else { - BER_BVZERO( &c->c_auth ); + BER_BVZERO( &client->c_auth ); } + ldap_pvt_thread_mutex_unlock( &client->c_mutex ); - op->o_upstream_msgid = c->c_next_msgid++; + ldap_pvt_thread_mutex_lock( &upstream->c_mutex ); + op->o_upstream_msgid = upstream->c_next_msgid++; ber_printf( ber, "t{titOtO}", LDAP_TAG_MESSAGE, LDAP_TAG_MSGID, op->o_upstream_msgid, LDAP_REQ_BIND, &op->o_request, LDAP_TAG_CONTROLS, BER_BV_OPTIONAL( &op->o_ctrls ) ); - if ( tavl_insert( &c->c_ops, op, operation_upstream_cmp, avl_dup_error ) ) { + if ( tavl_insert( &upstream->c_ops, op, operation_upstream_cmp, + avl_dup_error ) ) { assert(0); } - ldap_pvt_thread_mutex_unlock( &c->c_mutex ); + ldap_pvt_thread_mutex_unlock( &upstream->c_mutex ); - ldap_pvt_thread_mutex_unlock( &c->c_io_mutex ); + ldap_pvt_thread_mutex_unlock( &upstream->c_io_mutex ); ber_free( copy, 0 ); - upstream_write_cb( -1, 0, c ); + upstream_write_cb( -1, 0, upstream ); return 0; fail: if ( copy ) { ber_free( copy, 0 ); } - ldap_pvt_thread_mutex_unlock( &c->c_io_mutex ); + ldap_pvt_thread_mutex_unlock( &upstream->c_io_mutex ); ldap_pvt_thread_mutex_lock( &op->o_client->c_mutex ); client_destroy( op->o_client ); return 1; } +/* + * We hold op->o_upstream->c_io_mutex on entering the function. + */ static int request_bind_as_vc( Operation *op ) { - Connection *c = op->o_upstream; + Connection *client = op->o_client, *upstream = op->o_upstream; BerElement *ber, *request, *copy = NULL; BerValue binddn, auth, mech; ber_int_t version; @@ -137,79 +146,87 @@ request_bind_as_vc( Operation *op ) goto fail; } - ber = c->c_pendingber; + ber = upstream->c_pendingber; if ( ber == NULL && (ber = ber_alloc()) == NULL ) { Debug( LDAP_DEBUG_ANY, "request_bind_as_vc: " "ber_alloc failed\n" ); goto fail; } - c->c_pendingber = ber; + upstream->c_pendingber = ber; - op->o_upstream_msgid = c->c_next_msgid++; + op->o_upstream_msgid = upstream->c_next_msgid++; - ldap_pvt_thread_mutex_lock( &c->c_mutex ); + ldap_pvt_thread_mutex_lock( &upstream->c_mutex ); ber_printf( ber, "t{tit{tst{{tOOtOtO}}}}", LDAP_TAG_MESSAGE, LDAP_TAG_MSGID, op->o_upstream_msgid, LDAP_REQ_EXTENDED, LDAP_TAG_EXOP_REQ_OID, LDAP_EXOP_VERIFY_CREDENTIALS, LDAP_TAG_EXOP_REQ_VALUE, - LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE, BER_BV_OPTIONAL( &c->c_vc_cookie ), + LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE, BER_BV_OPTIONAL( &upstream->c_vc_cookie ), &binddn, tag, &auth, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS, BER_BV_OPTIONAL( &op->o_ctrls ) ); + ldap_pvt_thread_mutex_unlock( &upstream->c_mutex ); tag = ber_peek_tag( copy, &len ); switch ( tag ) { case LDAP_AUTH_SASL: ber_get_stringbv( copy, &mech, LBER_BV_NOTERM ); - if ( ber_bvcmp( &mech, &c->c_sasl_bind_mech ) ) { - ber_memfree( c->c_sasl_bind_mech.bv_val ); - ber_dupbv( &c->c_sasl_bind_mech, &mech ); + + ldap_pvt_thread_mutex_lock( &client->c_mutex ); + if ( ber_bvcmp( &mech, &client->c_sasl_bind_mech ) ) { + ber_memfree( client->c_sasl_bind_mech.bv_val ); + ber_dupbv( &client->c_sasl_bind_mech, &mech ); } + ldap_pvt_thread_mutex_unlock( &client->c_mutex ); /* TODO: extract authzdn from the message */ break; case LDAP_AUTH_SIMPLE: - if ( !BER_BVISNULL( &c->c_auth ) ) { - ber_memfree( c->c_auth.bv_val ); + ldap_pvt_thread_mutex_lock( &client->c_mutex ); + if ( !BER_BVISNULL( &client->c_auth ) ) { + ch_free( client->c_auth.bv_val ); } if ( !BER_BVISEMPTY( &binddn ) ) { char *ptr; - c->c_auth.bv_len = STRLENOF("dn:") + binddn.bv_len; - c->c_auth.bv_val = ch_malloc( c->c_auth.bv_len + 1 ); + client->c_auth.bv_len = STRLENOF("dn:") + binddn.bv_len; + client->c_auth.bv_val = ch_malloc( client->c_auth.bv_len + 1 ); - ptr = lutil_strcopy( c->c_auth.bv_val, "dn:" ); + ptr = lutil_strcopy( client->c_auth.bv_val, "dn:" ); ptr = lutil_strncopy( ptr, binddn.bv_val, binddn.bv_len ); *ptr = '\0'; } else { - BER_BVZERO( &c->c_auth ); + BER_BVZERO( &client->c_auth ); } - if ( !BER_BVISNULL( &c->c_sasl_bind_mech ) ) { - ber_memfree( c->c_sasl_bind_mech.bv_val ); - BER_BVZERO( &c->c_sasl_bind_mech ); + if ( !BER_BVISNULL( &client->c_sasl_bind_mech ) ) { + ber_memfree( client->c_sasl_bind_mech.bv_val ); + BER_BVZERO( &client->c_sasl_bind_mech ); } + ldap_pvt_thread_mutex_unlock( &client->c_mutex ); break; default: - ldap_pvt_thread_mutex_unlock( &c->c_mutex ); goto fail; } - if ( tavl_insert( &c->c_ops, op, operation_upstream_cmp, avl_dup_error ) ) { + + ldap_pvt_thread_mutex_lock( &upstream->c_mutex ); + if ( tavl_insert( &upstream->c_ops, op, operation_upstream_cmp, + avl_dup_error ) ) { assert(0); } - ldap_pvt_thread_mutex_unlock( &c->c_mutex ); + ldap_pvt_thread_mutex_unlock( &upstream->c_mutex ); - ldap_pvt_thread_mutex_unlock( &c->c_io_mutex ); + ldap_pvt_thread_mutex_unlock( &upstream->c_io_mutex ); ber_free( copy, 0 ); - upstream_write_cb( -1, 0, c ); + upstream_write_cb( -1, 0, upstream ); return 0; fail: if ( copy ) { ber_free( copy, 0 ); } - ldap_pvt_thread_mutex_unlock( &c->c_io_mutex ); - ldap_pvt_thread_mutex_lock( &op->o_client->c_mutex ); - client_destroy( op->o_client ); + ldap_pvt_thread_mutex_unlock( &upstream->c_io_mutex ); + ldap_pvt_thread_mutex_lock( &client->c_mutex ); + client_destroy( client ); return 1; } @@ -229,6 +246,14 @@ client_reset( void *ctx, void *arg ) c->c_state = SLAP_C_BINDING; destroy = 0; } + if ( !BER_BVISNULL( &c->c_auth ) ) { + ch_free( c->c_auth.bv_val ); + BER_BVZERO( &c->c_auth ); + } + if ( !BER_BVISNULL( &c->c_sasl_bind_mech ) ) { + ch_free( c->c_sasl_bind_mech.bv_val ); + BER_BVZERO( &c->c_sasl_bind_mech ); + } ldap_pvt_thread_mutex_unlock( &c->c_mutex ); tavl_delete( &root, op, operation_client_cmp ); diff --git a/servers/lloadd/operation.c b/servers/lloadd/operation.c index d2083442f2..e8cc3a0a9c 100644 --- a/servers/lloadd/operation.c +++ b/servers/lloadd/operation.c @@ -276,38 +276,42 @@ request_process( void *ctx, void *arg ) { Operation *op = arg; BerElement *output; - Connection *c; + Connection *client = op->o_client, *upstream; ber_int_t msgid; int rc; - c = backend_select( op ); - if ( !c ) { + upstream = backend_select( op ); + if ( !upstream ) { Debug( LDAP_DEBUG_STATS, "request_process: " "no available connection found\n" ); goto fail; } - op->o_upstream = c; + op->o_upstream = upstream; - output = c->c_pendingber; + output = upstream->c_pendingber; if ( output == NULL && (output = ber_alloc()) == NULL ) { goto fail; } - c->c_pendingber = output; + upstream->c_pendingber = output; - ldap_pvt_thread_mutex_lock( &c->c_mutex ); - op->o_upstream_msgid = msgid = c->c_next_msgid++; - rc = tavl_insert( &c->c_ops, op, operation_upstream_cmp, avl_dup_error ); + ldap_pvt_thread_mutex_unlock( &upstream->c_mutex ); + op->o_upstream_msgid = msgid = upstream->c_next_msgid++; + rc = tavl_insert( + &upstream->c_ops, op, operation_upstream_cmp, avl_dup_error ); + ldap_pvt_thread_mutex_unlock( &upstream->c_mutex ); assert( rc == LDAP_SUCCESS ); if ( lload_features & LLOAD_FEATURE_PROXYAUTHZ ) { + ldap_pvt_thread_mutex_lock( &client->c_mutex ); Debug( LDAP_DEBUG_TRACE, "request_process: " "proxying identity %s to upstream\n", - c->c_auth.bv_val ); + client->c_auth.bv_val ); ber_printf( output, "t{titOt{{sbO}" /* "}}" */, LDAP_TAG_MESSAGE, LDAP_TAG_MSGID, msgid, op->o_tag, &op->o_request, LDAP_TAG_CONTROLS, - LDAP_CONTROL_PROXY_AUTHZ, 1, &c->c_auth ); + LDAP_CONTROL_PROXY_AUTHZ, 1, &client->c_auth ); + ldap_pvt_thread_mutex_unlock( &client->c_mutex ); if ( !BER_BVISNULL( &op->o_ctrls ) ) { BerElement *control_ber = ber_alloc(); @@ -329,13 +333,16 @@ request_process( void *ctx, void *arg ) op->o_tag, &op->o_request, LDAP_TAG_CONTROLS, BER_BV_OPTIONAL( &op->o_ctrls ) ); } - ldap_pvt_thread_mutex_unlock( &c->c_mutex ); - ldap_pvt_thread_mutex_unlock( &c->c_io_mutex ); + ldap_pvt_thread_mutex_unlock( &upstream->c_io_mutex ); - upstream_write_cb( -1, 0, c ); + upstream_write_cb( -1, 0, upstream ); return NULL; + fail: + if ( upstream ) { + ldap_pvt_thread_mutex_unlock( &upstream->c_io_mutex ); + } operation_send_reject( op, LDAP_OTHER, "internal error" ); return NULL; } diff --git a/servers/lloadd/upstream.c b/servers/lloadd/upstream.c index e5bfd657fb..611801e081 100644 --- a/servers/lloadd/upstream.c +++ b/servers/lloadd/upstream.c @@ -155,11 +155,14 @@ handle_vc_bind_response( Operation *op, BerElement *ber ) tag = ber_peek_tag( ber, &len ); if ( result == LDAP_PROTOCOL_ERROR ) { - Backend *b = op->o_upstream->c_private; - ldap_pvt_thread_mutex_lock( &op->o_upstream->c_mutex ); + Connection *upstream = op->o_upstream; + Backend *b; + + ldap_pvt_thread_mutex_lock( &upstream->c_mutex ); + b = (Backend *)upstream->c_private; Debug( LDAP_DEBUG_ANY, "VC extended operation not supported on backend %s\n", b->b_bindconf.sb_uri.bv_val ); - ldap_pvt_thread_mutex_unlock( &op->o_upstream->c_mutex ); + ldap_pvt_thread_mutex_unlock( &upstream->c_mutex ); } ldap_pvt_thread_mutex_lock( &c->c_mutex );