changeset 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 a0e3af6f94fb
files freeDiameter/cnxctx.c freeDiameter/cnxctx.h freeDiameter/sctps.c
diffstat 3 files changed, 21 insertions(+), 16 deletions(-) [+]
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 */
--- a/freeDiameter/cnxctx.h	Mon Sep 13 18:39:22 2010 +0900
+++ b/freeDiameter/cnxctx.h	Tue Sep 14 13:31:27 2010 +0900
@@ -127,7 +127,7 @@
 
 int fd_sctps_init(struct cnxctx * conn);
 int fd_sctps_handshake_others(struct cnxctx * conn, char * priority, void * alt_creds);
-int fd_sctps_startthreads(struct cnxctx * conn);
+int fd_sctps_startthreads(struct cnxctx * conn, int others);
 void fd_sctps_bye(struct cnxctx * conn);
 void fd_sctps_waitthreadsterm(struct cnxctx * conn);
 void fd_sctps_gnutls_deinit_others(struct cnxctx * conn);
--- a/freeDiameter/sctps.c	Mon Sep 13 18:39:22 2010 +0900
+++ b/freeDiameter/sctps.c	Tue Sep 14 13:31:27 2010 +0900
@@ -597,18 +597,22 @@
 	return 0;
 }
 
-/* Receive messages from all stream pairs */
-int fd_sctps_startthreads(struct cnxctx * conn)
+/* Receive messages from others ? all other stream pairs : the master pair */
+int fd_sctps_startthreads(struct cnxctx * conn, int others)
 {
 	uint16_t i;
 	
 	TRACE_ENTRY("%p", conn);
 	CHECK_PARAMS( conn && conn->cc_sctps_data.array );
 	
-	for (i = 0; i < conn->cc_sctp_para.pairs; i++) {
-		
-		/* Start the decipher thread */
-		CHECK_POSIX( pthread_create( &conn->cc_sctps_data.array[i].thr, NULL, decipher, &conn->cc_sctps_data.array[i] ) );
+	if (others) {
+		for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
+
+			/* Start the decipher thread */
+			CHECK_POSIX( pthread_create( &conn->cc_sctps_data.array[i].thr, NULL, decipher, &conn->cc_sctps_data.array[i] ) );
+		}
+	} else {
+		CHECK_POSIX( pthread_create( &conn->cc_sctps_data.array[0].thr, NULL, decipher, &conn->cc_sctps_data.array[0] ) );
 	}
 	return 0;
 }
"Welcome to our mercurial repository"