Jan Vcelak 1f24c41
TLS: do not reuse tls_session if hostname check fails
Jan Vcelak 1f24c41
Jan Vcelak 1f24c41
If multiple servers are specified, the connection to the first one succeeds, and the hostname verification fails,
Jan Vcelak 1f24c41
*tls_session is not dropped, but reused when connecting to the second server.
Jan Vcelak 1f24c41
Jan Vcelak 1f24c41
This is a problem with Mozilla NSS backend because another handshake cannot be performed on the same file descriptor.
Jan Vcelak 1f24c41
From this reason, hostname checking was moved into ldap_int_tls_connect() before connection error handling.
Jan Vcelak 1f24c41
Jan Vcelak 1f24c41
Author: Jan Vcelak <jvcelak@redhat.com>
Jan Vcelak 1f24c41
Upstream ITS: #7373
Jan Vcelak 1f24c41
Resolves: #852476 
Jan Vcelak 1f24c41
Jan Vcelak 1f24c41
diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c
705b2a5
index 10b993b..a3cd590 100644
Jan Vcelak 1f24c41
--- a/libraries/libldap/tls2.c
Jan Vcelak 1f24c41
+++ b/libraries/libldap/tls2.c
705b2a5
@@ -320,7 +320,7 @@ update_flags( Sockbuf *sb, tls_session * ssl, int rc )
Jan Vcelak 1f24c41
  */
Jan Vcelak 1f24c41
 
Jan Vcelak 1f24c41
 static int
Jan Vcelak 1f24c41
-ldap_int_tls_connect( LDAP *ld, LDAPConn *conn )
Jan Vcelak 1f24c41
+ldap_int_tls_connect( LDAP *ld, LDAPConn *conn, const char *host )
Jan Vcelak 1f24c41
 {
Jan Vcelak 1f24c41
 	Sockbuf *sb = conn->lconn_sb;
Jan Vcelak 1f24c41
 	int	err;
705b2a5
@@ -365,6 +365,10 @@ ldap_int_tls_connect( LDAP *ld, LDAPConn *conn )
Jan Vcelak 1f24c41
 	errno = WSAGetLastError();
Jan Vcelak 1f24c41
 #endif
Jan Vcelak 1f24c41
 
Jan Vcelak 1f24c41
+	if ( err == 0 ) {
Jan Vcelak 1f24c41
+		err = ldap_pvt_tls_check_hostname( ld, ssl, host );
Jan Vcelak 1f24c41
+	}
Jan Vcelak 1f24c41
+
Jan Vcelak 1f24c41
 	if ( err < 0 )
Jan Vcelak 1f24c41
 	{
Jan Vcelak 1f24c41
 		char buf[256], *msg;
705b2a5
@@ -495,7 +499,15 @@ ldap_pvt_tls_check_hostname( LDAP *ld, void *s, const char *name_in )
Jan Vcelak 1f24c41
 {
Jan Vcelak 1f24c41
 	tls_session *session = s;
Jan Vcelak 1f24c41
 
Jan Vcelak 1f24c41
-	return tls_imp->ti_session_chkhost( ld, session, name_in );
Jan Vcelak 1f24c41
+	if (ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER &&
Jan Vcelak 1f24c41
+	    ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_ALLOW) {
Jan Vcelak 1f24c41
+		ld->ld_errno = tls_imp->ti_session_chkhost( ld, session, name_in );
Jan Vcelak 1f24c41
+		if (ld->ld_errno != LDAP_SUCCESS) {
Jan Vcelak 1f24c41
+			return ld->ld_errno;
Jan Vcelak 1f24c41
+		}
Jan Vcelak 1f24c41
+	}
Jan Vcelak 1f24c41
+
Jan Vcelak 1f24c41
+	return LDAP_SUCCESS;
Jan Vcelak 1f24c41
 }
Jan Vcelak 1f24c41
 
Jan Vcelak 1f24c41
 int
705b2a5
@@ -857,7 +869,7 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv )
705b2a5
 #endif /* LDAP_USE_NON_BLOCKING_TLS */
705b2a5
 
705b2a5
 	ld->ld_errno = LDAP_SUCCESS;
705b2a5
-	ret = ldap_int_tls_connect( ld, conn );
705b2a5
+	ret = ldap_int_tls_connect( ld, conn, host );
705b2a5
 
705b2a5
 #ifdef LDAP_USE_NON_BLOCKING_TLS
705b2a5
 	while ( ret > 0 ) { /* this should only happen for non-blocking io */
705b2a5
@@ -878,7 +890,7 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv )
705b2a5
 		} else {
705b2a5
 			/* ldap_int_poll called ldap_pvt_ndelay_off */
705b2a5
 			ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_SET_NONBLOCK, sb );
705b2a5
-			ret = ldap_int_tls_connect( ld, conn );
705b2a5
+			ret = ldap_int_tls_connect( ld, conn, host );
705b2a5
 			if ( ret > 0 ) { /* need to call tls_connect once more */
705b2a5
 				struct timeval curr_time_tv, delta_tv;
705b2a5
 
705b2a5
@@ -935,20 +947,6 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv )
Jan Vcelak 1f24c41
 		return (ld->ld_errno);
Jan Vcelak 1f24c41
 	}
Jan Vcelak 1f24c41
 
Jan Vcelak 1f24c41
-	ssl = ldap_pvt_tls_sb_ctx( sb );
Jan Vcelak 1f24c41
-	assert( ssl != NULL );
Jan Vcelak 1f24c41
-
Jan Vcelak 1f24c41
-	/* 
Jan Vcelak 1f24c41
-	 * compare host with name(s) in certificate
Jan Vcelak 1f24c41
-	 */
Jan Vcelak 1f24c41
-	if (ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER &&
Jan Vcelak 1f24c41
-	    ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_ALLOW) {
Jan Vcelak 1f24c41
-		ld->ld_errno = ldap_pvt_tls_check_hostname( ld, ssl, host );
Jan Vcelak 1f24c41
-		if (ld->ld_errno != LDAP_SUCCESS) {
Jan Vcelak 1f24c41
-			return ld->ld_errno;
Jan Vcelak 1f24c41
-		}
Jan Vcelak 1f24c41
-	}
Jan Vcelak 1f24c41
-
Jan Vcelak 1f24c41
 	return LDAP_SUCCESS;
Jan Vcelak 1f24c41
 }
Jan Vcelak 1f24c41