005aba9
From 19e631e977c4f57905b2380cf79ccaf8e6d99e9d Mon Sep 17 00:00:00 2001
005aba9
From: Howard Chu <hyc@openldap.org>
005aba9
Date: Mon, 27 Apr 2020 03:41:12 +0100
005aba9
Subject: [PATCH 1/4] ITS#9176 Add TLS SNI support to libldap
005aba9
005aba9
Implemented for OpenSSL, GnuTLS just stubbed
005aba9
---
005aba9
 libraries/libldap/ldap-tls.h | 2 +-
005aba9
 libraries/libldap/tls2.c     | 2 +-
005aba9
 libraries/libldap/tls_g.c    | 2 +-
005aba9
 libraries/libldap/tls_o.c    | 8 ++++++--
005aba9
 4 files changed, 9 insertions(+), 5 deletions(-)
005aba9
005aba9
diff --git a/libraries/libldap/ldap-tls.h b/libraries/libldap/ldap-tls.h
005aba9
index c8a27112f1..c149b1867c 100644
005aba9
--- a/libraries/libldap/ldap-tls.h
005aba9
+++ b/libraries/libldap/ldap-tls.h
005aba9
@@ -34,7 +34,7 @@ typedef void (TI_ctx_free)(tls_ctx *ctx);
005aba9
 typedef int (TI_ctx_init)(struct ldapoptions *lo, struct ldaptls *lt, int is_server);
005aba9
 
005aba9
 typedef tls_session *(TI_session_new)(tls_ctx *ctx, int is_server);
005aba9
-typedef int (TI_session_connect)(LDAP *ld, tls_session *s);
005aba9
+typedef int (TI_session_connect)(LDAP *ld, tls_session *s, const char *name_in);
005aba9
 typedef int (TI_session_accept)(tls_session *s);
005aba9
 typedef int (TI_session_upflags)(Sockbuf *sb, tls_session *s, int rc);
005aba9
 typedef char *(TI_session_errmsg)(tls_session *s, int rc, char *buf, size_t len );
005aba9
diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c
005aba9
index 82ca5272cc..cbeea8c6c4 100644
005aba9
--- a/libraries/libldap/tls2.c
005aba9
+++ b/libraries/libldap/tls2.c
005aba9
@@ -368,7 +368,7 @@ ldap_int_tls_connect( LDAP *ld, LDAPConn *conn, const char *host )
005aba9
 			lo->ldo_tls_connect_cb( ld, ssl, ctx, lo->ldo_tls_connect_arg );
005aba9
 	}
005aba9
 
005aba9
-	err = tls_imp->ti_session_connect( ld, ssl );
005aba9
+	err = tls_imp->ti_session_connect( ld, ssl, host );
005aba9
 
005aba9
 #ifdef HAVE_WINSOCK
005aba9
 	errno = WSAGetLastError();
005aba9
diff --git a/libraries/libldap/tls_g.c b/libraries/libldap/tls_g.c
005aba9
index 3b72cd2a1f..5468ed3f05 100644
005aba9
--- a/libraries/libldap/tls_g.c
005aba9
+++ b/libraries/libldap/tls_g.c
005aba9
@@ -336,7 +336,7 @@ tlsg_session_accept( tls_session *session )
005aba9
 }
005aba9
 
005aba9
 static int
005aba9
-tlsg_session_connect( LDAP *ld, tls_session *session )
005aba9
+tlsg_session_connect( LDAP *ld, tls_session *session, const char *name_in )
005aba9
 {
005aba9
 	return tlsg_session_accept( session);
005aba9
 }
005aba9
diff --git a/libraries/libldap/tls_o.c b/libraries/libldap/tls_o.c
005aba9
index 498f805fa1..455b23c0e9 100644
005aba9
--- a/libraries/libldap/tls_o.c
005aba9
+++ b/libraries/libldap/tls_o.c
005aba9
@@ -548,12 +548,16 @@ tlso_session_new( tls_ctx *ctx, int is_server )
005aba9
 }
005aba9
 
005aba9
 static int
