From: Grigorii Demidov Date: Mon, 31 Dec 2018 13:30:44 +0000 (+0100) Subject: daemon/tls: in some cases rehandshake might be improperly handled, which may lead... X-Git-Tag: v3.2.1~9^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7d2ffa24e85a7ff553921c362591c962b4f11416;p=thirdparty%2Fknot-resolver.git daemon/tls: in some cases rehandshake might be improperly handled, which may lead to assertion; --- diff --git a/daemon/io.c b/daemon/io.c index 7bb19b040..f183d3471 100644 --- a/daemon/io.c +++ b/daemon/io.c @@ -235,7 +235,17 @@ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf) /* buf->base points to start of the tls receive buffer. Decode data free space in session wire buffer. */ consumed = tls_process_input_data(s, (const uint8_t *)buf->base, nread); - if (consumed <= 0) { + if (consumed < 0) { + if (kr_verbose_status) { + struct sockaddr *peer = session_get_peer(s); + char *peer_str = kr_straddr(peer); + kr_log_verbose("[io] => connection to '%s': " + "error processing TLS data, close\n", + peer_str ? peer_str : ""); + } + worker_end_tcp(s); + return; + } else if (consumed == 0) { return; } data = session_wirebuf_get_free_start(s); diff --git a/daemon/tls.c b/daemon/tls.c index 02af3a156..508bcf854 100644 --- a/daemon/tls.c +++ b/daemon/tls.c @@ -493,16 +493,21 @@ ssize_t tls_process_input_data(struct session *s, const uint8_t *buf, ssize_t nr kr_log_verbose("[%s] TLS rehandshake with %s has started\n", logstring, kr_straddr(peer)); tls_set_hs_state(tls_p, TLS_HS_IN_PROGRESS); + int err = kr_ok(); while (tls_p->handshake_state <= TLS_HS_IN_PROGRESS) { - int err = tls_handshake(tls_p, tls_p->handshake_cb); + err = tls_handshake(tls_p, tls_p->handshake_cb); if (err == kr_error(EAGAIN)) { break; } else if (err != kr_ok()) { return err; } } - /* Wait for more data */ - break; + if (err == kr_error(EAGAIN)) { + /* pull function is out of data */ + break; + } + /* There are can be data available, check it. */ + continue; } else if (count < 0) { kr_log_verbose("[%s] gnutls_record_recv failed: %s (%zd)\n", logstring, gnutls_strerror_name(count), count); @@ -514,8 +519,21 @@ ssize_t tls_process_input_data(struct session *s, const uint8_t *buf, ssize_t nr wire_buf += count; wire_buf_size -= count; submitted += count; + if (wire_buf_size == 0 && tls_p->consumed != tls_p->nread) { + /* session buffer is full + * whereas not all the data were consumed */ + return kr_error(ENOSPC); + } + } + /* Here all data must be consumed. */ + if (tls_p->consumed != tls_p->nread) { + /* Something went wrong, better return error. + * This is most probably due to gnutls_record_recv() did not + * consume all available network data by calling kres_gnutls_pull(). + * TODO assess the need for buffering of data amount. + */ + return kr_error(ENOSPC); } - assert(tls_p->consumed == tls_p->nread); return submitted; } diff --git a/daemon/tls.h b/daemon/tls.h index e57799c5c..2eb776c39 100644 --- a/daemon/tls.h +++ b/daemon/tls.h @@ -94,7 +94,7 @@ struct tls_common_ctx { const uint8_t *buf; ssize_t nread; ssize_t consumed; - uint8_t recv_buf[8192]; + uint8_t recv_buf[16384]; tls_handshake_cb handshake_cb; struct worker_ctx *worker; size_t write_queue_size;