]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: make failures when establishing "Tunnel" forwarding terminate
authordjm@openbsd.org <djm@openbsd.org>
Fri, 3 Apr 2020 02:40:32 +0000 (02:40 +0000)
committerDamien Miller <djm@mindrot.org>
Fri, 3 Apr 2020 02:42:33 +0000 (13:42 +1100)
the connection when ExitOnForwardFailure is enabled; bz3116; ok dtucker

OpenBSD-Commit-ID: ef4b4808de0a419c17579b1081da768625c1d735

clientloop.c
clientloop.h
ssh.c

index 5bfccdd358d8bc4271159cdbe6ee9eb0bf5cfbfe..8950f444b418ae66f0d8f79c3001f6fd7c16c9f9 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.342 2020/02/26 13:40:09 jsg Exp $ */
+/* $OpenBSD: clientloop.c,v 1.343 2020/04/03 02:40:32 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1645,7 +1645,7 @@ client_request_agent(struct ssh *ssh, const char *request_type, int rchan)
 
 char *
 client_request_tun_fwd(struct ssh *ssh, int tun_mode,
-    int local_tun, int remote_tun)
+    int local_tun, int remote_tun, channel_open_fn *cb, void *cbctx)
 {
        Channel *c;
        int r, fd;
@@ -1673,6 +1673,9 @@ client_request_tun_fwd(struct ssh *ssh, int tun_mode,
                    sys_tun_outfilter, NULL, NULL);
 #endif
 
+       if (cb != NULL)
+               channel_register_open_confirm(ssh, c->self, cb, cbctx);
+
        if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN)) != 0 ||
            (r = sshpkt_put_cstring(ssh, "tun@openssh.com")) != 0 ||
            (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
index bf79c87bf89d0b6c3d36387e5698832964ce470d..31630551b23cba11ddf59a3e7c0031ccb8ac6458 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.h,v 1.36 2018/07/09 21:03:30 markus Exp $ */
+/* $OpenBSD: clientloop.h,v 1.37 2020/04/03 02:40:32 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -46,7 +46,8 @@ int    client_x11_get_proto(struct ssh *, const char *, const char *,
 void    client_global_request_reply_fwd(int, u_int32_t, void *);
 void    client_session2_setup(struct ssh *, int, int, int,
            const char *, struct termios *, int, struct sshbuf *, char **);
-char    *client_request_tun_fwd(struct ssh *, int, int, int);
+char    *client_request_tun_fwd(struct ssh *, int, int, int,
+    channel_open_fn *, void *);
 void    client_stop_mux(void);
 
 /* Escape filter for protocol 2 sessions */
diff --git a/ssh.c b/ssh.c
index 470d9b7e6bbf763a2197df51cd1e2b9484e67005..d99a245a401b12c8fa0dd07b1718a68d9d14c394 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.522 2020/04/03 02:27:12 dtucker Exp $ */
+/* $OpenBSD: ssh.c,v 1.523 2020/04/03 02:40:32 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -197,7 +197,7 @@ struct sshbuf *command;
 int subsystem_flag = 0;
 
 /* # of replies received for global requests */
-static int remote_forward_confirms_received = 0;
+static int forward_confirms_pending = -1;
 
 /* mux.c */
 extern int muxserver_sock;
@@ -1673,6 +1673,16 @@ fork_postauth(void)
                fatal("daemon() failed: %.200s", strerror(errno));
 }
 
+static void
+forwarding_success(void)
+{
+       if (forward_confirms_pending > 0 && --forward_confirms_pending == 0) {
+               debug("All forwarding requests processed");
+               if (fork_after_authentication_flag)
+                       fork_postauth();
+       }
+}
+
 /* Callback for remote forward global requests */
 static void
 ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
@@ -1732,11 +1742,7 @@ ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
                                    "for listen port %d", rfwd->listen_port);
                }
        }
-       if (++remote_forward_confirms_received == options.num_remote_forwards) {
-               debug("All remote forwarding requests processed");
-               if (fork_after_authentication_flag)
-                       fork_postauth();
-       }
+       forwarding_success();
 }
 
 static void
@@ -1753,6 +1759,19 @@ ssh_stdio_confirm(struct ssh *ssh, int id, int success, void *arg)
                fatal("stdio forwarding failed");
 }
 
+static void
+ssh_tun_confirm(struct ssh *ssh, int id, int success, void *arg)
+{
+       if (!success) {
+               error("Tunnel forwarding failed");
+               if (options.exit_on_forward_failure)
+                       cleanup_exit(255);
+       }
+
+       debug("%s: tunnel forward established, id=%d", __func__, id);
+       forwarding_success();
+}
+
 static void
 ssh_init_stdio_forwarding(struct ssh *ssh)
 {
@@ -1816,32 +1835,29 @@ ssh_init_forwarding(struct ssh *ssh, char **ifname)
                    options.remote_forwards[i].connect_path :
                    options.remote_forwards[i].connect_host,
                    options.remote_forwards[i].connect_port);
-               options.remote_forwards[i].handle =
+               if ((options.remote_forwards[i].handle =
                    channel_request_remote_forwarding(ssh,
-                   &options.remote_forwards[i]);
-               if (options.remote_forwards[i].handle < 0) {
-                       if (options.exit_on_forward_failure)
-                               fatal("Could not request remote forwarding.");
-                       else
-                               logit("Warning: Could not request remote "
-                                   "forwarding.");
-               } else {
+                   &options.remote_forwards[i])) >= 0) {
                        client_register_global_confirm(
                            ssh_confirm_remote_forward,
                            &options.remote_forwards[i]);
-               }
+                       forward_confirms_pending++;
+               } else if (options.exit_on_forward_failure)
+                       fatal("Could not request remote forwarding.");
+               else
+                       logit("Warning: Could not request remote forwarding.");
        }
 
        /* Initiate tunnel forwarding. */
        if (options.tun_open != SSH_TUNMODE_NO) {
                if ((*ifname = client_request_tun_fwd(ssh,
                    options.tun_open, options.tun_local,
-                   options.tun_remote)) == NULL) {
-                       if (options.exit_on_forward_failure)
-                               fatal("Could not request tunnel forwarding.");
-                       else
-                               error("Could not request tunnel forwarding.");
-               }
+                   options.tun_remote, ssh_tun_confirm, NULL)) != NULL)
+                       forward_confirms_pending++;
+               else if (options.exit_on_forward_failure)
+                       fatal("Could not request tunnel forwarding.");
+               else
+                       error("Could not request tunnel forwarding.");
        }
 }