mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-24 16:49:39 -05:00
ITS#8650 loop on incomplete TLS handshake
Always retry ldap_int_tls_connect() if it didn't complete, regardless of blocking or non-blocking socket. Code from ITS#7428 was wrong to only retry for async.
This commit is contained in:
parent
c6493c45b5
commit
735e1ab14b
1 changed files with 53 additions and 60 deletions
|
|
@ -1099,78 +1099,71 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv )
|
|||
ld->ld_errno = LDAP_SUCCESS;
|
||||
ret = ldap_int_tls_connect( ld, conn, host );
|
||||
|
||||
/* this mainly only happens for non-blocking io
|
||||
* but can also happen when the handshake is too
|
||||
* big for a single network message.
|
||||
*/
|
||||
while ( ret > 0 ) {
|
||||
#ifdef LDAP_USE_NON_BLOCKING_TLS
|
||||
while ( ret > 0 ) { /* this should only happen for non-blocking io */
|
||||
int wr=0;
|
||||
if ( async ) {
|
||||
struct timeval curr_time_tv, delta_tv;
|
||||
int wr=0;
|
||||
|
||||
if ( sb->sb_trans_needs_read ) {
|
||||
wr=0;
|
||||
} else if ( sb->sb_trans_needs_write ) {
|
||||
wr=1;
|
||||
}
|
||||
Debug1( LDAP_DEBUG_TRACE, "ldap_int_tls_start: ldap_int_tls_connect needs %s\n",
|
||||
wr ? "write": "read" );
|
||||
|
||||
ret = ldap_int_poll( ld, sd, &tv, wr);
|
||||
if ( ret < 0 ) {
|
||||
ld->ld_errno = LDAP_TIMEOUT;
|
||||
break;
|
||||
} else {
|
||||
/* ldap_int_poll called ldap_pvt_ndelay_off if not async */
|
||||
if ( !async ) {
|
||||
ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_NONBLOCK, (void*)1 );
|
||||
if ( sb->sb_trans_needs_read ) {
|
||||
wr=0;
|
||||
} else if ( sb->sb_trans_needs_write ) {
|
||||
wr=1;
|
||||
}
|
||||
ret = ldap_int_tls_connect( ld, conn, host );
|
||||
if ( ret > 0 ) { /* need to call tls_connect once more */
|
||||
struct timeval curr_time_tv, delta_tv;
|
||||
Debug1( LDAP_DEBUG_TRACE, "ldap_int_tls_start: ldap_int_tls_connect needs %s\n",
|
||||
wr ? "write": "read" );
|
||||
|
||||
/* This is mostly copied from result.c:wait4msg(), should
|
||||
* probably be moved into a separate function */
|
||||
/* This is mostly copied from result.c:wait4msg(), should
|
||||
* probably be moved into a separate function */
|
||||
#ifdef HAVE_GETTIMEOFDAY
|
||||
gettimeofday( &curr_time_tv, NULL );
|
||||
gettimeofday( &curr_time_tv, NULL );
|
||||
#else /* ! HAVE_GETTIMEOFDAY */
|
||||
time( &curr_time_tv.tv_sec );
|
||||
curr_time_tv.tv_usec = 0;
|
||||
time( &curr_time_tv.tv_sec );
|
||||
curr_time_tv.tv_usec = 0;
|
||||
#endif /* ! HAVE_GETTIMEOFDAY */
|
||||
|
||||
/* delta = curr - start */
|
||||
delta_tv.tv_sec = curr_time_tv.tv_sec - start_time_tv.tv_sec;
|
||||
delta_tv.tv_usec = curr_time_tv.tv_usec - start_time_tv.tv_usec;
|
||||
if ( delta_tv.tv_usec < 0 ) {
|
||||
delta_tv.tv_sec--;
|
||||
delta_tv.tv_usec += 1000000;
|
||||
}
|
||||
/* delta = curr - start */
|
||||
delta_tv.tv_sec = curr_time_tv.tv_sec - start_time_tv.tv_sec;
|
||||
delta_tv.tv_usec = curr_time_tv.tv_usec - start_time_tv.tv_usec;
|
||||
if ( delta_tv.tv_usec < 0 ) {
|
||||
delta_tv.tv_sec--;
|
||||
delta_tv.tv_usec += 1000000;
|
||||
}
|
||||
|
||||
/* tv0 < delta ? */
|
||||
if ( ( tv0.tv_sec < delta_tv.tv_sec ) ||
|
||||
( ( tv0.tv_sec == delta_tv.tv_sec ) &&
|
||||
( tv0.tv_usec < delta_tv.tv_usec ) ) )
|
||||
{
|
||||
ret = -1;
|
||||
ld->ld_errno = LDAP_TIMEOUT;
|
||||
break;
|
||||
} else {
|
||||
/* timeout -= delta_time */
|
||||
tv0.tv_sec -= delta_tv.tv_sec;
|
||||
tv0.tv_usec -= delta_tv.tv_usec;
|
||||
if ( tv0.tv_usec < 0 ) {
|
||||
tv0.tv_sec--;
|
||||
tv0.tv_usec += 1000000;
|
||||
}
|
||||
start_time_tv.tv_sec = curr_time_tv.tv_sec;
|
||||
start_time_tv.tv_usec = curr_time_tv.tv_usec;
|
||||
}
|
||||
tv = tv0;
|
||||
Debug3( LDAP_DEBUG_TRACE, "ldap_int_tls_start: ld %p %ld s %ld us to go\n",
|
||||
(void *)ld, (long) tv.tv_sec, (long) tv.tv_usec );
|
||||
/* tv0 < delta ? */
|
||||
if ( ( tv0.tv_sec < delta_tv.tv_sec ) ||
|
||||
( ( tv0.tv_sec == delta_tv.tv_sec ) &&
|
||||
( tv0.tv_usec < delta_tv.tv_usec ) ) )
|
||||
{
|
||||
ret = -1;
|
||||
ld->ld_errno = LDAP_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
/* timeout -= delta_time */
|
||||
tv0.tv_sec -= delta_tv.tv_sec;
|
||||
tv0.tv_usec -= delta_tv.tv_usec;
|
||||
if ( tv0.tv_usec < 0 ) {
|
||||
tv0.tv_sec--;
|
||||
tv0.tv_usec += 1000000;
|
||||
}
|
||||
start_time_tv.tv_sec = curr_time_tv.tv_sec;
|
||||
start_time_tv.tv_usec = curr_time_tv.tv_usec;
|
||||
tv = tv0;
|
||||
Debug3( LDAP_DEBUG_TRACE, "ldap_int_tls_start: ld %p %ld s %ld us to go\n",
|
||||
(void *)ld, (long) tv.tv_sec, (long) tv.tv_usec );
|
||||
ret = ldap_int_poll( ld, sd, &tv, wr);
|
||||
if ( ret < 0 ) {
|
||||
ld->ld_errno = LDAP_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Leave it nonblocking if async */
|
||||
if ( !async && ld->ld_options.ldo_tm_net.tv_sec >= 0 ) {
|
||||
ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_NONBLOCK, NULL );
|
||||
}
|
||||
#endif /* LDAP_USE_NON_BLOCKING_TLS */
|
||||
ret = ldap_int_tls_connect( ld, conn, host );
|
||||
}
|
||||
|
||||
if ( ret < 0 ) {
|
||||
if ( ld->ld_errno == LDAP_SUCCESS )
|
||||
|
|
|
|||
Loading…
Reference in a new issue