# HG changeset patch # User Thomas Klausner # Date 1582022317 -3600 # Node ID 89cbb08d3189edecd5dcc721ef6c9295c060fef4 # Parent a51f71694121e87bc9f9702b0ad0e3358a4803aa Remove trailing whitespace. diff -r a51f71694121 -r 89cbb08d3189 libfdcore/cnxctx.c --- a/libfdcore/cnxctx.c Tue Feb 18 20:58:20 2020 +1100 +++ b/libfdcore/cnxctx.c Tue Feb 18 11:38:37 2020 +0100 @@ -176,7 +176,7 @@ } else { cnx->cc_family = AF_INET6; /* can create socket for both IP and IPv6 */ } - + /* Create the socket */ CHECK_FCT_DO( fd_sctp_create_bind_server( &cnx->cc_socket, cnx->cc_family, ep_list, port ), goto error ); @@ -226,41 +226,41 @@ TRACE_ENTRY("%p", serv); CHECK_PARAMS_DO(serv, return NULL); - + /* Accept the new connection -- this is blocking until new client enters or until cancellation */ CHECK_SYS_DO( cli_sock = accept(serv->cc_socket, (sSA *)&ss, &ss_len), return NULL ); - + CHECK_MALLOC_DO( cli = fd_cnx_init(1), { shutdown(cli_sock, SHUT_RDWR); close(cli_sock); return NULL; } ); cli->cc_socket = cli_sock; cli->cc_family = serv->cc_family; cli->cc_proto = serv->cc_proto; - + /* Set the timeout */ fd_cnx_s_setto(cli->cc_socket); - + /* Generate the name for the connection object */ { char addrbuf[INET6_ADDRSTRLEN]; char portbuf[10]; int rc; - + rc = getnameinfo((sSA *)&ss, ss_len, addrbuf, sizeof(addrbuf), portbuf, sizeof(portbuf), NI_NUMERICHOST | NI_NUMERICSERV); if (rc) { snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc)); portbuf[0] = '\0'; } - + /* Numeric values for debug... */ - snprintf(cli->cc_id, sizeof(cli->cc_id), CC_ID_HDR "%s from [%s]:%s (%d<-%d)", + snprintf(cli->cc_id, sizeof(cli->cc_id), CC_ID_HDR "%s from [%s]:%s (%d<-%d)", IPPROTO_NAME(cli->cc_proto), addrbuf, portbuf, serv->cc_socket, cli->cc_socket); - - + + /* ...Name for log messages */ rc = getnameinfo((sSA *)&ss, ss_len, cli->cc_remid, sizeof(cli->cc_remid), NULL, 0, 0); if (rc) snprintf(cli->cc_remid, sizeof(cli->cc_remid), "[err:%s]", gai_strerror(rc)); } - + LOG_D("Incoming connection: '%s' <- '%s' {%s}", fd_cnx_getid(serv), cli->cc_remid, cli->cc_id); #ifndef DISABLE_SCTP @@ -272,7 +272,7 @@ cli->cc_sctp_para.pairs = cli->cc_sctp_para.str_out; else cli->cc_sctp_para.pairs = cli->cc_sctp_para.str_in; - + LOG_A( "%s : client '%s' (SCTP:%d, %d/%d streams)", fd_cnx_getid(serv), fd_cnx_getid(cli), cli->cc_socket, cli->cc_sctp_para.str_in, cli->cc_sctp_para.str_out); } #endif /* DISABLE_SCTP */ @@ -286,14 +286,14 @@ int sock = 0; struct cnxctx * cnx = NULL; char sa_buf[sSA_DUMP_STRLEN]; - + TRACE_ENTRY("%p %d", sa, addrlen); CHECK_PARAMS_DO( sa && addrlen, return NULL ); - + fd_sa_sdump_numeric(sa_buf, sa); - + LOG_D("Connecting to TCP %s...", sa_buf); - + /* Create the socket and connect, which can take some time and/or fail */ { int ret = fd_tcp_client( &sock, sa, addrlen ); @@ -302,31 +302,31 @@ return NULL; } } - + /* Once the socket is created successfuly, prepare the remaining of the cnx */ CHECK_MALLOC_DO( cnx = fd_cnx_init(1), { shutdown(sock, SHUT_RDWR); close(sock); return NULL; } ); - + cnx->cc_socket = sock; cnx->cc_family = sa->sa_family; cnx->cc_proto = IPPROTO_TCP; - + /* Set the timeout */ fd_cnx_s_setto(cnx->cc_socket); - + /* Generate the names for the object */ { int rc; - + snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "TCP,#%d->%s", cnx->cc_socket, sa_buf); - + /* ...Name for log messages */ rc = getnameinfo(sa, addrlen, cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0); if (rc) snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc)); } - + LOG_A("TCP connection to %s succeed (socket:%d).", sa_buf, sock); - + return cnx; } @@ -343,14 +343,14 @@ struct cnxctx * cnx = NULL; char sa_buf[sSA_DUMP_STRLEN]; sSS primary; - + TRACE_ENTRY("%p", list); CHECK_PARAMS_DO( list && !FD_IS_LIST_EMPTY(list), return NULL ); - + fd_sa_sdump_numeric(sa_buf, &((struct fd_endpoint *)(list->next))->sa); - + LOG_D("Connecting to SCTP %s:%hu...", sa_buf, port); - + { int ret = fd_sctp_client( &sock, no_ip6, port, list ); if (ret != 0) { @@ -358,40 +358,40 @@ return NULL; } } - + /* Once the socket is created successfuly, prepare the remaining of the cnx */ CHECK_MALLOC_DO( cnx = fd_cnx_init(1), { shutdown(sock, SHUT_RDWR); close(sock); return NULL; } ); - + cnx->cc_socket = sock; cnx->cc_family = no_ip6 ? AF_INET : AF_INET6; cnx->cc_proto = IPPROTO_SCTP; - + /* Set the timeout */ fd_cnx_s_setto(cnx->cc_socket); - + /* Retrieve the number of streams and primary address */ CHECK_FCT_DO( fd_sctp_get_str_info( sock, &cnx->cc_sctp_para.str_in, &cnx->cc_sctp_para.str_out, &primary ), goto error ); if (cnx->cc_sctp_para.str_out < cnx->cc_sctp_para.str_in) cnx->cc_sctp_para.pairs = cnx->cc_sctp_para.str_out; else cnx->cc_sctp_para.pairs = cnx->cc_sctp_para.str_in; - + fd_sa_sdump_numeric(sa_buf, (sSA *)&primary); - + /* Generate the names for the object */ { int rc; - + snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "SCTP,#%d->%s", cnx->cc_socket, sa_buf); - + /* ...Name for log messages */ rc = getnameinfo((sSA *)&primary, sSAlen(&primary), cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0); if (rc) snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc)); } - + LOG_A("SCTP connection to %s succeed (socket:%d, %d/%d streams).", sa_buf, sock, cnx->cc_sctp_para.str_in, cnx->cc_sctp_para.str_out); - + return cnx; error: @@ -444,17 +444,17 @@ conn->cc_id[1] = 'C'; else conn->cc_id[1] = '-'; - + if (conn->cc_state & CC_STATUS_ERROR) conn->cc_id[2] = 'E'; else conn->cc_id[2] = '-'; - + if (conn->cc_state & CC_STATUS_SIGNALED) conn->cc_id[3] = 'S'; else conn->cc_id[3] = '-'; - + if (conn->cc_state & CC_STATUS_TLS) conn->cc_id[4] = 'T'; else @@ -508,7 +508,7 @@ { TRACE_ENTRY("%p %p", conn, eps); CHECK_PARAMS(conn && eps); - + /* Check we have a full connection object, not a listening socket (with no remote) */ CHECK_PARAMS( conn->cc_incoming ); @@ -546,16 +546,16 @@ static int fd_cnx_may_dtls(struct cnxctx * conn); /* Get a short string representing the connection */ -int fd_cnx_proto_info(struct cnxctx * conn, char * buf, size_t len) +int fd_cnx_proto_info(struct cnxctx * conn, char * buf, size_t len) { CHECK_PARAMS( conn ); - + if (fd_cnx_teststate(conn, CC_STATUS_TLS)) { snprintf(buf, len, "%s,%s,soc#%d", IPPROTO_NAME(conn->cc_proto), fd_cnx_may_dtls(conn) ? "DTLS" : "TLS", conn->cc_socket); } else { snprintf(buf, len, "%s,soc#%d", IPPROTO_NAME(conn->cc_proto), conn->cc_socket); } - + return 0; } @@ -563,27 +563,27 @@ int fd_cnx_get_local_eps(struct fd_list * list) { struct ifaddrs *iflist, *cur; - + CHECK_SYS(getifaddrs(&iflist)); - + for (cur = iflist; cur != NULL; cur = cur->ifa_next) { if (cur->ifa_flags & IFF_LOOPBACK) continue; - + if (cur->ifa_addr == NULL) /* may happen with ppp interfaces */ continue; - + if (fd_g_config->cnf_flags.no_ip4 && (cur->ifa_addr->sa_family == AF_INET)) continue; - + if (fd_g_config->cnf_flags.no_ip6 && (cur->ifa_addr->sa_family == AF_INET6)) continue; - + CHECK_FCT(fd_ep_add_merge( list, cur->ifa_addr, sSAlen(cur->ifa_addr), EP_FL_LL )); } - + freeifaddrs(iflist); - + return 0; } @@ -597,31 +597,31 @@ { TRACE_ENTRY("%p", conn); CHECK_PARAMS_DO( conn, goto fatal ); - + TRACE_DEBUG(FULL, "Error flag set for socket %d (%s, %s)", conn->cc_socket, conn->cc_id, conn->cc_remid); /* Mark the error */ fd_cnx_addstate(conn, CC_STATUS_ERROR); - + /* Report the error if not reported yet, and not closing */ if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING | CC_STATUS_SIGNALED )) { TRACE_DEBUG(FULL, "Sending FDEVP_CNX_ERROR event"); CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_ERROR, 0, NULL), goto fatal); fd_cnx_addstate(conn, CC_STATUS_SIGNALED); } - + return; fatal: /* An unrecoverable error occurred, stop the daemon */ ASSERT(0); - CHECK_FCT_DO(fd_core_shutdown(), ); + CHECK_FCT_DO(fd_core_shutdown(), ); } /* Set the timeout option on the socket */ -void fd_cnx_s_setto(int sock) +void fd_cnx_s_setto(int sock) { struct timeval tv; - + /* Set a timeout on the socket so that in any case we are not stuck waiting for something */ memset(&tv, 0, sizeof(tv)); tv.tv_usec = 100000L; /* 100ms, to react quickly to head-of-the-line blocking. */ @@ -636,15 +636,15 @@ { fd_set rfds; struct timeval tv; - + FD_ZERO (&rfds); FD_SET (conn->cc_socket, &rfds); - + tv.tv_sec = ms / 1000; tv.tv_usec = (ms * 1000) % 1000000; - + return select (conn->cc_socket + 1, &rfds, NULL, NULL, &tv); -} +} #endif /* GNUTLS_VERSION_300 */ /* A recv-like function, taking a cnxctx object instead of socket as entry. We use it to quickly react to timeouts without traversing GNUTLS wrapper each time */ @@ -664,13 +664,13 @@ goto again; } } - + /* Mark the error */ if (ret <= 0) { CHECK_SYS_DO(ret, /* continue, this is only used to log the error here */); fd_cnx_markerror(conn); } - + return ret; } @@ -686,7 +686,7 @@ if ((ret < 0) && ((errno == EAGAIN) || (errno == EINTR))) { ret = -errno; pthread_testcancel(); - + /* Check how much time we were blocked for this sending. */ CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), return -1 ); if ( ((now.tv_sec - ts.tv_sec) * 1000 + ((now.tv_nsec - ts.tv_nsec) / 1000000L)) > MAX_HOTL_BLOCKING_TIME) { @@ -694,17 +694,17 @@ } else if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING )) { goto again; /* don't care, just ignore */ } - + /* propagate the error */ errno = -ret; ret = -1; CHECK_SYS_DO(ret, /* continue */); } - + /* Mark the error */ if (ret <= 0) fd_cnx_markerror(conn); - + return ret; } @@ -730,7 +730,7 @@ struct fd_msg_pmdl * fd_msg_pmdl_get_inbuf(uint8_t * buf, size_t datalen) { return (struct fd_msg_pmdl *)(buf + PMDL_PADDED(datalen)); -} +} static int fd_cnx_init_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl) { @@ -743,7 +743,7 @@ static uint8_t * fd_cnx_alloc_msg_buffer(size_t expected_len, struct fd_msg_pmdl ** pmdl) { uint8_t * ret = NULL; - + CHECK_MALLOC_DO( ret = malloc( fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL ); CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} ); return ret; @@ -753,14 +753,14 @@ static uint8_t * fd_cnx_realloc_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl) { uint8_t * ret = NULL; - + CHECK_MALLOC_DO( ret = realloc( buffer, fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL ); CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} ); return ret; } #endif /* DISABLE_SCTP */ -static void free_rcvdata(void * arg) +static void free_rcvdata(void * arg) { struct fd_cnx_rcvdata * data = arg; struct fd_msg_pmdl * pmdl = fd_msg_pmdl_get_inbuf(data->buffer, data->length); @@ -772,21 +772,21 @@ 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( ! fd_cnx_teststate(conn, CC_STATUS_TLS ) ); ASSERT( fd_cnx_target_queue(conn) ); - + /* Receive from a TCP connection: we have to rebuild the message boundaries */ do { uint8_t header[4]; @@ -802,7 +802,7 @@ } received += ret; - + if (header[0] != DIAMETER_VERSION) break; /* No need to wait for 4 bytes in this case */ } while (received < sizeof(header)); @@ -833,22 +833,22 @@ } received += ret; } - + fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl); - + /* We have received a complete message, pass it to the daemon */ - CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer), - { + CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer), + { free_rcvdata(&rcv_data); - goto fatal; + goto fatal; } ); - + } while (conn->cc_loop); - + out: - TRACE_DEBUG(FULL, "Thread terminated"); + TRACE_DEBUG(FULL, "Thread terminated"); return NULL; - + fatal: /* An unrecoverable error occurred, stop the daemon */ CHECK_FCT_DO(fd_core_shutdown(), ); @@ -862,21 +862,21 @@ struct cnxctx * conn = arg; struct fd_cnx_rcvdata rcv_data; int event; - + TRACE_ENTRY("%p", arg); CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto fatal); - + /* 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( ! fd_cnx_teststate(conn, CC_STATUS_TLS ) ); ASSERT( fd_cnx_target_queue(conn) ); - + do { struct fd_msg_pmdl *pmdl=NULL; CHECK_FCT_DO( fd_sctp_recvmeta(conn, NULL, &rcv_data.buffer, &rcv_data.length, &event), goto fatal ); @@ -884,7 +884,7 @@ fd_cnx_markerror(conn); goto out; } - + if (event == FDEVP_CNX_SHUTDOWN) { /* Just ignore the notification for now, we will get another error later anyway */ continue; @@ -895,11 +895,11 @@ fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl); } CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), event, rcv_data.length, rcv_data.buffer), goto fatal ); - + } while (conn->cc_loop || (event != FDEVP_CNX_MSG_RECV)); - + out: - TRACE_DEBUG(FULL, "Thread terminated"); + TRACE_DEBUG(FULL, "Thread terminated"); return NULL; fatal: @@ -913,15 +913,15 @@ int fd_cnx_start_clear(struct cnxctx * conn, int loop) { TRACE_ENTRY("%p %i", conn, loop); - + CHECK_PARAMS( conn && fd_cnx_target_queue(conn) && (!fd_cnx_teststate(conn, CC_STATUS_TLS)) && (!conn->cc_loop)); - + /* Release resources in case of a previous call was already made */ CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */); - + /* Save the loop request */ conn->cc_loop = loop; - + switch (conn->cc_proto) { case IPPROTO_TCP: /* Start the tcp_notls thread */ @@ -938,7 +938,7 @@ ASSERT(0); return ENOTSUP; } - + return 0; } @@ -949,11 +949,11 @@ static ssize_t fd_tls_recv_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz) { ssize_t ret; -again: - CHECK_GNUTLS_DO( ret = gnutls_record_recv(session, data, sz), +again: + CHECK_GNUTLS_DO( ret = gnutls_record_recv(session, data, sz), { switch (ret) { - case GNUTLS_E_REHANDSHAKE: + case GNUTLS_E_REHANDSHAKE: if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING)) { CHECK_GNUTLS_DO( ret = gnutls_handshake(session), { @@ -975,7 +975,7 @@ /* The connection is closed */ TRACE_DEBUG(FULL, "Got 0 size while reading the socket, probably connection closed..."); break; - + default: if (gnutls_error_is_fatal (ret) == 0) { LOG_N("Ignoring non-fatal GNU TLS error: %s", gnutls_strerror (ret)); @@ -984,11 +984,11 @@ LOG_E("Fatal GNUTLS error: %s", gnutls_strerror (ret)); } } ); - + if (ret == 0) CHECK_GNUTLS_DO( gnutls_bye(session, GNUTLS_SHUT_RDWR), ); - -end: + +end: if (ret <= 0) fd_cnx_markerror(conn); return ret; @@ -1000,12 +1000,12 @@ ssize_t ret; struct timespec ts, now; CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), return -1 ); -again: +again: CHECK_GNUTLS_DO( ret = gnutls_record_send(session, data, sz), { pthread_testcancel(); switch (ret) { - case GNUTLS_E_REHANDSHAKE: + case GNUTLS_E_REHANDSHAKE: if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING)) { CHECK_GNUTLS_DO( ret = gnutls_handshake(session), { @@ -1034,10 +1034,10 @@ LOG_E("Fatal GNUTLS error: %s", gnutls_strerror (ret)); } } ); -end: +end: if (ret <= 0) fd_cnx_markerror(conn); - + return ret; } @@ -1045,8 +1045,8 @@ /* The function that receives TLS data and re-builds a Diameter message -- it exits only on error or cancelation */ /* For the case of DTLS, since we are not using SCTP_UNORDERED, the messages over a single stream are ordered. Furthermore, as long as messages are shorter than the MTU [2^14 = 16384 bytes], they are delivered in a single - record, as far as I understand. - For larger messages, however, it is possible that pieces of messages coming from different streams can get interleaved. + record, as far as I understand. + For larger messages, however, it is possible that pieces of messages coming from different streams can get interleaved. As a result, we do not use the following function for DTLS reception, because we use the sequence number to rebuild the messages. */ int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session) @@ -1095,19 +1095,19 @@ } received += ret; } - + fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl); - + /* We have received a complete message, pass it to the daemon */ - CHECK_FCT_DO( ret = fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer), - { + CHECK_FCT_DO( ret = fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer), + { free_rcvdata(&rcv_data); CHECK_FCT_DO(fd_core_shutdown(), ); - return ret; + return ret; } ); - + } while (1); - + out: return (ret == 0) ? 0 : ENOTCONN; } @@ -1116,24 +1116,24 @@ static void * rcvthr_tls_single(void * arg) { struct cnxctx * conn = arg; - + TRACE_ENTRY("%p", arg); CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), return NULL ); - + /* Set the thread name */ { char buf[48]; snprintf(buf, sizeof(buf), "Receiver (%d) TLS/single stream", conn->cc_socket); fd_log_threadname ( buf ); } - + ASSERT( fd_cnx_teststate(conn, CC_STATUS_TLS) ); ASSERT( fd_cnx_target_queue(conn) ); - /* The next function only returns when there is an error on the socket */ + /* The next function only returns when there is an error on the socket */ CHECK_FCT_DO(fd_tls_rcvthr_core(conn, conn->cc_tls_para.session), /* continue */); - TRACE_DEBUG(FULL, "Thread terminated"); + TRACE_DEBUG(FULL, "Thread terminated"); return NULL; } @@ -1151,7 +1151,7 @@ /* Set the algorithm suite */ if (priority) { const char * errorpos; - CHECK_GNUTLS_DO( gnutls_priority_set_direct( *session, priority, &errorpos ), + CHECK_GNUTLS_DO( gnutls_priority_set_direct( *session, priority, &errorpos ), { TRACE_DEBUG(INFO, "Error in priority string '%s' at position: '%s'", priority, errorpos); return EINVAL; } ); } else { CHECK_GNUTLS_DO( gnutls_priority_set( *session, fd_g_config->cnf_sec_data.prio_cache ), return EINVAL ); @@ -1164,7 +1164,7 @@ if (mode == GNUTLS_SERVER) { gnutls_certificate_server_set_request (*session, GNUTLS_CERT_REQUIRE); } - + return 0; } @@ -1179,17 +1179,17 @@ unsigned int cert_list_size; gnutls_x509_crt_t cert; time_t now; - + TRACE_ENTRY("%p %d", conn, verbose); CHECK_PARAMS(conn); - + /* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */ #ifdef DEBUG if (verbose) { const char *tmp; gnutls_kx_algorithm_t kx; gnutls_credentials_type_t cred; - + LOG_D("TLS Session information for connection '%s':", conn->cc_id); /* print the key exchange's algorithm name */ @@ -1229,7 +1229,7 @@ gnutls_dh_get_prime_bits (session)); } break; -#ifdef ENABLE_SRP +#ifdef ENABLE_SRP case GNUTLS_CRD_SRP: LOG_D("\t - SRP session with username %s", gnutls_srp_server_get_username (session)); @@ -1263,7 +1263,7 @@ LOG_D("\t - MAC: %s", tmp); } #endif /* DEBUG */ - + /* First, use built-in verification */ CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (session, >ret), return EINVAL ); if (gtret) { @@ -1280,33 +1280,33 @@ LOG_E(" - The certificate signature uses a weak algorithm."); return EINVAL; } - + /* Code from http://www.gnu.org/software/gnutls/manual/gnutls.html#Verifying-peer_0027s-certificate */ if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) { LOG_E("TLS: Remote peer did not present a certificate, other mechanisms are not supported yet. socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id); return EINVAL; } - + GNUTLS_TRACE( cert_list = gnutls_certificate_get_peers (session, &cert_list_size) ); if (cert_list == NULL) return EINVAL; - + now = time(NULL); - + #ifdef DEBUG char serial[40]; char dn[128]; size_t size; unsigned int algo, bits; time_t expiration_time, activation_time; - + LOG_D("TLS Certificate information for connection '%s' (%d certs provided):", conn->cc_id, cert_list_size); for (i = 0; i < cert_list_size; i++) { 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); - + LOG_A(" Certificate %d info:", i); GNUTLS_TRACE( expiration_time = gnutls_x509_crt_get_expiration_time (cert) ); @@ -1318,7 +1318,7 @@ /* Print the serial number of the certificate. */ size = sizeof (serial); gnutls_x509_crt_get_serial (cert, serial, &size); - + { int j; char buf[1024]; @@ -1354,24 +1354,24 @@ for (i = 0; i < cert_list_size; i++) { time_t deadline; - + 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); - + GNUTLS_TRACE( deadline = gnutls_x509_crt_get_expiration_time(cert) ); if ((deadline != (time_t)-1) && (deadline < now)) { LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id); LOG_E(" - The certificate %d in the chain is expired", i); ret = EINVAL; } - + GNUTLS_TRACE( deadline = gnutls_x509_crt_get_activation_time(cert) ); if ((deadline != (time_t)-1) && (deadline > now)) { LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id); LOG_E(" - The certificate %d in the chain is not yet activated", i); ret = EINVAL; } - + if ((i == 0) && (conn->cc_tls_para.cn)) { if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) { LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id); @@ -1379,7 +1379,7 @@ ret = EINVAL; } } - + GNUTLS_TRACE( gnutls_x509_crt_deinit (cert) ); } @@ -1400,10 +1400,10 @@ int hostname_verified = 0; TRACE_ENTRY("%p", session); - + /* get the associated connection */ conn = gnutls_session_get_ptr (session); - + /* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */ #ifdef DEBUG const char *tmp; @@ -1414,7 +1414,7 @@ dhe = ecdh = 0; LOG_A("TLS Session information for connection '%s':", conn->cc_id); - + /* print the key exchange's algorithm name */ GNUTLS_TRACE( kx = gnutls_kx_get (session) ); @@ -1474,7 +1474,7 @@ dhe = 1; else if (kx == GNUTLS_KX_ECDHE_RSA || kx == GNUTLS_KX_ECDHE_ECDSA) ecdh = 1; - + /* Now print some info on the remote certificate */ if (gnutls_certificate_type_get (session) == GNUTLS_CRT_X509) { gnutls_datum_t cinfo; @@ -1504,7 +1504,7 @@ LOG_D("\t\t%s", cinfo.data); gnutls_free (cinfo.data); } - + if (conn->cc_tls_para.cn) { if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) { LOG_E("\tTLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id); @@ -1512,7 +1512,7 @@ gnutls_x509_crt_deinit (cert); return GNUTLS_E_CERTIFICATE_ERROR; } - + } hostname_verified = 1; @@ -1535,7 +1535,7 @@ LOG_D("\t - Ephemeral DH using prime of %d bits", gnutls_dh_get_prime_bits (session)); - /* print the protocol's name (ie TLS 1.0) + /* print the protocol's name (ie TLS 1.0) */ tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session)); LOG_D("\t - Protocol: %s", tmp); @@ -1557,8 +1557,8 @@ */ tmp = gnutls_mac_get_name (gnutls_mac_get (session)); LOG_D("\t - MAC: %s", tmp); - -#endif /* DEBUG */ + +#endif /* DEBUG */ /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. @@ -1577,12 +1577,12 @@ if (status & GNUTLS_CERT_NOT_ACTIVATED) LOG_E(" - The certificate is not yet activated."); - } + } if (status & GNUTLS_CERT_INVALID) { return GNUTLS_E_CERTIFICATE_ERROR; } - + /* Up to here the process is the same for X.509 certificates and * OpenPGP keys. From now on X.509 certificates are assumed. This can * be easily extended to work with openpgp keys as well. @@ -1634,22 +1634,22 @@ int fd_cnx_handshake(struct cnxctx * conn, int mode, int algo, char * priority, void * alt_creds) { int dtls = 0; - + TRACE_ENTRY( "%p %d %d %p %p", conn, mode, algo, priority, alt_creds); CHECK_PARAMS( conn && (!fd_cnx_teststate(conn, CC_STATUS_TLS)) && ( (mode == GNUTLS_CLIENT) || (mode == GNUTLS_SERVER) ) && (!conn->cc_loop) ); /* Save the mode */ conn->cc_tls_para.mode = mode; conn->cc_tls_para.algo = algo; - + /* Cancel receiving thread if any -- it should already be terminated anyway, we just release the resources */ CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */); - + /* Once TLS handshake is done, we don't stop after the first message */ conn->cc_loop = 1; - + dtls = fd_cnx_may_dtls(conn); - + /* Prepare the master session credentials and priority */ CHECK_FCT( fd_tls_prepare(&conn->cc_tls_para.session, mode, dtls, priority, alt_creds) ); @@ -1682,32 +1682,32 @@ return ENOTSUP; } } - + /* 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_tls_para.session, (void *) conn); - + if ((conn->cc_tls_para.cn != NULL) && (mode == GNUTLS_CLIENT)) { /* this might allow virtual hosting on the remote peer */ CHECK_GNUTLS_DO( gnutls_server_name_set (conn->cc_tls_para.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_tls_para.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT)); #endif /* GNUTLS_VERSION_310 */ - + /* Mark the connection as protected from here, so that the gnutls credentials will be freed */ fd_cnx_addstate(conn, CC_STATUS_TLS); - + /* Handshake master session */ { int ret; - + CHECK_GNUTLS_DO( ret = gnutls_handshake(conn->cc_tls_para.session), { if (TRACE_BOOL(INFO)) { @@ -1719,15 +1719,15 @@ #ifndef GNUTLS_VERSION_300 /* Now verify the remote credentials are valid -- only simple tests here */ - CHECK_FCT_DO( fd_tls_verify_credentials(conn->cc_tls_para.session, conn, 1), - { + CHECK_FCT_DO( fd_tls_verify_credentials(conn->cc_tls_para.session, conn, 1), + { CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_RDWR), ); fd_cnx_markerror(conn); return EINVAL; }); #endif /* GNUTLS_VERSION_300 */ } - + /* Multi-stream TLS: handshake other streams as well */ if ((!dtls) && (conn->cc_sctp_para.pairs > 1)) { #ifndef DISABLE_SCTP @@ -1750,7 +1750,7 @@ return ENOTSUP; } } - + return 0; } @@ -1759,10 +1759,10 @@ { TRACE_ENTRY("%p %p %p", conn, cert_list, cert_list_size); CHECK_PARAMS( conn && fd_cnx_teststate(conn, CC_STATUS_TLS) && cert_list && cert_list_size ); - + /* This function only works for X.509 certificates. */ CHECK_PARAMS( gnutls_certificate_type_get (conn->cc_tls_para.session) == GNUTLS_CRT_X509 ); - + GNUTLS_TRACE( *cert_list = gnutls_certificate_get_peers (conn->cc_tls_para.session, cert_list_size) ); if (*cert_list == NULL) { TRACE_DEBUG(INFO, "No certificate was provided by remote peer / an error occurred."); @@ -1770,7 +1770,7 @@ } TRACE_DEBUG( FULL, "Saved certificate chain (%d certificates) in peer structure.", *cert_list_size); - + return 0; } @@ -1781,7 +1781,7 @@ int ev; size_t ev_sz; void * ev_data; - + TRACE_ENTRY("%p %p %p %p", conn, timeout, buf, len); CHECK_PARAMS(conn && (conn->cc_socket > 0) && buf && len); CHECK_PARAMS(conn->cc_rcvthr != (pthread_t)NULL); @@ -1794,27 +1794,27 @@ } else { CHECK_FCT( fd_event_get(conn->cc_incoming, &ev, &ev_sz, &ev_data) ); } - + switch (ev) { case FDEVP_CNX_MSG_RECV: /* We got one */ *len = ev_sz; *buf = ev_data; return 0; - + case FDEVP_PSM_TIMEOUT: TRACE_DEBUG(FULL, "Timeout event received"); return ETIMEDOUT; - + case FDEVP_CNX_EP_CHANGE: /* We ignore this event */ goto get_next; - + case FDEVP_CNX_ERROR: TRACE_DEBUG(FULL, "Received ERROR event on the connection"); return ENOTCONN; } - + TRACE_DEBUG(INFO, "Received unexpected event %d (%s)", ev, fd_pev_str(ev)); return EINVAL; } @@ -1835,12 +1835,12 @@ int ret; TRACE_ENTRY( "%p %p", conn, alt_fifo ); CHECK_PARAMS( conn && alt_fifo && conn->cc_incoming ); - + /* The magic function does it all */ CHECK_POSIX_DO( pthread_mutex_lock(&state_lock), { ASSERT(0); } ); CHECK_FCT_DO( ret = fd_fifo_move( conn->cc_incoming, alt_fifo, &conn->cc_alt ), ); CHECK_POSIX_DO( pthread_mutex_unlock(&state_lock), { ASSERT(0); } ); - + return ret; } @@ -1861,7 +1861,7 @@ } if (ret <= 0) return ENOTCONN; - + sent += ret; } while ( sent < len ); return 0; @@ -1871,16 +1871,16 @@ int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len) { TRACE_ENTRY("%p %p %zd", conn, buf, len); - + CHECK_PARAMS(conn && (conn->cc_socket > 0) && (! fd_cnx_teststate(conn, CC_STATUS_ERROR)) && buf && len); TRACE_DEBUG(FULL, "Sending %zdb %sdata on connection %s", len, fd_cnx_teststate(conn, CC_STATUS_TLS) ? "TLS-protected ":"", conn->cc_id); - + switch (conn->cc_proto) { case IPPROTO_TCP: CHECK_FCT( send_simple(conn, buf, len) ); break; - + #ifndef DISABLE_SCTP case IPPROTO_SCTP: { int dtls = fd_cnx_uses_dtls(conn); @@ -1892,14 +1892,14 @@ limit = conn->cc_sctp_para.pairs; else limit = conn->cc_sctp_para.str_out; - + if (limit > 1) { conn->cc_sctp_para.next += 1; conn->cc_sctp_para.next %= limit; stream = conn->cc_sctp_para.next; } } - + if (stream == 0) { /* We can use default function, it sends over stream #0 */ CHECK_FCT( send_simple(conn, buf, len) ); @@ -1908,7 +1908,7 @@ struct iovec iov; iov.iov_base = buf; iov.iov_len = len; - + CHECK_SYS_DO( fd_sctp_sendstrv(conn, stream, &iov, 1), { fd_cnx_markerror(conn); return ENOTCONN; } ); } else { /* push the data to the appropriate session */ @@ -1932,13 +1932,13 @@ } break; #endif /* DISABLE_SCTP */ - + default: TRACE_DEBUG(INFO, "Unknown protocol: %d", conn->cc_proto); ASSERT(0); return ENOTSUP; /* or EINVAL... */ } - + return 0; } @@ -1951,11 +1951,11 @@ void fd_cnx_destroy(struct cnxctx * conn) { TRACE_ENTRY("%p", conn); - + CHECK_PARAMS_DO(conn, return); - + fd_cnx_addstate(conn, CC_STATUS_CLOSING); - + /* Initiate shutdown of the TLS session(s): call gnutls_bye(WR), then read until error */ if (fd_cnx_teststate(conn, CC_STATUS_TLS)) { #ifndef DISABLE_SCTP @@ -1985,7 +1985,7 @@ GNUTLS_TRACE( gnutls_deinit(conn->cc_tls_para.session) ); conn->cc_tls_para.session = NULL; } - + /* Destroy the wrapper (also stops the demux thread) */ fd_sctp3436_destroy(conn); @@ -2007,7 +2007,7 @@ /* Cancel the receiver thread in case it did not already terminate */ CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ ); } - + /* Free the resources of the TLS session */ if (conn->cc_tls_para.session) { GNUTLS_TRACE( gnutls_deinit(conn->cc_tls_para.session) ); @@ -2017,25 +2017,25 @@ } #endif /* DISABLE_SCTP */ } - + /* Terminate the thread in case it is not done yet -- is there any such case left ?*/ CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ ); - + /* Shut the connection down */ if (conn->cc_socket > 0) { shutdown(conn->cc_socket, SHUT_RDWR); close(conn->cc_socket); conn->cc_socket = -1; } - + /* Empty and destroy FIFO list */ if (conn->cc_incoming) { fd_event_destroy( &conn->cc_incoming, free ); } - + /* Free the object */ free(conn); - + /* Done! */ return; }