]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Handle SSL_ERROR_WANT_WRITE on SSL_read for negotiation
authorRalph Dolmans <ralph@nlnetlabs.nl>
Wed, 15 Jul 2020 13:49:42 +0000 (15:49 +0200)
committerRalph Dolmans <ralph@nlnetlabs.nl>
Wed, 15 Jul 2020 13:49:42 +0000 (15:49 +0200)
- Close connection when receiving overly large frame

dnstap/dtstream.c
dnstap/dtstream.h

index 030b66eeed0d75a0505ca20eb0e9e0092598b32f..171fe1c122022c4fc63c736c1be6db7ab457b64b 100644 (file)
@@ -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;
index d93714baf9736eef13cef74f942f53633efa63c2..ede491f30d3ef4f4ff11a4d4db67062f068cde83 100644 (file)
@@ -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 */