Apply ConnectTimeout to multiplexing local socket connections. If the
authordtucker <dtucker@openbsd.org>
Fri, 4 Aug 2023 06:32:40 +0000 (06:32 +0000)
committerdtucker <dtucker@openbsd.org>
Fri, 4 Aug 2023 06:32:40 +0000 (06:32 +0000)
multiplex socket exists but the connection times out, ssh will fall back
to a direct connection the same way it would if the socket did not exist
at all.  ok djm@

usr.bin/ssh/misc.c
usr.bin/ssh/mux.c

index 3f5ed04..c49aa60 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.c,v 1.184 2023/07/19 14:02:27 djm Exp $ */
+/* $OpenBSD: misc.c,v 1.185 2023/08/04 06:32:40 dtucker Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2005-2020 Damien Miller.  All rights reserved.
@@ -273,15 +273,16 @@ waitfd(int fd, int *timeoutp, short events)
 {
        struct pollfd pfd;
        struct timeval t_start;
-       int oerrno, r;
+       int oerrno, r, have_timeout = (*timeoutp >= 0);
 
        pfd.fd = fd;
        pfd.events = events;
-       for (; *timeoutp >= 0;) {
+       for (; !have_timeout || *timeoutp >= 0;) {
                monotime_tv(&t_start);
                r = poll(&pfd, 1, *timeoutp);
                oerrno = errno;
-               ms_subtract_diff(&t_start, timeoutp);
+               if (have_timeout)
+                       ms_subtract_diff(&t_start, timeoutp);
                errno = oerrno;
                if (r > 0)
                        return 0;
index d2a8e24..20ec1b0 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: mux.c,v 1.98 2023/07/26 23:06:00 djm Exp $ */
+/* $OpenBSD: mux.c,v 1.99 2023/08/04 06:32:40 dtucker Exp $ */
 /*
  * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
  *
@@ -55,6 +55,7 @@
 #include "readconf.h"
 #include "clientloop.h"
 #include "ssherr.h"
+#include "misc.h"
 
 /* from ssh.c */
 extern int tty_flag;
@@ -1445,16 +1446,13 @@ control_client_sigrelay(int signo)
 }
 
 static int
-mux_client_read(int fd, struct sshbuf *b, size_t need)
+mux_client_read(int fd, struct sshbuf *b, size_t need, int timeout_ms)
 {
        size_t have;
        ssize_t len;
        u_char *p;
-       struct pollfd pfd;
        int r;
 
-       pfd.fd = fd;
-       pfd.events = POLLIN;
        if ((r = sshbuf_reserve(b, need, &p)) != 0)
                fatal_fr(r, "reserve");
        for (have = 0; have < need; ) {
@@ -1466,7 +1464,8 @@ mux_client_read(int fd, struct sshbuf *b, size_t need)
                if (len == -1) {
                        switch (errno) {
                        case EAGAIN:
-                               (void)poll(&pfd, 1, -1);
+                               if (waitrfd(fd, &timeout_ms) == -1)
+                                       return -1;      /* timeout */
                                /* FALLTHROUGH */
                        case EINTR:
                                continue;
@@ -1535,7 +1534,7 @@ mux_client_write_packet(int fd, struct sshbuf *m)
 }
 
 static int
-mux_client_read_packet(int fd, struct sshbuf *m)
+mux_client_read_packet_timeout(int fd, struct sshbuf *m, int timeout_ms)
 {
        struct sshbuf *queue;
        size_t need, have;
@@ -1544,7 +1543,7 @@ mux_client_read_packet(int fd, struct sshbuf *m)
 
        if ((queue = sshbuf_new()) == NULL)
                fatal_f("sshbuf_new");
-       if (mux_client_read(fd, queue, 4) != 0) {
+       if (mux_client_read(fd, queue, 4, timeout_ms) != 0) {
                if ((oerrno = errno) == EPIPE)
                        debug3_f("read header failed: %s",
                            strerror(errno));
@@ -1553,7 +1552,7 @@ mux_client_read_packet(int fd, struct sshbuf *m)
                return -1;
        }
        need = PEEK_U32(sshbuf_ptr(queue));
-       if (mux_client_read(fd, queue, need) != 0) {
+       if (mux_client_read(fd, queue, need, timeout_ms) != 0) {
                oerrno = errno;
                debug3_f("read body failed: %s", strerror(errno));
                sshbuf_free(queue);
@@ -1568,7 +1567,13 @@ mux_client_read_packet(int fd, struct sshbuf *m)
 }
 
 static int
-mux_client_hello_exchange(int fd)
+mux_client_read_packet(int fd, struct sshbuf *m)
+{
+       return mux_client_read_packet_timeout(fd, m, -1);
+}
+
+static int
+mux_client_hello_exchange(int fd, int timeout_ms)
 {
        struct sshbuf *m;
        u_int type, ver;
@@ -1589,7 +1594,7 @@ mux_client_hello_exchange(int fd)
        sshbuf_reset(m);
 
        /* Read their HELLO */
-       if (mux_client_read_packet(fd, m) != 0) {
+       if (mux_client_read_packet_timeout(fd, m, timeout_ms) != 0) {
                debug_f("read packet failed");
                goto out;
        }
@@ -2237,7 +2242,7 @@ int
 muxclient(const char *path)
 {
        struct sockaddr_un addr;
-       int sock;
+       int sock, timeout = options.connection_timeout, timeout_ms = -1;
        u_int pid;
 
        if (muxclient_command == 0) {
@@ -2293,7 +2298,11 @@ muxclient(const char *path)
        }
        set_nonblock(sock);
 
-       if (mux_client_hello_exchange(sock) != 0) {
+       /* Timeout on initial connection only. */
+       if (timeout > 0 && timeout < INT_MAX / 1000)
+               timeout_ms = timeout * 1000;
+
+       if (mux_client_hello_exchange(sock, timeout_ms) != 0) {
                error_f("master hello exchange failed");
                close(sock);
                return -1;