[Date Prev][Date Next] [Chronological] [Thread] [Top]

(ITS#8980) Async mode and TLS Non-Blocking Issue



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