mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-25 17:19:43 -05:00
Fix a race on bind response processing.
During response processing, an upstream connection could be marked ready after a different bind had already been allocated to it, thus allowing two binds to be in progress on the same connection.
This commit is contained in:
parent
485a169758
commit
9bd90a741c
3 changed files with 33 additions and 17 deletions
|
|
@ -374,8 +374,9 @@ request_bind( LloadConnection *client, LloadOperation *op )
|
|||
if ( ber == NULL && (ber = ber_alloc()) == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "request_bind: "
|
||||
"ber_alloc failed\n" );
|
||||
ldap_pvt_thread_mutex_unlock( &upstream->c_io_mutex );
|
||||
CONNECTION_LOCK_DECREF(upstream);
|
||||
ldap_pvt_thread_mutex_unlock( &upstream->c_io_mutex );
|
||||
upstream->c_state = LLOAD_C_READY;
|
||||
if ( !BER_BVISNULL( &upstream->c_sasl_bind_mech ) ) {
|
||||
ber_memfree( upstream->c_sasl_bind_mech.bv_val );
|
||||
BER_BVZERO( &upstream->c_sasl_bind_mech );
|
||||
|
|
@ -605,7 +606,28 @@ handle_bind_response(
|
|||
op->o_client_msgid, op->o_client_connid, result );
|
||||
|
||||
CONNECTION_LOCK(upstream);
|
||||
if ( result != LDAP_SASL_BIND_IN_PROGRESS ) {
|
||||
if ( !tavl_find( upstream->c_ops, op, operation_upstream_cmp ) ) {
|
||||
/*
|
||||
* operation might not be found because:
|
||||
* - it has timed out (only happens when debugging/hung/...)
|
||||
* a response has been sent for us, we must not send another
|
||||
* - it has been abandoned (new bind, unbind)
|
||||
* no response is expected
|
||||
* - ???
|
||||
*/
|
||||
operation_destroy_from_upstream( op );
|
||||
CONNECTION_UNLOCK(upstream);
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
if ( result == LDAP_SASL_BIND_IN_PROGRESS ) {
|
||||
tavl_delete( &upstream->c_ops, op, operation_upstream_cmp );
|
||||
op->o_upstream_msgid = 0;
|
||||
op->o_upstream_refcnt++;
|
||||
rc = tavl_insert(
|
||||
&upstream->c_ops, op, operation_upstream_cmp, avl_dup_error );
|
||||
assert( rc == LDAP_SUCCESS );
|
||||
} else {
|
||||
int sasl_finished = 0;
|
||||
if ( !BER_BVISNULL( &upstream->c_sasl_bind_mech ) ) {
|
||||
sasl_finished = 1;
|
||||
|
|
@ -620,14 +642,6 @@ handle_bind_response(
|
|||
return finish_sasl_bind( upstream, op, ber );
|
||||
}
|
||||
upstream->c_state = LLOAD_C_READY;
|
||||
} else {
|
||||
if ( tavl_delete( &upstream->c_ops, op, operation_upstream_cmp ) ) {
|
||||
op->o_upstream_msgid = 0;
|
||||
op->o_upstream_refcnt++;
|
||||
rc = tavl_insert( &upstream->c_ops, op, operation_upstream_cmp,
|
||||
avl_dup_error );
|
||||
assert( rc == LDAP_SUCCESS );
|
||||
}
|
||||
}
|
||||
CONNECTION_UNLOCK(upstream);
|
||||
|
||||
|
|
|
|||
|
|
@ -837,6 +837,15 @@ connection_timeout( LloadConnection *upstream, time_t threshold )
|
|||
found_op = tavl_delete( &upstream->c_ops, op, operation_upstream_cmp );
|
||||
assert( op == found_op );
|
||||
|
||||
if ( upstream->c_state == LLOAD_C_BINDING ) {
|
||||
assert( op->o_tag == LDAP_REQ_BIND && upstream->c_ops == NULL );
|
||||
upstream->c_state = LLOAD_C_READY;
|
||||
if ( !BER_BVISNULL( &upstream->c_sasl_bind_mech ) ) {
|
||||
ber_memfree( upstream->c_sasl_bind_mech.bv_val );
|
||||
BER_BVZERO( &upstream->c_sasl_bind_mech );
|
||||
}
|
||||
}
|
||||
|
||||
rc = tavl_insert( &ops, op, operation_upstream_cmp, avl_dup_error );
|
||||
assert( rc == LDAP_SUCCESS );
|
||||
|
||||
|
|
|
|||
|
|
@ -257,13 +257,6 @@ handle_one_response( LloadConnection *c )
|
|||
CONNECTION_LOCK_DECREF(c);
|
||||
op->o_upstream_refcnt--;
|
||||
if ( !client || !op->o_upstream_refcnt ) {
|
||||
if ( c->c_state == LLOAD_C_BINDING ) {
|
||||
c->c_state = LLOAD_C_READY;
|
||||
if ( !BER_BVISNULL( &c->c_sasl_bind_mech ) ) {
|
||||
ber_memfree( c->c_sasl_bind_mech.bv_val );
|
||||
BER_BVZERO( &c->c_sasl_bind_mech );
|
||||
}
|
||||
}
|
||||
operation_destroy_from_upstream( op );
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in a new issue