From: Vernon Smith Date: Tue, 19 Feb 2019 05:57:00 +0000 (+0000) Subject: ITS#8980 fix async connections with non-blocking TLS X-Git-Tag: OPENLDAP_REL_ENG_2_4_48~107 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d4a0a9b3a65bd1ce721d55845d4240942d17538b;p=thirdparty%2Fopenldap.git ITS#8980 fix async connections with non-blocking TLS --- diff --git a/libraries/libldap/os-ip.c b/libraries/libldap/os-ip.c index a823cc6260..cb7b0a3b27 100644 --- a/libraries/libldap/os-ip.c +++ b/libraries/libldap/os-ip.c @@ -443,7 +443,7 @@ ldap_pvt_connect(LDAP *ld, ber_socket_t s, if ( connect(s, sin, addrlen) != AC_SOCKET_ERROR ) { osip_debug(ld, "connect success\n", 0, 0, 0); - if ( opt_tv && ldap_pvt_ndelay_off(ld, s) == -1 ) + if ( !async && opt_tv && ldap_pvt_ndelay_off(ld, s) == -1 ) return ( -1 ); return ( 0 ); } diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c index 96da4d421b..bc93e4d633 100644 --- a/libraries/libldap/tls2.c +++ b/libraries/libldap/tls2.c @@ -826,7 +826,7 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv ) Sockbuf *sb; char *host; void *ssl; - int ret; + int ret, async; #ifdef LDAP_USE_NON_BLOCKING_TLS struct timeval start_time_tv, tv, tv0; ber_socket_t sd = AC_SOCKET_ERROR; @@ -853,8 +853,12 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv ) /* * Use non-blocking io during SSL Handshake when a timeout is configured */ + async = LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_CONNECT_ASYNC ); if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) { - ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_NONBLOCK, (void*)1 ); + if ( !async ) { + /* if async, this has already been set */ + ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_NONBLOCK, (void*)1 ); + } ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, &sd ); tv = ld->ld_options.ldo_tm_net; tv0 = tv; @@ -888,8 +892,10 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv ) ld->ld_errno = LDAP_TIMEOUT; break; } else { - /* ldap_int_poll called ldap_pvt_ndelay_off */ - ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_NONBLOCK, (void*)1 ); + /* 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 ); if ( ret > 0 ) { /* need to call tls_connect once more */ struct timeval curr_time_tv, delta_tv; @@ -936,7 +942,8 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv ) } } } - if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) { + /* 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 */ diff --git a/libraries/libldap/tls_o.c b/libraries/libldap/tls_o.c index 2b0c021a69..b10121d3ae 100644 --- a/libraries/libldap/tls_o.c +++ b/libraries/libldap/tls_o.c @@ -452,7 +452,19 @@ tlso_session_connect( LDAP *ld, tls_session *sess ) tlso_session *s = (tlso_session *)sess; /* Caller expects 0 = success, OpenSSL returns 1 = success */ - return SSL_connect( s ) - 1; + int rc = SSL_connect( s ) - 1; +#ifdef LDAP_USE_NON_BLOCKING_TLS + if ( rc < 0 ) { + int sockerr = sock_errno(); + int sslerr = SSL_get_error( s, rc+1 ); + if ( sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE ) { + rc = 0; + } else if ( sslerr == SSL_ERROR_SYSCALL && + ( sockerr == EAGAIN || sockerr == ENOTCONN )) { + rc = 0; + } + } +#endif /* LDAP_USE_NON_BLOCKING_TLS */ } static int