Commit 3f56af5c authored by Sebastien Decugis's avatar Sebastien Decugis
Browse files

Added a test for cnxctx (tbc) and fixed some bugs

parent ddddb5cc
......@@ -32,6 +32,9 @@ L = Koganei
O = WIDE
OU = "AAA WG"
#Default lifetime
DAYS = 365
#Values for the CA
CA_CN = chavroux.cowaddict.org
CA_mail = sdecugis@nict.go.jp
......@@ -129,6 +132,7 @@ cert:
fi;
@openssl ca $(CONFIG) -in $(DIR)/clients/csr/$(name).csr \
-out $(DIR)/clients/certs/$(name).cert \
-days $(DAYS) \
-batch
@ln -s $(DIR)/clients/certs/$(name).cert $(DIR)/certs/`openssl x509 -noout -hash < $(DIR)/clients/certs/$(name).cert`.0
......
......@@ -396,6 +396,20 @@ char * fd_cnx_getid(struct cnxctx * conn)
return conn->cc_id;
}
/* Return the protocol of a connection */
int fd_cnx_getproto(struct cnxctx * conn)
{
CHECK_PARAMS_DO( conn, return 0 );
return conn->cc_proto;
}
/* Return the TLS state of a connection */
int fd_cnx_getTLS(struct cnxctx * conn)
{
CHECK_PARAMS_DO( conn, return 0 );
return conn->cc_tls;
}
/* Get the list of endpoints (IP addresses) of the local and remote peers on this connection */
int fd_cnx_getendpoints(struct cnxctx * conn, struct fd_list * local, struct fd_list * remote)
{
......@@ -473,8 +487,15 @@ static void * rcvthr_notls_tcp(void * arg)
struct cnxctx * conn = arg;
TRACE_ENTRY("%p", arg);
CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto out);
/* Set the thread name */
{
char buf[48];
snprintf(buf, sizeof(buf), "Receiver (%d) TCP/noTLS)", conn->cc_socket);
fd_log_threadname ( buf );
}
ASSERT( conn->cc_proto == IPPROTO_TCP );
ASSERT( conn->cc_tls == 0 );
ASSERT( Target_Queue(conn) );
......@@ -547,8 +568,15 @@ static void * rcvthr_notls_sctp(void * arg)
int event;
TRACE_ENTRY("%p", arg);
CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto out);
/* Set the thread name */
{
char buf[48];
snprintf(buf, sizeof(buf), "Receiver (%d) SCTP/noTLS)", conn->cc_socket);
fd_log_threadname ( buf );
}
ASSERT( conn->cc_proto == IPPROTO_SCTP );
ASSERT( conn->cc_tls == 0 );
ASSERT( Target_Queue(conn) );
......@@ -606,7 +634,7 @@ end:
/* The function that receives TLS data and re-builds a Diameter message -- it exits only on error or cancelation */
int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session)
{
/* No guaranty that GnuTLS preserves the message boundaries, so we re-build it as in TCP */
/* No guarantee that GnuTLS preserves the message boundaries, so we re-build it as in TCP */
do {
uint8_t header[4];
uint8_t * newmsg;
......@@ -615,7 +643,7 @@ int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session)
size_t received = 0;
do {
ret = fd_tls_recv_handle_error(conn, conn->cc_tls_para.session, &header[received], sizeof(header) - received);
ret = fd_tls_recv_handle_error(conn, session, &header[received], sizeof(header) - received);
if (ret == 0) {
/* The connection is closed */
goto out;
......@@ -639,7 +667,7 @@ int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session)
while (received < length) {
pthread_cleanup_push(free, newmsg); /* In case we are canceled, clean the partialy built buffer */
ret = fd_tls_recv_handle_error(conn, conn->cc_tls_para.session, newmsg + received, length - received);
ret = fd_tls_recv_handle_error(conn, session, newmsg + received, length - received);
pthread_cleanup_pop(0);
if (ret == 0) {
......@@ -663,8 +691,15 @@ static void * rcvthr_tls_single(void * arg)
struct cnxctx * conn = arg;
TRACE_ENTRY("%p", arg);
CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto error);
/* Set the thread name */
{
char buf[48];
snprintf(buf, sizeof(buf), "Receiver (%d) TLS/ single stream)", conn->cc_socket);
fd_log_threadname ( buf );
}
ASSERT( conn->cc_tls == 1 );
ASSERT( Target_Queue(conn) );
......@@ -708,7 +743,7 @@ int fd_cnx_start_clear(struct cnxctx * conn, int loop)
}
/* Prepare a gnutls session object for handshake */
int fd_tls_prepare(gnutls_session_t * session, int mode, char * priority)
int fd_tls_prepare(gnutls_session_t * session, int mode, char * priority, void * alt_creds)
{
/* Create the master session context */
CHECK_GNUTLS_DO( gnutls_init (session, mode), return ENOMEM );
......@@ -723,7 +758,7 @@ int fd_tls_prepare(gnutls_session_t * session, int mode, char * priority)
}
/* Set the credentials of this side of the connection */
CHECK_GNUTLS_DO( gnutls_credentials_set (*session, GNUTLS_CRD_CERTIFICATE, fd_g_config->cnf_sec_data.credentials), return EINVAL );
CHECK_GNUTLS_DO( gnutls_credentials_set (*session, GNUTLS_CRD_CERTIFICATE, alt_creds ?: fd_g_config->cnf_sec_data.credentials), return EINVAL );
/* Request the remote credentials as well */
if (mode == GNUTLS_SERVER) {
......@@ -734,7 +769,7 @@ int fd_tls_prepare(gnutls_session_t * session, int mode, char * priority)
}
/* TLS handshake a connection; no need to have called start_clear before. Reception is active if handhsake is successful */
int fd_cnx_handshake(struct cnxctx * conn, int mode, char * priority)
int fd_cnx_handshake(struct cnxctx * conn, int mode, char * priority, void * alt_creds)
{
TRACE_ENTRY( "%p %d", conn, mode);
CHECK_PARAMS( conn && (!conn->cc_tls) && ( (mode == GNUTLS_CLIENT) || (mode == GNUTLS_SERVER) ) && (!conn->cc_loop) );
......@@ -749,7 +784,7 @@ int fd_cnx_handshake(struct cnxctx * conn, int mode, char * priority)
conn->cc_loop = 1;
/* Prepare the master session credentials and priority */
CHECK_FCT( fd_tls_prepare(&conn->cc_tls_para.session, mode, priority) );
CHECK_FCT( fd_tls_prepare(&conn->cc_tls_para.session, mode, priority, alt_creds) );
/* Special case: multi-stream TLS is not natively managed in GNU TLS, we use a wrapper library */
if (conn->cc_sctp_para.pairs > 1) {
......@@ -800,16 +835,22 @@ int fd_cnx_handshake(struct cnxctx * conn, int mode, char * priority)
if (conn->cc_sctp_para.pairs > 1) {
#ifndef DISABLE_SCTP
/* Resume all additional sessions from the master one. */
CHECK_FCT(fd_sctps_handshake_others(conn, priority));
CHECK_FCT(fd_sctps_handshake_others(conn, priority, alt_creds));
/* Mark the connection as protected from here */
conn->cc_tls = 1;
/* Start decrypting the messages from all threads and queuing them in target queue */
CHECK_FCT(fd_sctps_startthreads(conn));
#endif /* DISABLE_SCTP */
} else {
/* Mark the connection as protected from here */
conn->cc_tls = 1;
/* Start decrypting the data */
CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, rcvthr_tls_single, conn ) );
}
return 0;
}
......
......@@ -78,7 +78,7 @@ struct cnxctx {
/* TLS */
int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session);
int fd_tls_prepare(gnutls_session_t * session, int mode, char * priority);
int fd_tls_prepare(gnutls_session_t * session, int mode, char * priority, void * alt_creds);
/* TCP */
int fd_tcp_create_bind_server( int * sock, sSA * sa, socklen_t salen );
......@@ -113,7 +113,7 @@ struct sctps_ctx {
};
int fd_sctps_init(struct cnxctx * conn);
int fd_sctps_handshake_others(struct cnxctx * conn, char * priority);
int fd_sctps_handshake_others(struct cnxctx * conn, char * priority, void * alt_creds);
int fd_sctps_startthreads(struct cnxctx * conn);
void fd_sctps_stopthreads(struct cnxctx * conn);
void fd_sctps_destroy(struct cnxctx * conn);
......
......@@ -176,6 +176,13 @@ const char * fd_pev_str(int event);
#define CHECK_EVENT( _e ) \
(((int)(_e) >= FDEVP_DUMP_ALL) && ((int)(_e) <= FDEVP_PSM_TIMEOUT))
/* The data structure for FDEVP_CNX_INCOMING events */
struct cnx_incoming {
struct msg * cer; /* the CER message received on this connection */
struct cnxctx * cnx; /* The connection context */
int validate; /* The peer is new, it must be validated (by an extension) or error CEA to be sent */
};
/* Structure to store a sent request */
struct sentreq {
struct fd_list chain; /* the "o" field points directly to the hop-by-hop of the request (uint32_t *) */
......@@ -189,8 +196,9 @@ void fd_peer_dump_list(int details);
void fd_peer_dump(struct fd_peer * peer, int details);
int fd_peer_alloc(struct fd_peer ** ptr);
int fd_peer_free(struct fd_peer ** ptr);
int fd_peer_handle_newCER( struct msg ** cer, struct cnxctx ** cnx, int tls_done );
int fd_peer_handle_newCER( struct msg ** cer, struct cnxctx ** cnx );
/* fd_peer_add declared in freeDiameter.h */
int fd_peer_validate( struct fd_peer * peer );
/* Peer expiry */
int fd_p_expi_init(void);
......@@ -215,9 +223,11 @@ int fd_cnx_serv_listen(struct cnxctx * conn);
struct cnxctx * fd_cnx_serv_accept(struct cnxctx * serv);
struct cnxctx * fd_cnx_cli_connect_tcp(sSA * sa, socklen_t addrlen);
struct cnxctx * fd_cnx_cli_connect_sctp(int no_ip6, uint16_t port, struct fd_list * list);
char * fd_cnx_getid(struct cnxctx * conn);
int fd_cnx_start_clear(struct cnxctx * conn, int loop);
int fd_cnx_handshake(struct cnxctx * conn, int mode, char * priority);
int fd_cnx_handshake(struct cnxctx * conn, int mode, char * priority, void * alt_creds);
char * fd_cnx_getid(struct cnxctx * conn);
int fd_cnx_getproto(struct cnxctx * conn);
int fd_cnx_getTLS(struct cnxctx * conn);
int fd_cnx_getcred(struct cnxctx * conn, const gnutls_datum_t **cert_list, unsigned int *cert_list_size);
int fd_cnx_getendpoints(struct cnxctx * conn, struct fd_list * local, struct fd_list * remote);
char * fd_cnx_getremoteid(struct cnxctx * conn);
......
......@@ -208,6 +208,32 @@ psm_loop:
}
}
/* A new connection was established and CER containing this peer id was received */
if (event == FDEVP_CNX_INCOMING) {
struct cnx_incoming * params = ev_data;
ASSERT(params);
switch (peer->p_hdr.info.pi_state) {
case STATE_CLOSED:
TODO("Handle the CER, validate the peer if needed (and set expiry), set the alt_fifo in the connection, reply a CEA, eventually handshake, move to OPEN or REOPEN state");
break;
case STATE_WAITCNXACK:
case STATE_WAITCEA:
TODO("Election");
break;
default:
TODO("Reply with error CEA");
TODO("Close the connection");
/* reject_incoming_connection */
}
free(ev_data);
goto psm_loop;
}
/* MSG_RECEIVED: fd_p_expi_update(struct fd_peer * peer ) */
/* If timeout or OPEN : call cb if defined */
......@@ -222,8 +248,8 @@ psm_loop:
psm_end:
pthread_cleanup_pop(1); /* set STATE_ZOMBIE */
pthread_detach(peer->p_psm);
peer->p_psm = (pthread_t)NULL;
pthread_detach(pthread_self());
return NULL;
}
......
......@@ -375,7 +375,7 @@ void fd_peer_dump_list(int details)
}
/* Handle an incoming CER request on a new connection */
int fd_peer_handle_newCER( struct msg ** cer, struct cnxctx ** cnx, int tls_done )
int fd_peer_handle_newCER( struct msg ** cer, struct cnxctx ** cnx )
{
struct msg * msg;
struct dict_object *avp_oh_model;
......@@ -384,9 +384,11 @@ int fd_peer_handle_newCER( struct msg ** cer, struct cnxctx ** cnx, int tls_done
struct avp_hdr * avp_hdr;
struct fd_list * li;
int found = 0;
int ret = 0;
struct fd_peer * peer;
struct cnx_incoming * ev_data;
TRACE_ENTRY("%p %p %d", cer, cnx, tls_done);
TRACE_ENTRY("%p %p", cer, cnx);
CHECK_PARAMS(cer && *cer && cnx && *cnx);
msg = *cer;
......@@ -410,27 +412,48 @@ int fd_peer_handle_newCER( struct msg ** cer, struct cnxctx ** cnx, int tls_done
}
if (!found) {
/* Create a new peer entry for this new remote peer */
peer = NULL;
CHECK_FCT_DO( ret = fd_peer_alloc(&peer), goto out );
/* Set the peer Diameter Id and the responder flag parameters */
CHECK_MALLOC_DO( peer->p_hdr.info.pi_diamid = malloc(avp_hdr->avp_value->os.len + 1), { ret = ENOMEM; goto out; } );
CHECK_MALLOC_DO( peer->p_dbgorig = strdup(fd_cnx_getid(*cnx)), { ret = ENOMEM; goto out; } );
peer->p_flags.pf_responder = 1;
/* Upgrade the lock to write lock */
CHECK_POSIX_DO( ret = pthread_rwlock_wrlock(&fd_g_peers_rw), goto out );
/* Insert the new peer in the list (the PSM will take care of setting the expiry after validation) */
fd_list_insert_before( li, &peer->p_hdr.chain );
TODO("Create a new peer entry with this diameter id (pf_responder = 1)");
TODO("Upgrade the lock to wr");
TODO("Add the new peer in the list");
TODO("Release the wr lock");
TODO("Start the peer PSM, which will have to validate if this peer is authorized to connect, and so on");
/* Release the write lock */
CHECK_POSIX_DO( ret = pthread_rwlock_unlock(&fd_g_peers_rw), goto out );
/* Start the PSM, which will receive the event bellow */
CHECK_FCT_DO( ret = fd_psm_begin(peer), goto out );
}
TODO("Send the new connection event to the peer SM with the appropriate data: msg, conn, tls_done, found");
/* FDEVP_CNX_INCOMING */
/* Send the new connection event to the PSM */
CHECK_MALLOC_DO( ev_data = malloc(sizeof(struct cnx_incoming)), { ret = ENOMEM; goto out; } );
memset(ev_data, 0, sizeof(ev_data));
ev_data->cer = msg;
ev_data->cnx = *cnx;
ev_data->validate = !found;
/* Reset the "out" parameters, so that they are not cleanup on function return. */
*cer = NULL;
*cnx = NULL;
CHECK_FCT_DO( ret = fd_event_send(peer->p_events, FDEVP_CNX_INCOMING, sizeof(ev_data), ev_data), goto out );
out:
CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) );
if (ret == 0) {
/* Reset the "out" parameters, so that they are not cleanup on function return. */
*cer = NULL;
*cnx = NULL;
}
TODO("(later if not tls_done) handshake or start_clear(.., 1) ");
return 0;
return ret;
}
/* Save a callback to accept / reject incoming unknown peers */
......@@ -440,3 +463,12 @@ int fd_peer_validate_register ( int (*peer_validate)(struct peer_info * /* info
TODO("...");
return ENOTSUP;
}
/* Validate a peer by calling the callbacks in turn -- return 0 if the peer is validated, ! 0 in case of error or if the peer is rejected */
int fd_peer_validate( struct fd_peer * peer )
{
TODO("Default to reject");
TODO("Call all callbacks in turn");
TODO("Save cb2 in the peer if needed");
return ENOTSUP;
}
This diff is collapsed.
......@@ -72,10 +72,16 @@ static void * demuxer(void * arg)
uint16_t strid;
TRACE_ENTRY("%p", arg);
CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto out);
/* Set the thread name */
{
char buf[48];
snprintf(buf, sizeof(buf), "Demuxer (%d)", conn->cc_socket);
fd_log_threadname ( buf );
}
ASSERT( conn->cc_proto == IPPROTO_SCTP );
ASSERT( conn->cc_tls == 1 );
ASSERT( Target_Queue(conn) );
ASSERT( conn->cc_sctps_data.array );
......@@ -114,11 +120,17 @@ static void * decipher(void * arg)
struct cnxctx *cnx;
TRACE_ENTRY("%p", arg);
CHECK_PARAMS_DO(ctx && ctx->raw_recv && ctx->parent, goto error);
cnx = ctx->parent;
ASSERT( Target_Queue(cnx) );
/* Set the thread name */
{
char buf[48];
snprintf(buf, sizeof(buf), "Decipher (%hu@%d)", ctx->strid, cnx->cc_socket);
fd_log_threadname ( buf );
}
CHECK_FCT_DO(fd_tls_rcvthr_core(cnx, ctx->strid ? ctx->session : cnx->cc_tls_para.session), /* continue */);
error:
CHECK_FCT_DO( fd_event_send( Target_Queue(cnx), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
......@@ -208,6 +220,7 @@ struct sr_store {
struct fd_list list; /* list of sr_data, ordered by key.size then key.data */
pthread_rwlock_t lock;
struct cnxctx *parent;
/* Add another list to chain in a global list to implement a garbage collector on sessions */
};
/* Saved master session data for resuming sessions */
......@@ -218,7 +231,7 @@ struct sr_data {
};
/* The level at which we debug session resuming */
#define SR_LEVEL FULL
#define SR_LEVEL (FULL + 1)
/* Initialize the store area for a connection */
static int store_init(struct cnxctx * conn)
......@@ -302,9 +315,9 @@ static int sr_store (void *dbf, gnutls_datum_t key, gnutls_datum_t data)
int ret = 0;
CHECK_PARAMS_DO( sto && key.data && data.data, return -1 );
TRACE_DEBUG_BUFFER(SR_LEVEL, "Session store [key ", key.data, key.size < 16 ? key.size : 16, "]");
CHECK_POSIX_DO( pthread_rwlock_wrlock(&sto->lock), return -1 );
TRACE_DEBUG_BUFFER(SR_LEVEL, "Session store [key ", key.data, key.size, "]");
li = find_or_next(sto, key, &match);
if (match) {
......@@ -312,8 +325,10 @@ static int sr_store (void *dbf, gnutls_datum_t key, gnutls_datum_t data)
/* Check the data is the same */
if ((data.size != sr->data.size) || memcmp(data.data, sr->data.data, data.size)) {
TRACE_DEBUG(INFO, "GnuTLS tried to store a session with same key and different data!");
TRACE_DEBUG(SR_LEVEL, "GnuTLS tried to store a session with same key and different data!");
ret = -1;
} else {
TRACE_DEBUG(SR_LEVEL, "GnuTLS tried to store a session with same key and same data, skipped.");
}
goto out;
}
......@@ -349,9 +364,9 @@ static int sr_remove (void *dbf, gnutls_datum_t key)
int ret = 0;
CHECK_PARAMS_DO( sto && key.data, return -1 );
TRACE_DEBUG_BUFFER(SR_LEVEL, "Session delete [key ", key.data, key.size < 16 ? key.size : 16, "]");
CHECK_POSIX_DO( pthread_rwlock_wrlock(&sto->lock), return -1 );
TRACE_DEBUG_BUFFER(SR_LEVEL, "Session delete [key ", key.data, key.size, "]");
li = find_or_next(sto, key, &match);
if (match) {
......@@ -381,9 +396,9 @@ static gnutls_datum_t sr_fetch (void *dbf, gnutls_datum_t key)
gnutls_datum_t error = { NULL, 0 };
CHECK_PARAMS_DO( sto && key.data, return error );
TRACE_DEBUG_BUFFER(SR_LEVEL, "Session fetch [key ", key.data, key.size < 16 ? key.size : 16, "]");
CHECK_POSIX_DO( pthread_rwlock_rdlock(&sto->lock), return error );
TRACE_DEBUG_BUFFER(SR_LEVEL, "Session fetch [key ", key.data, key.size, "]");
li = find_or_next(sto, key, &match);
if (match) {
......@@ -393,6 +408,7 @@ static gnutls_datum_t sr_fetch (void *dbf, gnutls_datum_t key)
memcpy(res.data, sr->data.data, res.size);
}
out:
TRACE_DEBUG(SR_LEVEL, "Fetched (%p, %d) from store %p", res.data, res.size, sto);
CHECK_POSIX_DO( pthread_rwlock_unlock(&sto->lock), return error);
return res;
}
......@@ -416,10 +432,24 @@ static void * handshake_resume_th(void * arg)
struct sctps_ctx * ctx = (struct sctps_ctx *) arg;
TRACE_ENTRY("%p", arg);
/* Set the thread name */
{
char buf[48];
snprintf(buf, sizeof(buf), "Handshake resume (%hu@%d)", ctx->strid, ctx->parent->cc_socket);
fd_log_threadname ( buf );
}
TRACE_DEBUG(FULL, "Starting TLS resumed handshake on stream %hu", ctx->strid);
CHECK_GNUTLS_DO( gnutls_handshake( ctx->session ), return NULL);
/* We can trace success of resuming handshake by using gnutls_session_is_resumed */
if (TRACE_BOOL(FULL)) {
int resumed = gnutls_session_is_resumed(ctx->session);
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 (full handshake) on stream %hu (conn: '%s')\n", ctx->strid, fd_cnx_getid(ctx->parent));
}
}
/* Finish */
return arg;
......@@ -466,7 +496,7 @@ int fd_sctps_init(struct cnxctx * conn)
}
/* Handshake other streams, after full handshake on the master session */
int fd_sctps_handshake_others(struct cnxctx * conn, char * priority)
int fd_sctps_handshake_others(struct cnxctx * conn, char * priority, void * alt_creds)
{
uint16_t i;
int errors = 0;
......@@ -486,7 +516,7 @@ int fd_sctps_handshake_others(struct cnxctx * conn, char * priority)
/* Initialize the session objects and start the handshake in a separate thread */
for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
/* Set credentials and priority */
CHECK_FCT( fd_tls_prepare(&conn->cc_sctps_data.array[i].session, conn->cc_tls_para.mode, priority) );
CHECK_FCT( fd_tls_prepare(&conn->cc_sctps_data.array[i].session, conn->cc_tls_para.mode, priority, alt_creds) );
/* For the client, copy data from master session; for the server, set session resuming pointers */
if (conn->cc_tls_para.mode == GNUTLS_CLIENT) {
......@@ -549,6 +579,26 @@ void fd_sctps_stopthreads(struct cnxctx * conn)
return;
}
static void * bye_th(void * arg)
{
struct sctps_ctx * ctx = (struct sctps_ctx *) arg;
TRACE_ENTRY("%p", arg);
/* Set the thread name */
{
char buf[48];
snprintf(buf, sizeof(buf), "gnutls_bye (%hu@%d)", ctx->strid, ctx->parent->cc_socket);
fd_log_threadname ( buf );
}
CHECK_GNUTLS_DO( gnutls_bye(ctx->session, GNUTLS_SHUT_RDWR), /* Continue */ );
/* Finish */
return arg;
}
/* Destroy a wrapper context */
void fd_sctps_destroy(struct cnxctx * conn)
{
......@@ -559,11 +609,14 @@ void fd_sctps_destroy(struct cnxctx * conn)
/* Terminate all receiving threads in case we did not do it yet */
fd_sctps_stopthreads(conn);
/* End all TLS sessions -- maybe we should do it in parallel ? */
for (i = 0; i < conn->cc_sctp_para.pairs; i++) {
CHECK_GNUTLS_DO( gnutls_bye(conn->cc_sctps_data.array[i].session, GNUTLS_SHUT_RDWR), /* Continue */ );
/* End all TLS sessions, in parallel */
for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
CHECK_POSIX_DO( pthread_create( &conn->cc_sctps_data.array[i].thr, NULL, bye_th, &conn->cc_sctps_data.array[i] ), break );
}
for (--i; i > 0; --i) {
CHECK_POSIX_DO( pthread_join( conn->cc_sctps_data.array[i].thr, NULL ), continue );
}
skip:
/* Now, stop the demux thread */
CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ );
......@@ -571,7 +624,8 @@ void fd_sctps_destroy(struct cnxctx * conn)
for (i = 0; i < conn->cc_sctp_para.pairs; i++) {
fd_event_destroy( &conn->cc_sctps_data.array[i].raw_recv, free );
free(conn->cc_sctps_data.array[i].partial.buf);
gnutls_deinit(conn->cc_sctps_data.array[i].session);
if (i > 0)
gnutls_deinit(conn->cc_sctps_data.array[i].session);
}
/* Free the array itself now */
......
......@@ -115,7 +115,7 @@ static void * client_sm(void * arg)
/* Handshake if we are a secure server port, or start clear otherwise */
if (s->secur) {
int ret = fd_cnx_handshake(c->conn, GNUTLS_SERVER, NULL);
int ret = fd_cnx_handshake(c->conn, GNUTLS_SERVER, NULL, NULL);
if (ret != 0) {
if (TRACE_BOOL(INFO)) {
fd_log_debug("TLS handshake failed for client '%s', connection aborted.\n", fd_cnx_getid(c->conn));
......@@ -152,7 +152,11 @@ static void * client_sm(void * arg)
{ fd_log_debug("Connection '%s', expecting CER, received something else, closing...\n", fd_cnx_getid(c->conn)); goto cleanup; } );
/* Finally, pass the information to the peers module which will handle it next */
CHECK_FCT_DO( fd_peer_handle_newCER( &msg, &c->conn, s->secur ), goto fatal_error );
pthread_cleanup_push((void *)fd_cnx_destroy, c->conn);
pthread_cleanup_push((void *)fd_msg_free, msg);
CHECK_FCT_DO( fd_peer_handle_newCER( &msg, &c->conn ), goto cleanup );
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
/* The end, we cleanup the client structure */
cleanup:
......
......@@ -17,6 +17,7 @@ SET(TEST_LIST
testfifo
testsess
testdisp
testcnx
)
#############################
......
This diff is collapsed.
......@@ -45,10 +45,11 @@
#include <pthread.h>
#include <errno.h>
#include <gcrypt.h>
/* Test timeout duration, unless -n is passed on the command line */
#ifndef TEST_TIMEOUT
#define TEST_TIMEOUT 5 /* 5 seconds */
#define TEST_TIMEOUT 30 /* in seconds */