upstream: make failures when establishing "Tunnel" forwarding terminate

the connection when ExitOnForwardFailure is enabled; bz3116; ok dtucker

OpenBSD-Commit-ID: ef4b4808de0a419c17579b1081da768625c1d735
This commit is contained in:
djm@openbsd.org 2020-04-03 02:40:32 +00:00 committed by Damien Miller
parent ed833da176
commit 663e84bb53
3 changed files with 47 additions and 27 deletions

View 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> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * 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 * char *
client_request_tun_fwd(struct ssh *ssh, int tun_mode, 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; Channel *c;
int r, fd; int r, fd;
@ -1673,6 +1673,9 @@ client_request_tun_fwd(struct ssh *ssh, int tun_mode,
sys_tun_outfilter, NULL, NULL); sys_tun_outfilter, NULL, NULL);
#endif #endif
if (cb != NULL)
channel_register_open_confirm(ssh, c->self, cb, cbctx);
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN)) != 0 || if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN)) != 0 ||
(r = sshpkt_put_cstring(ssh, "tun@openssh.com")) != 0 || (r = sshpkt_put_cstring(ssh, "tun@openssh.com")) != 0 ||
(r = sshpkt_put_u32(ssh, c->self)) != 0 || (r = sshpkt_put_u32(ssh, c->self)) != 0 ||

View 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> * 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_global_request_reply_fwd(int, u_int32_t, void *);
void client_session2_setup(struct ssh *, int, int, int, void client_session2_setup(struct ssh *, int, int, int,
const char *, struct termios *, int, struct sshbuf *, char **); 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); void client_stop_mux(void);
/* Escape filter for protocol 2 sessions */ /* Escape filter for protocol 2 sessions */

56
ssh.c
View File

@ -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> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -197,7 +197,7 @@ struct sshbuf *command;
int subsystem_flag = 0; int subsystem_flag = 0;
/* # of replies received for global requests */ /* # of replies received for global requests */
static int remote_forward_confirms_received = 0; static int forward_confirms_pending = -1;
/* mux.c */ /* mux.c */
extern int muxserver_sock; extern int muxserver_sock;
@ -1673,6 +1673,16 @@ fork_postauth(void)
fatal("daemon() failed: %.200s", strerror(errno)); 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 */ /* Callback for remote forward global requests */
static void static void
ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) 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); "for listen port %d", rfwd->listen_port);
} }
} }
if (++remote_forward_confirms_received == options.num_remote_forwards) { forwarding_success();
debug("All remote forwarding requests processed");
if (fork_after_authentication_flag)
fork_postauth();
}
} }
static void static void
@ -1753,6 +1759,19 @@ ssh_stdio_confirm(struct ssh *ssh, int id, int success, void *arg)
fatal("stdio forwarding failed"); 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 static void
ssh_init_stdio_forwarding(struct ssh *ssh) ssh_init_stdio_forwarding(struct ssh *ssh)
{ {
@ -1816,34 +1835,31 @@ ssh_init_forwarding(struct ssh *ssh, char **ifname)
options.remote_forwards[i].connect_path : options.remote_forwards[i].connect_path :
options.remote_forwards[i].connect_host, options.remote_forwards[i].connect_host,
options.remote_forwards[i].connect_port); options.remote_forwards[i].connect_port);
options.remote_forwards[i].handle = if ((options.remote_forwards[i].handle =
channel_request_remote_forwarding(ssh, channel_request_remote_forwarding(ssh,
&options.remote_forwards[i]); &options.remote_forwards[i])) >= 0) {
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 {
client_register_global_confirm( client_register_global_confirm(
ssh_confirm_remote_forward, ssh_confirm_remote_forward,
&options.remote_forwards[i]); &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. */ /* Initiate tunnel forwarding. */
if (options.tun_open != SSH_TUNMODE_NO) { if (options.tun_open != SSH_TUNMODE_NO) {
if ((*ifname = client_request_tun_fwd(ssh, if ((*ifname = client_request_tun_fwd(ssh,
options.tun_open, options.tun_local, options.tun_open, options.tun_local,
options.tun_remote)) == NULL) { options.tun_remote, ssh_tun_confirm, NULL)) != NULL)
if (options.exit_on_forward_failure) forward_confirms_pending++;
else if (options.exit_on_forward_failure)
fatal("Could not request tunnel forwarding."); fatal("Could not request tunnel forwarding.");
else else
error("Could not request tunnel forwarding."); error("Could not request tunnel forwarding.");
} }
} }
}
static void static void
check_agent_present(void) check_agent_present(void)