diff options
author | des <des@FreeBSD.org> | 2005-06-05 15:40:50 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2005-06-05 15:40:50 +0000 |
commit | 11a09ab416e21c995885dc0e5847151627094217 (patch) | |
tree | 7767975616a98948a7ef791c43b28a21711a22c7 /crypto/openssh/clientloop.c | |
parent | d5d493f03ae792146848e3cba16bb9e667c73125 (diff) | |
download | FreeBSD-src-11a09ab416e21c995885dc0e5847151627094217.zip FreeBSD-src-11a09ab416e21c995885dc0e5847151627094217.tar.gz |
Vendor import of OpenSSH 4.0p1.
Diffstat (limited to 'crypto/openssh/clientloop.c')
-rw-r--r-- | crypto/openssh/clientloop.c | 175 |
1 files changed, 106 insertions, 69 deletions
diff --git a/crypto/openssh/clientloop.c b/crypto/openssh/clientloop.c index 0b9a0fb..1e25088 100644 --- a/crypto/openssh/clientloop.c +++ b/crypto/openssh/clientloop.c @@ -59,7 +59,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: clientloop.c,v 1.130 2004/08/11 21:43:04 avsm Exp $"); +RCSID("$OpenBSD: clientloop.c,v 1.135 2005/03/01 10:09:52 djm Exp $"); #include "ssh.h" #include "ssh1.h" @@ -432,8 +432,6 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, static void client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) { - struct winsize oldws, newws; - /* Flush stdout and stderr buffers. */ if (buffer_len(bout) > 0) atomicio(vwrite, fileno(stdout), buffer_ptr(bout), buffer_len(bout)); @@ -450,19 +448,11 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) buffer_free(bout); buffer_free(berr); - /* Save old window size. */ - ioctl(fileno(stdin), TIOCGWINSZ, &oldws); - /* Send the suspend signal to the program itself. */ kill(getpid(), SIGTSTP); - /* Check if the window size has changed. */ - if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 && - (oldws.ws_row != newws.ws_row || - oldws.ws_col != newws.ws_col || - oldws.ws_xpixel != newws.ws_xpixel || - oldws.ws_ypixel != newws.ws_ypixel)) - received_window_change_signal = 1; + /* Reset window sizes in case they have changed */ + received_window_change_signal = 1; /* OK, we have been continued by the user. Reinitialize buffers. */ buffer_init(bin); @@ -571,7 +561,7 @@ client_process_control(fd_set * readset) struct sockaddr_storage addr; struct confirm_ctx *cctx; char *cmd; - u_int len, env_len; + u_int len, env_len, command, flags; uid_t euid; gid_t egid; @@ -601,39 +591,74 @@ client_process_control(fd_set * readset) return; } - allowed = 1; - if (options.control_master == 2) { - char *p, prompt[1024]; - - allowed = 0; - snprintf(prompt, sizeof(prompt), - "Allow shared connection to %s? ", host); - p = read_passphrase(prompt, RP_USE_ASKPASS|RP_ALLOW_EOF); - if (p != NULL) { - /* - * Accept empty responses and responses consisting - * of the word "yes" as affirmative. - */ - if (*p == '\0' || *p == '\n' || - strcasecmp(p, "yes") == 0) - allowed = 1; - xfree(p); - } - } - unset_nonblock(client_fd); + /* Read command */ buffer_init(&m); + if (ssh_msg_recv(client_fd, &m) == -1) { + error("%s: client msg_recv failed", __func__); + close(client_fd); + buffer_free(&m); + return; + } + if ((ver = buffer_get_char(&m)) != 1) { + error("%s: wrong client version %d", __func__, ver); + buffer_free(&m); + close(client_fd); + return; + } + + allowed = 1; + command = buffer_get_int(&m); + flags = buffer_get_int(&m); + + buffer_clear(&m); + switch (command) { + case SSHMUX_COMMAND_OPEN: + if (options.control_master == 2) + allowed = ask_permission("Allow shared connection " + "to %s? ", host); + /* continue below */ + break; + case SSHMUX_COMMAND_TERMINATE: + if (options.control_master == 2) + allowed = ask_permission("Terminate shared connection " + "to %s? ", host); + if (allowed) + quit_pending = 1; + /* FALLTHROUGH */ + case SSHMUX_COMMAND_ALIVE_CHECK: + /* Reply for SSHMUX_COMMAND_TERMINATE and ALIVE_CHECK */ + buffer_clear(&m); + buffer_put_int(&m, allowed); + buffer_put_int(&m, getpid()); + if (ssh_msg_send(client_fd, /* version */1, &m) == -1) { + error("%s: client msg_send failed", __func__); + close(client_fd); + buffer_free(&m); + return; + } + buffer_free(&m); + close(client_fd); + return; + default: + error("Unsupported command %d", command); + buffer_free(&m); + close(client_fd); + return; + } + + /* Reply for SSHMUX_COMMAND_OPEN */ + buffer_clear(&m); buffer_put_int(&m, allowed); buffer_put_int(&m, getpid()); - if (ssh_msg_send(client_fd, /* version */0, &m) == -1) { + if (ssh_msg_send(client_fd, /* version */1, &m) == -1) { error("%s: client msg_send failed", __func__); close(client_fd); buffer_free(&m); return; } - buffer_clear(&m); if (!allowed) { error("Refused control connection"); @@ -642,14 +667,14 @@ client_process_control(fd_set * readset) return; } + buffer_clear(&m); if (ssh_msg_recv(client_fd, &m) == -1) { error("%s: client msg_recv failed", __func__); close(client_fd); buffer_free(&m); return; } - - if ((ver = buffer_get_char(&m)) != 0) { + if ((ver = buffer_get_char(&m)) != 1) { error("%s: wrong client version %d", __func__, ver); buffer_free(&m); close(client_fd); @@ -658,9 +683,8 @@ client_process_control(fd_set * readset) cctx = xmalloc(sizeof(*cctx)); memset(cctx, 0, sizeof(*cctx)); - - cctx->want_tty = buffer_get_int(&m); - cctx->want_subsys = buffer_get_int(&m); + cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0; + cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0; cctx->term = buffer_get_string(&m, &len); cmd = buffer_get_string(&m, &len); @@ -692,14 +716,21 @@ client_process_control(fd_set * readset) if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1) error("%s: tcgetattr: %s", __func__, strerror(errno)); + /* This roundtrip is just for synchronisation of ttymodes */ buffer_clear(&m); - if (ssh_msg_send(client_fd, /* version */0, &m) == -1) { + if (ssh_msg_send(client_fd, /* version */1, &m) == -1) { error("%s: client msg_send failed", __func__); close(client_fd); close(new_fd[0]); close(new_fd[1]); close(new_fd[2]); buffer_free(&m); + xfree(cctx->term); + if (env_len != 0) { + for (i = 0; i < env_len; i++) + xfree(cctx->env[i]); + xfree(cctx->env); + } return; } buffer_free(&m); @@ -732,11 +763,11 @@ static void process_cmdline(void) { void (*handler)(int); - char *s, *cmd; - u_short fwd_port, fwd_host_port; - char buf[1024], sfwd_port[6], sfwd_host_port[6]; + char *s, *cmd, *cancel_host; int delete = 0; int local = 0; + u_short cancel_port; + Forward fwd; leave_raw_mode(); handler = signal(SIGINT, SIG_IGN); @@ -782,37 +813,38 @@ process_cmdline(void) s++; if (delete) { - if (sscanf(s, "%5[0-9]", sfwd_host_port) != 1) { - logit("Bad forwarding specification."); - goto out; + cancel_port = 0; + cancel_host = hpdelim(&s); /* may be NULL */ + if (s != NULL) { + cancel_port = a2port(s); + cancel_host = cleanhostname(cancel_host); + } else { + cancel_port = a2port(cancel_host); + cancel_host = NULL; } - if ((fwd_host_port = a2port(sfwd_host_port)) == 0) { - logit("Bad forwarding port(s)."); + if (cancel_port == 0) { + logit("Bad forwarding close port"); goto out; } - channel_request_rforward_cancel(fwd_host_port); + channel_request_rforward_cancel(cancel_host, cancel_port); } else { - if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]", - sfwd_port, buf, sfwd_host_port) != 3 && - sscanf(s, "%5[0-9]/%255[^/]/%5[0-9]", - sfwd_port, buf, sfwd_host_port) != 3) { + if (!parse_forward(&fwd, s)) { logit("Bad forwarding specification."); goto out; } - if ((fwd_port = a2port(sfwd_port)) == 0 || - (fwd_host_port = a2port(sfwd_host_port)) == 0) { - logit("Bad forwarding port(s)."); - goto out; - } if (local) { - if (channel_setup_local_fwd_listener(fwd_port, buf, - fwd_host_port, options.gateway_ports) < 0) { + if (channel_setup_local_fwd_listener(fwd.listen_host, + fwd.listen_port, fwd.connect_host, + fwd.connect_port, options.gateway_ports) < 0) { logit("Port forwarding failed."); goto out; } - } else - channel_request_remote_forwarding(fwd_port, buf, - fwd_host_port); + } else { + channel_request_remote_forwarding(fwd.listen_host, + fwd.listen_port, fwd.connect_host, + fwd.connect_port); + } + logit("Forwarding port."); } @@ -1196,14 +1228,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) * Set signal handlers, (e.g. to restore non-blocking mode) * but don't overwrite SIG_IGN, matches behaviour from rsh(1) */ + if (signal(SIGHUP, SIG_IGN) != SIG_IGN) + signal(SIGHUP, signal_handler); if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, signal_handler); if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) signal(SIGQUIT, signal_handler); if (signal(SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, signal_handler); - if (have_pty) - signal(SIGWINCH, window_change_handler); + signal(SIGWINCH, window_change_handler); if (have_pty) enter_raw_mode(); @@ -1311,8 +1344,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) /* Terminate the session. */ /* Stop watching for window change. */ - if (have_pty) - signal(SIGWINCH, SIG_DFL); + signal(SIGWINCH, SIG_DFL); channel_free_all(); @@ -1679,9 +1711,13 @@ client_session2_setup(int id, int want_tty, int want_subsystem, dispatch_fn *subsys_repl) { int len; + Channel *c = NULL; debug2("%s: id %d", __func__, id); + if ((c = channel_lookup(id)) == NULL) + fatal("client_session2_setup: channel %d: unknown channel", id); + if (want_tty) { struct winsize ws; struct termios tio; @@ -1700,6 +1736,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem, tty_make_modes(-1, tiop != NULL ? tiop : &tio); packet_send(); /* XXX wait for reply */ + c->client_tty = 1; } /* Transfer any environment variables from client to server */ |