make channel_output_poll() return a flag indicating whether channel
authordjm <djm@openbsd.org>
Mon, 4 Sep 2023 00:01:46 +0000 (00:01 +0000)
committerdjm <djm@openbsd.org>
Mon, 4 Sep 2023 00:01:46 +0000 (00:01 +0000)
data was enqueued. Will be used to improve keystroke timing
obfuscation. Problem spotted by / tested by naddy@

usr.bin/ssh/channels.c
usr.bin/ssh/channels.h

index 7c43bf3..1b310e3 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.c,v 1.432 2023/07/04 03:59:21 dlg Exp $ */
+/* $OpenBSD: channels.c,v 1.433 2023/09/04 00:01:46 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -2848,8 +2848,9 @@ channel_after_poll(struct ssh *ssh, struct pollfd *pfd, u_int npfd)
 
 /*
  * Enqueue data for channels with open or draining c->input.
+ * Returns non-zero if a packet was enqueued.
  */
-static void
+static int
 channel_output_poll_input_open(struct ssh *ssh, Channel *c)
 {
        size_t len, plen;
@@ -2872,7 +2873,7 @@ channel_output_poll_input_open(struct ssh *ssh, Channel *c)
                        else
                                chan_ibuf_empty(ssh, c);
                }
-               return;
+               return 0;
        }
 
        if (!c->have_remote_id)
@@ -2889,7 +2890,7 @@ channel_output_poll_input_open(struct ssh *ssh, Channel *c)
                 */
                if (plen > c->remote_window || plen > c->remote_maxpacket) {
                        debug("channel %d: datagram too big", c->self);
-                       return;
+                       return 0;
                }
                /* Enqueue it */
                if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 ||
@@ -2898,7 +2899,7 @@ channel_output_poll_input_open(struct ssh *ssh, Channel *c)
                    (r = sshpkt_send(ssh)) != 0)
                        fatal_fr(r, "channel %i: send datagram", c->self);
                c->remote_window -= plen;
-               return;
+               return 1;
        }
 
        /* Enqueue packet for buffered data. */
@@ -2907,7 +2908,7 @@ channel_output_poll_input_open(struct ssh *ssh, Channel *c)
        if (len > c->remote_maxpacket)
                len = c->remote_maxpacket;
        if (len == 0)
-               return;
+               return 0;
        if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 ||
            (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
            (r = sshpkt_put_string(ssh, sshbuf_ptr(c->input), len)) != 0 ||
@@ -2916,19 +2917,21 @@ channel_output_poll_input_open(struct ssh *ssh, Channel *c)
        if ((r = sshbuf_consume(c->input, len)) != 0)
                fatal_fr(r, "channel %i: consume", c->self);
        c->remote_window -= len;
+       return 1;
 }
 
 /*
  * Enqueue data for channels with open c->extended in read mode.
+ * Returns non-zero if a packet was enqueued.
  */
-static void
+static int
 channel_output_poll_extended_read(struct ssh *ssh, Channel *c)
 {
        size_t len;
        int r;
 
        if ((len = sshbuf_len(c->extended)) == 0)
-               return;
+               return 0;
 
        debug2("channel %d: rwin %u elen %zu euse %d", c->self,
            c->remote_window, sshbuf_len(c->extended), c->extended_usage);
@@ -2937,7 +2940,7 @@ channel_output_poll_extended_read(struct ssh *ssh, Channel *c)
        if (len > c->remote_maxpacket)
                len = c->remote_maxpacket;
        if (len == 0)
-               return;
+               return 0;
        if (!c->have_remote_id)
                fatal_f("channel %d: no remote id", c->self);
        if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA)) != 0 ||
@@ -2950,15 +2953,20 @@ channel_output_poll_extended_read(struct ssh *ssh, Channel *c)
                fatal_fr(r, "channel %i: consume", c->self);
        c->remote_window -= len;
        debug2("channel %d: sent ext data %zu", c->self, len);
+       return 1;
 }
 
-/* If there is data to send to the connection, enqueue some of it now. */
-void
+/*
+ * If there is data to send to the connection, enqueue some of it now.
+ * Returns non-zero if data was enqueued.
+ */
+int
 channel_output_poll(struct ssh *ssh)
 {
        struct ssh_channels *sc = ssh->chanctxt;
        Channel *c;
        u_int i;
+       int ret = 0;
 
        for (i = 0; i < sc->channels_alloc; i++) {
                c = sc->channels[i];
@@ -2981,12 +2989,13 @@ channel_output_poll(struct ssh *ssh)
                /* Get the amount of buffered data for this channel. */
                if (c->istate == CHAN_INPUT_OPEN ||
                    c->istate == CHAN_INPUT_WAIT_DRAIN)
-                       channel_output_poll_input_open(ssh, c);
+                       ret |= channel_output_poll_input_open(ssh, c);
                /* Send extended data, i.e. stderr */
                if (!(c->flags & CHAN_EOF_SENT) &&
                    c->extended_usage == CHAN_EXTENDED_READ)
-                       channel_output_poll_extended_read(ssh, c);
+                       ret |= channel_output_poll_extended_read(ssh, c);
        }
+       return ret;
 }
 
 /* -- mux proxy support  */
index 36820d3..7cfba92 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.h,v 1.151 2023/07/04 03:59:21 dlg Exp $ */
+/* $OpenBSD: channels.h,v 1.152 2023/09/04 00:01:46 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -332,7 +332,7 @@ struct timespec;
 void    channel_prepare_poll(struct ssh *, struct pollfd **,
            u_int *, u_int *, u_int, struct timespec *);
 void    channel_after_poll(struct ssh *, struct pollfd *, u_int);
-void     channel_output_poll(struct ssh *);
+int     channel_output_poll(struct ssh *);
 
 int      channel_not_very_much_buffered_data(struct ssh *);
 void     channel_close_all(struct ssh *);