005aba9
-tlso_session_connect( LDAP *ld, tls_session *sess )
005aba9
+tlso_session_connect( LDAP *ld, tls_session *sess, const char *name_in )
005aba9
 {
005aba9
 	tlso_session *s = (tlso_session *)sess;
005aba9
+	int rc;
005aba9
 
005aba9
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
005aba9
+	SSL_set_tlsext_host_name( s, name_in );
005aba9
+#endif
005aba9
 	/* Caller expects 0 = success, OpenSSL returns 1 = success */
005aba9
-	int rc = SSL_connect( s ) - 1;
005aba9
+	rc = SSL_connect( s ) - 1;
005aba9
 #ifdef LDAP_USE_NON_BLOCKING_TLS
005aba9
 	if ( rc < 0 ) {
005aba9
 		int sockerr = sock_errno();
005aba9
005aba9
From 421c2021c7209bd7cd947ccb8b989bddab7b63cb Mon Sep 17 00:00:00 2001
005aba9
From: Howard Chu <hyc@openldap.org>
005aba9
Date: Mon, 27 Apr 2020 18:25:10 +0100
005aba9
Subject: [PATCH 2/4] ITS#9176 check for numeric addrs before passing SNI
005aba9
005aba9
---
005aba9
 libraries/libldap/tls2.c  | 22 +++++++++++++++++++++-
005aba9
 libraries/libldap/tls_o.c |  4 +++-
005aba9
 2 files changed, 24 insertions(+), 2 deletions(-)
005aba9
005aba9
diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c
005aba9
index cbeea8c6c4..85628bc3b3 100644
005aba9
--- a/libraries/libldap/tls2.c
005aba9
+++ b/libraries/libldap/tls2.c
005aba9
@@ -334,6 +334,7 @@ ldap_int_tls_connect( LDAP *ld, LDAPConn *conn, const char *host )
005aba9
 	Sockbuf *sb = conn->lconn_sb;
005aba9
 	int	err;
005aba9
 	tls_session	*ssl = NULL;
005aba9
+	char *sni = host;
005aba9
 
005aba9
 	if ( HAS_TLS( sb )) {
005aba9
 		ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl );
005aba9
@@ -368,7 +369,26 @@ ldap_int_tls_connect( LDAP *ld, LDAPConn *conn, const char *host )
005aba9
 			lo->ldo_tls_connect_cb( ld, ssl, ctx, lo->ldo_tls_connect_arg );
005aba9
 	}
005aba9
 
005aba9
-	err = tls_imp->ti_session_connect( ld, ssl, host );
005aba9
+	/* pass hostname for SNI, but only if it's an actual name
005aba9
+	 * and not a numeric address
005aba9
+	 */
005aba9
+	{
005aba9
+		int numeric = 1;
005aba9
+		char *c;
005aba9
+		for ( c = sni; *c; c++ ) {
005aba9
+			if ( *c == ':' )	/* IPv6 address */
005aba9
+				break;
005aba9
+			if ( *c == '.' )
005aba9
+				continue;
005aba9
+			if ( !isdigit( *c )) {
005aba9
+				numeric = 0;
005aba9
+				break;
005aba9
+			}
005aba9
+		}
005aba9
+		if ( numeric )
005aba9
+			sni = NULL;
005aba9
+	}
005aba9
+	err = tls_imp->ti_session_connect( ld, ssl, sni );
005aba9
 
005aba9
 #ifdef HAVE_WINSOCK
005aba9
 	errno = WSAGetLastError();
005aba9
diff --git a/libraries/libldap/tls_o.c b/libraries/libldap/tls_o.c
005aba9
index 455b23c0e9..45948dbc64 100644
005aba9
--- a/libraries/libldap/tls_o.c
005aba9
+++ b/libraries/libldap/tls_o.c
005aba9
@@ -554,7 +554,9 @@ tlso_session_connect( LDAP *ld, tls_session *sess, const char *name_in )
005aba9
 	int rc;
005aba9
 
005aba9
 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
005aba9
-	SSL_set_tlsext_host_name( s, name_in );
005aba9
+	if ( name_in ) {
005aba9
+		SSL_set_tlsext_host_name( s, name_in );
005aba9
+	}
005aba9
 #endif
005aba9
 	/* Caller expects 0 = success, OpenSSL returns 1 = success */
005aba9
 	rc = SSL_connect( s ) - 1;
005aba9
005aba9
From 05a65a46c684031a841bcc39cf01a82e8cc713a0 Mon Sep 17 00:00:00 2001
005aba9
From: Howard Chu <hyc@openldap.org>
005aba9
Date: Mon, 27 Apr 2020 18:54:02 +0100
005aba9
Subject: [PATCH 3/4] ITS#9176 check for failure setting SNI
005aba9
005aba9
---
005aba9
 libraries/libldap/tls_o.c | 4 +++-
005aba9
 1 file changed, 3 insertions(+), 1 deletion(-)
005aba9
005aba9
diff --git a/libraries/libldap/tls_o.c b/libraries/libldap/tls_o.c
005aba9
index 45948dbc64..86e86db3b6 100644
005aba9
--- a/libraries/libldap/tls_o.c
005aba9
+++ b/libraries/libldap/tls_o.c
005aba9
@@ -555,7 +555,9 @@ tlso_session_connect( LDAP *ld, tls_session *sess, const char *name_in )
005aba9
 
005aba9
 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
005aba9
 	if ( name_in ) {
005aba9
-		SSL_set_tlsext_host_name( s, name_in );
005aba9
+		rc = SSL_set_tlsext_host_name( s, name_in );
005aba9
+		if ( !rc )		/* can fail to strdup the name */
005aba9
+			return -1;
005aba9
 	}
005aba9
 #endif
005aba9
 	/* Caller expects 0 = success, OpenSSL returns 1 = success */
005aba9
005aba9
From d059488fa86b58744ad70819516d3bf4a37dbb8e Mon Sep 17 00:00:00 2001
005aba9
From: Ryan Tandy <ryan@nardis.ca>
005aba9
Date: Mon, 27 Apr 2020 11:01:01 -0700
005aba9
Subject: [PATCH 4/4] ITS#9176 Implement SNI for GnuTLS
005aba9
005aba9
---
005aba9
 libraries/libldap/tls_g.c | 10 ++++++++++
005aba9
 1 file changed, 10 insertions(+)
005aba9
005aba9
diff --git a/libraries/libldap/tls_g.c b/libraries/libldap/tls_g.c
005aba9
index 5468ed3f05..5fceb3e935 100644
005aba9
--- a/libraries/libldap/tls_g.c
005aba9
+++ b/libraries/libldap/tls_g.c
005aba9
@@ -338,6 +338,16 @@ tlsg_session_accept( tls_session *session )
005aba9
 static int
005aba9
 tlsg_session_connect( LDAP *ld, tls_session *session, const char *name_in )
005aba9
 {
005aba9
+	tlsg_session *s = (tlsg_session *)session;
005aba9
+	int rc;
005aba9
+
005aba9
+	if ( name_in ) {
005aba9
+		rc = gnutls_server_name_set( s->session, GNUTLS_NAME_DNS, name_in, strlen(name_in) );
005aba9
+		if ( rc != GNUTLS_E_SUCCESS ) {
005aba9
+			return rc;
005aba9
+		}
005aba9
+	}
005aba9
+
005aba9
 	return tlsg_session_accept( session);
005aba9
 }
005aba9