tstellar / rpms / openldap

Forked from rpms/openldap 3 years ago
Clone
Blob Blame History Raw
TLS: do not reuse tls_session if hostname check fails

If multiple servers are specified, the connection to the first one succeeds, and the hostname verification fails,
*tls_session is not dropped, but reused when connecting to the second server.

This is a problem with Mozilla NSS backend because another handshake cannot be performed on the same file descriptor.
From this reason, hostname checking was moved into ldap_int_tls_connect() before connection error handling.

Author: Jan Vcelak <jvcelak@redhat.com>
Upstream ITS: #7373
Resolves: #852476 

diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c
index f0b5bef..b13cb6d 100644
--- a/libraries/libldap/tls2.c
+++ b/libraries/libldap/tls2.c
@@ -316,7 +316,7 @@ update_flags( Sockbuf *sb, tls_session * ssl, int rc )
  */
 
 static int
-ldap_int_tls_connect( LDAP *ld, LDAPConn *conn )
+ldap_int_tls_connect( LDAP *ld, LDAPConn *conn, const char *host )
 {
 	Sockbuf *sb = conn->lconn_sb;
 	int	err;
@@ -361,6 +361,10 @@ ldap_int_tls_connect( LDAP *ld, LDAPConn *conn )
 	errno = WSAGetLastError();
 #endif
 
+	if ( err == 0 ) {
+		err = ldap_pvt_tls_check_hostname( ld, ssl, host );
+	}
+
 	if ( err < 0 )
 	{
 		char buf[256], *msg;
@@ -491,7 +495,15 @@ ldap_pvt_tls_check_hostname( LDAP *ld, void *s, const char *name_in )
 {
 	tls_session *session = s;
 
-	return tls_imp->ti_session_chkhost( ld, session, name_in );
+	if (ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER &&
+	    ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_ALLOW) {
+		ld->ld_errno = tls_imp->ti_session_chkhost( ld, session, name_in );
+		if (ld->ld_errno != LDAP_SUCCESS) {
+			return ld->ld_errno;
+		}
+	}
+
+	return LDAP_SUCCESS;
 }
 
 int
@@ -831,25 +843,11 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv )
 	/*
 	 * Fortunately, the lib uses blocking io...
 	 */
-	if ( ldap_int_tls_connect( ld, conn ) < 0 ) {
+	if ( ldap_int_tls_connect( ld, conn, host ) < 0 ) {
 		ld->ld_errno = LDAP_CONNECT_ERROR;
 		return (ld->ld_errno);
 	}
 
-	ssl = ldap_pvt_tls_sb_ctx( sb );
-	assert( ssl != NULL );
-
-	/* 
-	 * compare host with name(s) in certificate
-	 */
-	if (ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER &&
-	    ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_ALLOW) {
-		ld->ld_errno = ldap_pvt_tls_check_hostname( ld, ssl, host );
-		if (ld->ld_errno != LDAP_SUCCESS) {
-			return ld->ld_errno;
-		}
-	}
-
 	return LDAP_SUCCESS;
 }
 
-- 
1.7.11.4