Commit 7cf7aa31 authored by Howard Chu's avatar Howard Chu Committed by Quanah Gibson-Mount
Browse files

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.
parent c385351a
...@@ -892,78 +892,71 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv ) ...@@ -892,78 +892,71 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv )
ld->ld_errno = LDAP_SUCCESS; ld->ld_errno = LDAP_SUCCESS;
ret = ldap_int_tls_connect( ld, conn, host ); 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 #ifdef LDAP_USE_NON_BLOCKING_TLS
while ( ret > 0 ) { /* this should only happen for non-blocking io */ if ( async ) {
int wr=0; struct timeval curr_time_tv, delta_tv;
int wr=0;
if ( sb->sb_trans_needs_read ) {
wr=0; if ( sb->sb_trans_needs_read ) {
} else if ( sb->sb_trans_needs_write ) { wr=0;
wr=1; } else if ( sb->sb_trans_needs_write ) {
} wr=1;
Debug( LDAP_DEBUG_TRACE, "ldap_int_tls_start: ldap_int_tls_connect needs %s\n",
wr ? "write": "read", 0, 0);
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 );
} }
ret = ldap_int_tls_connect( ld, conn, host ); Debug1( LDAP_DEBUG_TRACE, "ldap_int_tls_start: ldap_int_tls_connect needs %s\n",
if ( ret > 0 ) { /* need to call tls_connect once more */ wr ? "write": "read" );
struct timeval curr_time_tv, delta_tv;
/* This is mostly copied from result.c:wait4msg(), should /* This is mostly copied from result.c:wait4msg(), should
* probably be moved into a separate function */ * probably be moved into a separate function */
#ifdef HAVE_GETTIMEOFDAY #ifdef HAVE_GETTIMEOFDAY
gettimeofday( &curr_time_tv, NULL ); gettimeofday( &curr_time_tv, NULL );
#else /* ! HAVE_GETTIMEOFDAY */ #else /* ! HAVE_GETTIMEOFDAY */
time( &curr_time_tv.tv_sec ); time( &curr_time_tv.tv_sec );
curr_time_tv.tv_usec = 0; curr_time_tv.tv_usec = 0;
#endif /* ! HAVE_GETTIMEOFDAY */ #endif /* ! HAVE_GETTIMEOFDAY */
/* delta = curr - start */ /* delta = curr - start */
delta_tv.tv_sec = curr_time_tv.tv_sec - start_time_tv.tv_sec; 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; delta_tv.tv_usec = curr_time_tv.tv_usec - start_time_tv.tv_usec;
if ( delta_tv.tv_usec < 0 ) { if ( delta_tv.tv_usec < 0 ) {
delta_tv.tv_sec--; delta_tv.tv_sec--;
delta_tv.tv_usec += 1000000; delta_tv.tv_usec += 1000000;
} }
/* tv0 < delta ? */ /* tv0 < delta ? */
if ( ( tv0.tv_sec < delta_tv.tv_sec ) || if ( ( tv0.tv_sec < delta_tv.tv_sec ) ||
( ( tv0.tv_sec == delta_tv.tv_sec ) && ( ( tv0.tv_sec == delta_tv.tv_sec ) &&
( tv0.tv_usec < delta_tv.tv_usec ) ) ) ( tv0.tv_usec < delta_tv.tv_usec ) ) )
{ {
ret = -1; ret = -1;
ld->ld_errno = LDAP_TIMEOUT; ld->ld_errno = LDAP_TIMEOUT;
break; break;
} else { }
/* timeout -= delta_time */ /* timeout -= delta_time */
tv0.tv_sec -= delta_tv.tv_sec; tv0.tv_sec -= delta_tv.tv_sec;
tv0.tv_usec -= delta_tv.tv_usec; tv0.tv_usec -= delta_tv.tv_usec;
if ( tv0.tv_usec < 0 ) { if ( tv0.tv_usec < 0 ) {
tv0.tv_sec--; tv0.tv_sec--;
tv0.tv_usec += 1000000; tv0.tv_usec += 1000000;
} }
start_time_tv.tv_sec = curr_time_tv.tv_sec; start_time_tv.tv_sec = curr_time_tv.tv_sec;
start_time_tv.tv_usec = curr_time_tv.tv_usec; start_time_tv.tv_usec = curr_time_tv.tv_usec;
} tv = tv0;
tv = tv0; Debug3( LDAP_DEBUG_TRACE, "ldap_int_tls_start: ld %p %ld s %ld us to go\n",
Debug( 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 );
(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 */ #endif /* LDAP_USE_NON_BLOCKING_TLS */
ret = ldap_int_tls_connect( ld, conn, host );
}
if ( ret < 0 ) { if ( ret < 0 ) {
if ( ld->ld_errno == LDAP_SUCCESS ) if ( ld->ld_errno == LDAP_SUCCESS )
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment