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

Reply via email to