# HG changeset patch # User Sebastien Decugis # Date 1284438687 -32400 # Node ID 40141acabee7af65a9e72328b9fb6220d47cfccf # Parent 0b6cee362f5d0a2ed899a55759743119b7efe8ad Fix behavior of TLS/SCTP when only one peer does not accept the remote certificate diff -r 0b6cee362f5d -r 40141acabee7 freeDiameter/cnxctx.c --- 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 */ diff -r 0b6cee362f5d -r 40141acabee7 freeDiameter/cnxctx.h --- 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); diff -r 0b6cee362f5d -r 40141acabee7 freeDiameter/sctps.c --- 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; }