From d143f7a2dc82fb66e7741b93a1ae9e874ce2ac46 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Kuzn=C3=ADk?= <ondra@mistotebe.net>
Date: Mon, 21 Oct 2024 11:50:11 +0100
Subject: [PATCH] ITS#8047 Fix TLS connection timeout handling

The test for async in ldap_int_tls_start was inverted, we already
support calling ldap_int_tls_connect repeatedly. And so long as
LBER_SB_OPT_NEEDS_* are managed correctly, the application should be
able to do the right thing.

Might require a new result code rather than reporposing
LDAP_X_CONNECTING for this.

Reference:https://git.openldap.org/openldap/openldap/-/commit/d143f7a2dc82fb66e7741b93a1ae9e874ce2ac46
Conflict:context conflict by https://git.openldap.org/openldap/openldap/-/commit/139944ac1e5fcf74e903e1e3d887fb8498c2fd1e
---
 libraries/libldap/ldap-int.h |  1 +
 libraries/libldap/tls2.c     | 18 +++++++++++++++++-
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h
index 2dae6ef..6827ec4 100644
--- a/libraries/libldap/ldap-int.h
+++ b/libraries/libldap/ldap-int.h
@@ -368,6 +368,7 @@ typedef struct ldap_conn {
 #define LDAP_CONNST_NEEDSOCKET		1
 #define LDAP_CONNST_CONNECTING		2
 #define LDAP_CONNST_CONNECTED		3
+#define LDAP_CONNST_TLS_INPROGRESS	4
 	LDAPURLDesc		*lconn_server;
 	BerElement		*lconn_ber;	/* ber receiving on this conn. */
 
diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c
index 1fb6cff..3d3b5fd 100644
--- a/libraries/libldap/tls2.c
+++ b/libraries/libldap/tls2.c
@@ -383,6 +383,7 @@ ldap_int_tls_connect( LDAP *ld, LDAPConn *conn, const char *host )
 		if ( lo && lo->ldo_tls_connect_cb && lo->ldo_tls_connect_cb !=
 			ld->ld_options.ldo_tls_connect_cb )
 			lo->ldo_tls_connect_cb( ld, ssl, ctx, lo->ldo_tls_connect_arg );
+		conn->lconn_status = LDAP_CONNST_TLS_INPROGRESS;
 	}
 
 	/* pass hostname for SNI, but only if it's an actual name
@@ -441,9 +442,11 @@ ldap_int_tls_connect( LDAP *ld, LDAPConn *conn, const char *host )
 		ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug,
 			LBER_SBIOD_LEVEL_TRANSPORT );
 #endif
+		conn->lconn_status = LDAP_CONNST_CONNECTED;
 		return -1;
 	}
 
+	conn->lconn_status = LDAP_CONNST_CONNECTED;
 	return 0;
 }
 
@@ -516,8 +519,9 @@ int
 ldap_tls_inplace( LDAP *ld )
 {
 	Sockbuf		*sb = NULL;
+	LDAPConn	*lc = ld->ld_defconn;
 
-	if ( ld->ld_defconn && ld->ld_defconn->lconn_sb ) {
+	if ( lc && lc->lconn_sb ) {
 		sb = ld->ld_defconn->lconn_sb;
 
 	} else if ( ld->ld_sb ) {
@@ -527,6 +531,10 @@ ldap_tls_inplace( LDAP *ld )
 		return 0;
 	}
 
+	if ( lc && lc->lconn_status == LDAP_CONNST_TLS_INPROGRESS ) {
+		return 0;
+	}
+
 	return ldap_pvt_tls_inplace( sb );
 }
 
@@ -1159,6 +1167,9 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv )
 	  */
 	while ( ret > 0 ) {
 		if ( async ) {
+			ld->ld_errno = LDAP_X_CONNECTING;
+			return (ld->ld_errno);
+		} else {
 			struct timeval curr_time_tv, delta_tv;
 			int wr=0;
 
@@ -1217,6 +1228,11 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv )
 		ret = ldap_int_tls_connect( ld, conn, host );
 	}
 
+	if ( !async && ld->ld_options.ldo_tm_net.tv_sec >= 0 ) {
+		/* Restore original sb status */
+		ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_NONBLOCK, (void*)0 );
+	}
+
 	if ( ret < 0 ) {
 		if ( ld->ld_errno == LDAP_SUCCESS )
 			ld->ld_errno = LDAP_CONNECT_ERROR;
-- 
2.33.0

