Full_Name: Vernon Smith Version: 2.4.47 OS: Linux, Solaris URL: ftp://ftp.openldap.org/incoming/ Submission from: (NULL) (2601:40d:4300:679a:d18c:3060:e826:d35c)
I am using libldap library built with -DLDAP_USE_NON_BLOCKING_TLS and configured for Async connection mode. I test making connections using the library to servers that are hung to verify that my application will not hang in those cases. I have found 3 issues. The first is that the ldap_pvt_connect() clears non-blocking socket setup after the connection is made even when Async mode was configured. So here is my patch for that. diff --git a/libraries/libldap/os-ip.c b/libraries/libldap/os-ip.c index a823cc6..d7927e5 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 ); }
The second issue is that the tlso_session_connect() routine does not correctly handle the return code from SSL_connect(), it just returns it to the caller. For LDAP_USE_NON_BLOCKING_TLS, the return code must be checked and an appropriate return used. Here is my patch. diff --git a/libraries/libldap/tls_o.c b/libraries/libldap/tls_o.c index e95a448..7a31b5e 100644 --- a/libraries/libldap/tls_o.c +++ b/libraries/libldap/tls_o.c @@ -531,7 +531,23 @@ 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 + int sslerr = SSL_get_error(s, rc+1); + int sockerr = sock_errno(); + + if ( rc < 0 ) { + 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 */ + + return rc; }
static int
The third issue is that ldap_int_tls_start() compiled with -DLDAP_USE_NON_BLOCKING_TLS Plays with the socket non-blocking setting even if Async mode is configured. Here is mt patch to only play with the socket setting if not in Async mode. diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c index d9b2d27..69b749c 100644 --- a/libraries/libldap/tls2.c +++ b/libraries/libldap/tls2.c @@ -1075,8 +1075,11 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv ) /* * Use non-blocking io during SSL Handshake when a timeout is configured */ + int 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 ) { + 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; @@ -1110,8 +1113,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 in async mode */ + 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; @@ -1159,7 +1164,9 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv ) } } if ( ld->ld_options.ldo_tm_net.tv_sec >= 0 ) { - ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_NONBLOCK, NULL ); + if ( ! async ) { + ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_NONBLOCK, NULL ); + } } #endif /* LDAP_USE_NON_BLOCKING_TLS */
Thanks, Vern