From: Ralph Dolmans Date: Wed, 15 Jul 2020 13:49:42 +0000 (+0200) Subject: - Handle SSL_ERROR_WANT_WRITE on SSL_read for negotiation X-Git-Tag: release-1.11.0~14^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=db3ac2335cc5d2de1e6c8f73626cb65ef18b4d2d;p=thirdparty%2Funbound.git - Handle SSL_ERROR_WANT_WRITE on SSL_read for negotiation - Close connection when receiving overly large frame --- diff --git a/dnstap/dtstream.c b/dnstap/dtstream.c index 030b66eee..171fe1c12 100644 --- a/dnstap/dtstream.c +++ b/dnstap/dtstream.c @@ -94,6 +94,8 @@ static int dtio_control_start_send(struct dt_io_thread* dtio); #ifdef HAVE_SSL /** enable briefly waiting for a read event, for SSL negotiation */ static int dtio_enable_brief_read(struct dt_io_thread* dtio); +/** enable briefly waiting for a write event, for SSL negotiation */ +static int dtio_enable_brief_write(struct dt_io_thread* dtio); #endif struct dt_msg_queue* @@ -945,7 +947,7 @@ static int ssl_read_bytes(struct dt_io_thread* dtio, void* buf, size_t len) /* continue later */ return -1; } else if(want == SSL_ERROR_WANT_WRITE) { - (void)dtio_add_output_event_write(dtio); + (void)dtio_enable_brief_write(dtio); return -1; } else if(want == SSL_ERROR_SYSCALL) { #ifdef ECONNRESET @@ -1036,9 +1038,9 @@ static int dtio_read_accept_frame(struct dt_io_thread* dtio) dtio->read_frame.frame_len = ntohl(dtio->read_frame.frame_len); if(dtio->read_frame.frame_len > DTIO_RECV_FRAME_MAX_LEN) { verbose(VERB_OPS, "dnstap: received frame exceeds max " - "length, capped to %d bytes", + "length of %d bytes, closing connection", DTIO_RECV_FRAME_MAX_LEN); - dtio->read_frame.frame_len = DTIO_RECV_FRAME_MAX_LEN; + goto close_connection; } dtio->read_frame.buf = calloc(1, dtio->read_frame.frame_len); dtio->read_frame.buf_cap = dtio->read_frame.frame_len; @@ -1207,6 +1209,24 @@ static int dtio_disable_brief_read(struct dt_io_thread* dtio) } #endif /* HAVE_SSL */ +#ifdef HAVE_SSL +/** enable the brief write condition */ +static int dtio_enable_brief_write(struct dt_io_thread* dtio) +{ + dtio->ssl_brief_write = 1; + return dtio_add_output_event_write(dtio); +} +#endif /* HAVE_SSL */ + +#ifdef HAVE_SSL +/** disable the brief write condition */ +static int dtio_disable_brief_write(struct dt_io_thread* dtio) +{ + dtio->ssl_brief_write = 0; + return dtio_add_output_event_read(dtio); +} +#endif /* HAVE_SSL */ + #ifdef HAVE_SSL /** check peer verification after ssl handshake connection, false if closed*/ static int dtio_ssl_check_peer(struct dt_io_thread* dtio) @@ -1380,7 +1400,9 @@ void dtio_output_cb(int ATTR_UNUSED(fd), short bits, void* arg) } #endif - if((bits&UB_EV_READ)) { + if((bits&UB_EV_READ || dtio->ssl_brief_write)) { + if(dtio->ssl_brief_write) + (void)dtio_disable_brief_write(dtio); if(dtio->ready_frame_sent && !dtio->accept_frame_received) { if(dtio_read_accept_frame(dtio) <= 0) return; diff --git a/dnstap/dtstream.h b/dnstap/dtstream.h index d93714baf..ede491f30 100644 --- a/dnstap/dtstream.h +++ b/dnstap/dtstream.h @@ -151,6 +151,9 @@ struct dt_io_thread { * This happens during negotiation, we then do not want to write, * but wait for a read event. */ int ssl_brief_read; + /** true if SSL_read is waiting for a write event. Set back to 0 after + * single write event is handled. */ + int ssl_brief_write; /** the buffer that currently getting written, or NULL if no * (partial) message written now */