diff libfdcore/sctps.c @ 807:09f8f0c4f4a4

Several changes to support GnuTLS 3.x in a more efficient way
author Sebastien Decugis <sdecugis@freediameter.net>
date Fri, 24 Aug 2012 00:15:48 +0200
parents d5a4b5e175c2
children c0a88c1bcc1e
line wrap: on
line diff
--- a/libfdcore/sctps.c	Wed Aug 22 23:04:38 2012 +0200
+++ b/libfdcore/sctps.c	Fri Aug 24 00:15:48 2012 +0200
@@ -104,7 +104,6 @@
 				break;
 			
 			case FDEVP_CNX_ERROR:
-				fd_cnx_markerror(conn);
 				goto out;
 				
 			case FDEVP_CNX_SHUTDOWN:
@@ -120,9 +119,11 @@
 out:
 	/* Signal termination of the connection to all decipher threads */
 	for (strid = 0; strid < conn->cc_sctp_para.pairs; strid++) {
-		if (conn->cc_sctps_data.array[strid].raw_recv)
+		if (conn->cc_sctps_data.array[strid].raw_recv) {
 			CHECK_FCT_DO(fd_event_send(conn->cc_sctps_data.array[strid].raw_recv, FDEVP_CNX_ERROR, 0, NULL), goto fatal );
+		}
 	}
+	fd_cnx_markerror(conn);
 	TRACE_DEBUG(FULL, "Thread terminated");	
 	return NULL;
 	
@@ -170,7 +171,7 @@
 	TRACE_ENTRY("%p %p %zd", tr, data, len);
 	CHECK_PARAMS_DO( tr && data, { errno = EINVAL; return -1; } );
 	
-	CHECK_FCT_DO( fd_sctp_sendstr(ctx->parent, ctx->strid, (uint8_t *)data, len), /* errno is already set */ return -1 );
+	CHECK_FCT_DO( fd_sctp_sendstr(ctx->parent, ctx->strid, (uint8_t *)data, len), return -1 );
 	
 	return len;
 }
@@ -183,14 +184,16 @@
 	int emptied;
 	
 	TRACE_ENTRY("%p %p %zd", tr, buf, len);
-	CHECK_PARAMS_DO( tr && buf, { errno = EINVAL; return -1; } );
+	CHECK_PARAMS_DO( tr && buf, { errno = EINVAL; goto error; } );
 	
 	/* If we don't have data available now, pull new message from the fifo -- this is blocking (until the queue is destroyed) */
 	if (!ctx->partial.buf) {
 		int ev;
-		CHECK_FCT_DO( errno = fd_event_get(ctx->raw_recv, &ev, &ctx->partial.bufsz, (void *)&ctx->partial.buf), return -1 );
-		if (ev == FDEVP_CNX_ERROR) 
-			return 0; /* connection closed */
+		CHECK_FCT_DO( errno = fd_event_get(ctx->raw_recv, &ev, &ctx->partial.bufsz, (void *)&ctx->partial.buf), goto error );
+		if (ev == FDEVP_CNX_ERROR) {
+			/* Documentations says to return 0 on connection closed, but it does hang within gnutls_handshake */
+			return -1;
+		}
 	}
 		
 	pulled = ctx->partial.bufsz - ctx->partial.offset;
@@ -215,6 +218,10 @@
 
 	/* We are done */
 	return pulled;
+	
+error:
+	gnutls_transport_set_errno (ctx->session, errno);
+	return -1;
 }
 
 /* Set the parameters of a session to use the appropriate fifo and stream information */
@@ -462,21 +469,21 @@
 	}
 	
 	TRACE_DEBUG(FULL, "Starting TLS resumed handshake on stream %hu", ctx->strid);
-#ifdef GNUTLS_VERSION_310
-	GNUTLS_TRACE( gnutls_handshake_set_timeout( ctx->session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT));
-#endif /* GNUTLS_VERSION_310 */
+
 	CHECK_GNUTLS_DO( gnutls_handshake( ctx->session ), return NULL);
 			
 	GNUTLS_TRACE( resumed = gnutls_session_is_resumed(ctx->session) );
+	#ifndef GNUTLS_VERSION_300
 	if (!resumed) {
 		/* Check the credentials here also */
 		CHECK_FCT_DO( fd_tls_verify_credentials(ctx->session, ctx->parent, 0), return NULL );
 	}
+	#endif /* GNUTLS_VERSION_300 */
 	if (TRACE_BOOL(FULL)) {
 		if (resumed) {
 			fd_log_debug("Session was resumed successfully on stream %hu (conn: '%s')\n", ctx->strid, fd_cnx_getid(ctx->parent));
 		} else {
-			fd_log_debug("Session was NOT resumed on stream %hu  (full handshake + verif) (conn: '%s')\n", ctx->strid, fd_cnx_getid(ctx->parent));
+			fd_log_debug("Session was NOT resumed on stream %hu  (full handshake) (conn: '%s')\n", ctx->strid, fd_cnx_getid(ctx->parent));
 		}
 	}
 			
@@ -554,6 +561,24 @@
 		/* Set credentials and priority */
 		CHECK_FCT( fd_tls_prepare(&conn->cc_sctps_data.array[i].session, conn->cc_tls_para.mode, priority, alt_creds) );
 		
+		/* additional initialization for gnutls 3.x */
+		#ifdef GNUTLS_VERSION_300
+			/* the verify function has already been set in the global initialization in config.c */
+
+		/* fd_tls_verify_credentials_2 uses the connection */
+		gnutls_session_set_ptr (conn->cc_sctps_data.array[i].session, (void *) conn);
+
+		if ((conn->cc_tls_para.cn != NULL) && (conn->cc_tls_para.mode == GNUTLS_CLIENT)) {
+			/* this might allow virtual hosting on the remote peer */
+			CHECK_GNUTLS_DO( gnutls_server_name_set (conn->cc_sctps_data.array[i].session, GNUTLS_NAME_DNS, conn->cc_tls_para.cn, strlen(conn->cc_tls_para.cn)), /* ignore failure */);
+		}
+
+		#endif /* GNUTLS_VERSION_300 */
+
+		#ifdef GNUTLS_VERSION_310
+		GNUTLS_TRACE( gnutls_handshake_set_timeout( conn->cc_sctps_data.array[i].session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT));
+		#endif /* GNUTLS_VERSION_310 */
+
 		/* For the client, copy data from master session; for the server, set session resuming pointers */
 		if (conn->cc_tls_para.mode == GNUTLS_CLIENT) {
 			CHECK_GNUTLS_DO( gnutls_session_set_data(conn->cc_sctps_data.array[i].session, master_data.data, master_data.size), return ENOMEM );
"Welcome to our mercurial repository"