diff freeDiameter/cnxctx.c @ 543:40141acabee7

Fix behavior of TLS/SCTP when only one peer does not accept the remote certificate
author Sebastien Decugis <sdecugis@nict.go.jp>
date Tue, 14 Sep 2010 13:31:27 +0900
parents 0b6cee362f5d
children 88a494357a9d
line wrap: on
line diff
--- a/freeDiameter/cnxctx.c	Mon Sep 13 18:39:22 2010 +0900
+++ b/freeDiameter/cnxctx.c	Tue Sep 14 13:31:27 2010 +0900
@@ -994,7 +994,7 @@
 /* Verify remote credentials after successful handshake (return 0 if OK, EINVAL otherwise) */
 int fd_tls_verify_credentials(gnutls_session_t session, struct cnxctx * conn, int verbose)
 {
-	int i;
+	int i, ret = 0;
 	unsigned int gtret;
 	const gnutls_datum_t *cert_list;
 	unsigned int cert_list_size;
@@ -1175,15 +1175,13 @@
 		CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return EINVAL);
 		CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL);
 		
-		/* When gnutls 2.10.1 is around, we should use gnutls_certificate_set_verify_function */
-		
 		GNUTLS_TRACE( deadline = gnutls_x509_crt_get_expiration_time(cert) );
 		if ((deadline != (time_t)-1) && (deadline < now)) {
 			if (TRACE_BOOL(INFO)) {
 				fd_log_debug("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :\n", conn->cc_socket, conn->cc_remid, conn->cc_id);
 				fd_log_debug(" - The certificate %d in the chain is expired\n", i);
 			}
-			return EINVAL;
+			ret = EINVAL;
 		}
 		
 		GNUTLS_TRACE( deadline = gnutls_x509_crt_get_activation_time(cert) );
@@ -1192,7 +1190,7 @@
 				fd_log_debug("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :\n", conn->cc_socket, conn->cc_remid, conn->cc_id);
 				fd_log_debug(" - The certificate %d in the chain is not yet activated\n", i);
 			}
-			return EINVAL;
+			ret = EINVAL;
 		}
 		
 		if ((i == 0) && (conn->cc_tls_para.cn)) {
@@ -1201,14 +1199,14 @@
 					fd_log_debug("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :\n", conn->cc_socket, conn->cc_remid, conn->cc_id);
 					fd_log_debug(" - The certificate hostname does not match '%s'\n", conn->cc_tls_para.cn);
 				}
-				return EINVAL;
+				ret = EINVAL;
 			}
 		}
 		
 		GNUTLS_TRACE( gnutls_x509_crt_deinit (cert) );
 	}
 
-	return 0;
+	return ret;
 }
 
 /* TLS handshake a connection; no need to have called start_clear before. Reception is active if handhsake is successful */
@@ -1255,7 +1253,7 @@
 	{
 		int ret;
 		
-		/* When gnutls 2.10.1 is around, we should use gnutls_certificate_set_verify_function */
+		/* When gnutls 2.10.1 is around, we should use gnutls_certificate_set_verify_function and fd_tls_verify_credentials, so that handshake fails directly. */
 		
 		CHECK_GNUTLS_DO( ret = gnutls_handshake(conn->cc_tls_para.session),
 			{
@@ -1278,11 +1276,14 @@
 	/* Multi-stream TLS: handshake other streams as well */
 	if (conn->cc_sctp_para.pairs > 1) {
 #ifndef DISABLE_SCTP
+		/* Start reading the messages from the master session. That way, if the remote peer closed, we are not stuck inside handshake */
+		CHECK_FCT(fd_sctps_startthreads(conn, 0));
+		
 		/* Resume all additional sessions from the master one. */
 		CHECK_FCT(fd_sctps_handshake_others(conn, priority, alt_creds));
 
 		/* Start decrypting the messages from all threads and queuing them in target queue */
-		CHECK_FCT(fd_sctps_startthreads(conn));
+		CHECK_FCT(fd_sctps_startthreads(conn, 1));
 #endif /* DISABLE_SCTP */
 	} else {
 		/* Start decrypting the data */
"Welcome to our mercurial repository"