X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/0d34d6ceed345dd8d342758ecf0526819181478c..b0f6943a5dc83eaaaba15ebce897e162c1624033:/clientloop.c diff --git a/clientloop.c b/clientloop.c index 8f2f270d..9398dc98 100644 --- a/clientloop.c +++ b/clientloop.c @@ -1,3 +1,4 @@ +/* $OpenBSD: clientloop.c,v 1.169 2006/07/17 01:31:09 stevesk Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -59,7 +60,22 @@ */ #include "includes.h" -RCSID("$OpenBSD: clientloop.c,v 1.127 2004/06/17 15:10:13 djm Exp $"); + +#include +#ifdef HAVE_SYS_STAT_H +# include +#endif +#include +#include + +#include +#include +#ifdef HAVE_PATHS_H +#include +#endif +#include +#include +#include #include "ssh.h" #include "ssh1.h" @@ -77,6 +93,7 @@ RCSID("$OpenBSD: clientloop.c,v 1.127 2004/06/17 15:10:13 djm Exp $"); #include "log.h" #include "readconf.h" #include "clientloop.h" +#include "sshconnect.h" #include "authfd.h" #include "atomicio.h" #include "sshpty.h" @@ -113,11 +130,11 @@ extern char *host; static volatile sig_atomic_t received_window_change_signal = 0; static volatile sig_atomic_t received_signal = 0; -/* Flag indicating whether the user\'s terminal is in non-blocking mode. */ +/* Flag indicating whether the user's terminal is in non-blocking mode. */ static int in_non_blocking_mode = 0; /* Common data for the client loop code. */ -static int quit_pending; /* Set to non-zero to quit the client loop. */ +static volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ static int escape_char; /* Escape character. */ static int escape_pending; /* Last character was the escape character */ static int last_was_cr; /* Last character was a newline. */ @@ -140,6 +157,8 @@ int session_ident = -1; struct confirm_ctx { int want_tty; int want_subsys; + int want_x_fwd; + int want_agent_fwd; Buffer cmd; char *term; struct termios tio; @@ -175,7 +194,7 @@ enter_non_blocking(void) * Signal handler for the window change signal (SIGWINCH). This just sets a * flag indicating that the window has changed. */ - +/*ARGSUSED */ static void window_change_handler(int sig) { @@ -187,7 +206,7 @@ window_change_handler(int sig) * Signal handler for signals that cause the program to terminate. These * signals must be trapped to restore terminal modes. */ - +/*ARGSUSED */ static void signal_handler(int sig) { @@ -208,6 +227,109 @@ get_current_time(void) return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; } +#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" +void +client_x11_get_proto(const char *display, const char *xauth_path, + u_int trusted, char **_proto, char **_data) +{ + char cmd[1024]; + char line[512]; + char xdisplay[512]; + static char proto[512], data[512]; + FILE *f; + int got_data = 0, generated = 0, do_unlink = 0, i; + char *xauthdir, *xauthfile; + struct stat st; + + xauthdir = xauthfile = NULL; + *_proto = proto; + *_data = data; + proto[0] = data[0] = '\0'; + + if (xauth_path == NULL ||(stat(xauth_path, &st) == -1)) { + debug("No xauth program."); + } else { + if (display == NULL) { + debug("x11_get_proto: DISPLAY not set"); + return; + } + /* + * Handle FamilyLocal case where $DISPLAY does + * not match an authorization entry. For this we + * just try "xauth list unix:displaynum.screennum". + * XXX: "localhost" match to determine FamilyLocal + * is not perfect. + */ + if (strncmp(display, "localhost:", 10) == 0) { + snprintf(xdisplay, sizeof(xdisplay), "unix:%s", + display + 10); + display = xdisplay; + } + if (trusted == 0) { + xauthdir = xmalloc(MAXPATHLEN); + xauthfile = xmalloc(MAXPATHLEN); + strlcpy(xauthdir, "/tmp/ssh-XXXXXXXXXX", MAXPATHLEN); + if (mkdtemp(xauthdir) != NULL) { + do_unlink = 1; + snprintf(xauthfile, MAXPATHLEN, "%s/xauthfile", + xauthdir); + snprintf(cmd, sizeof(cmd), + "%s -f %s generate %s " SSH_X11_PROTO + " untrusted timeout 1200 2>" _PATH_DEVNULL, + xauth_path, xauthfile, display); + debug2("x11_get_proto: %s", cmd); + if (system(cmd) == 0) + generated = 1; + } + } + snprintf(cmd, sizeof(cmd), + "%s %s%s list %s 2>" _PATH_DEVNULL, + xauth_path, + generated ? "-f " : "" , + generated ? xauthfile : "", + display); + debug2("x11_get_proto: %s", cmd); + f = popen(cmd, "r"); + if (f && fgets(line, sizeof(line), f) && + sscanf(line, "%*s %511s %511s", proto, data) == 2) + got_data = 1; + if (f) + pclose(f); + } + + if (do_unlink) { + unlink(xauthfile); + rmdir(xauthdir); + } + if (xauthdir) + xfree(xauthdir); + if (xauthfile) + xfree(xauthfile); + + /* + * If we didn't get authentication data, just make up some + * data. The forwarding code will check the validity of the + * response anyway, and substitute this data. The X11 + * server, however, will ignore this fake data and use + * whatever authentication mechanisms it was using otherwise + * for the local connection. + */ + if (!got_data) { + u_int32_t rnd = 0; + + logit("Warning: No xauth data; " + "using fake authentication data for X11 forwarding."); + strlcpy(proto, SSH_X11_PROTO, sizeof proto); + for (i = 0; i < 16; i++) { + if (i % 4 == 0) + rnd = arc4random(); + snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", + rnd & 0xff); + rnd >>= 8; + } + } +} + /* * This is called when the interactive is entered. This checks if there is * an EOF coming on stdin. We must check this explicitly, as select() does @@ -316,10 +438,10 @@ client_check_window_change(void) if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) return; packet_start(SSH_CMSG_WINDOW_SIZE); - packet_put_int(ws.ws_row); - packet_put_int(ws.ws_col); - packet_put_int(ws.ws_xpixel); - packet_put_int(ws.ws_ypixel); + packet_put_int((u_int)ws.ws_row); + packet_put_int((u_int)ws.ws_col); + packet_put_int((u_int)ws.ws_xpixel); + packet_put_int((u_int)ws.ws_ypixel); packet_send(); } } @@ -348,7 +470,7 @@ server_alive_check(void) */ static void client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, - int *maxfdp, int *nallocp, int rekeying) + int *maxfdp, u_int *nallocp, int rekeying) { struct timeval tv, *tvp; int ret; @@ -402,7 +524,7 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, if (options.server_alive_interval == 0 || !compat20) tvp = NULL; - else { + else { tv.tv_sec = options.server_alive_interval; tv.tv_usec = 0; tvp = &tv; @@ -432,8 +554,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 +570,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); @@ -473,7 +585,7 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) } static void -client_process_net_input(fd_set * readset) +client_process_net_input(fd_set *readset) { int len; char buf[8192]; @@ -517,7 +629,7 @@ client_subsystem_reply(int type, u_int32_t seq, void *ctxt) { int id; Channel *c; - + id = packet_get_int(); packet_check_eom(); @@ -538,15 +650,34 @@ static void client_extra_session2_setup(int id, void *arg) { struct confirm_ctx *cctx = arg; + const char *display; Channel *c; int i; - + if (cctx == NULL) fatal("%s: cctx == NULL", __func__); if ((c = channel_lookup(id)) == NULL) fatal("%s: no channel for id %d", __func__, id); - client_session2_setup(id, cctx->want_tty, cctx->want_subsys, + display = getenv("DISPLAY"); + if (cctx->want_x_fwd && options.forward_x11 && display != NULL) { + char *proto, *data; + /* Get reasonable local authentication information. */ + client_x11_get_proto(display, options.xauth_location, + options.forward_x11_trusted, &proto, &data); + /* Request forwarding with authentication spoofing. */ + debug("Requesting X11 forwarding with authentication spoofing."); + x11_request_forwarding_with_spoofing(id, display, proto, data); + /* XXX wait for reply */ + } + + if (cctx->want_agent_fwd && options.forward_agent) { + debug("Requesting authentication agent forwarding."); + channel_request_start(id, "auth-agent-req@openssh.com", 0); + packet_send(); + } + + client_session2_setup(id, cctx->want_tty, cctx->want_subsys, cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env, client_subsystem_reply); @@ -557,21 +688,21 @@ client_extra_session2_setup(int id, void *arg) for (i = 0; cctx->env[i] != NULL; i++) xfree(cctx->env[i]); xfree(cctx->env); - } + } xfree(cctx); } static void -client_process_control(fd_set * readset) +client_process_control(fd_set *readset) { Buffer m; Channel *c; - int client_fd, new_fd[3], ver, i, allowed; + int client_fd, new_fd[3], ver, allowed; socklen_t addrlen; struct sockaddr_storage addr; struct confirm_ctx *cctx; char *cmd; - u_int len, env_len; + u_int i, len, env_len, command, flags; uid_t euid; gid_t egid; @@ -601,39 +732,76 @@ 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)) != SSHMUX_VER) { + 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 == SSHCTL_MASTER_ASK || + options.control_master == SSHCTL_MASTER_AUTO_ASK) + allowed = ask_permission("Allow shared connection " + "to %s? ", host); + /* continue below */ + break; + case SSHMUX_COMMAND_TERMINATE: + if (options.control_master == SSHCTL_MASTER_ASK || + options.control_master == SSHCTL_MASTER_AUTO_ASK) + 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, SSHMUX_VER, &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, SSHMUX_VER, &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,25 +810,25 @@ 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)) != SSHMUX_VER) { error("%s: wrong client version %d", __func__, ver); buffer_free(&m); close(client_fd); return; } - cctx = xmalloc(sizeof(*cctx)); - memset(cctx, 0, sizeof(*cctx)); - - cctx->want_tty = buffer_get_int(&m); - cctx->want_subsys = buffer_get_int(&m); + cctx = xcalloc(1, sizeof(*cctx)); + cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0; + cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0; + cctx->want_x_fwd = (flags & SSHMUX_FLAG_X11_FWD) != 0; + cctx->want_agent_fwd = (flags & SSHMUX_FLAG_AGENT_FWD) != 0; cctx->term = buffer_get_string(&m, &len); cmd = buffer_get_string(&m, &len); @@ -671,7 +839,7 @@ client_process_control(fd_set * readset) env_len = MIN(env_len, 4096); debug3("%s: receiving %d env vars", __func__, env_len); if (env_len != 0) { - cctx->env = xmalloc(sizeof(*cctx->env) * (env_len + 1)); + cctx->env = xcalloc(env_len + 1, sizeof(*cctx->env)); for (i = 0; i < env_len; i++) cctx->env[i] = buffer_get_string(&m, &len); cctx->env[i] = NULL; @@ -679,6 +847,7 @@ client_process_control(fd_set * readset) debug2("%s: accepted tty %d, subsys %d, cmd %s", __func__, cctx->want_tty, cctx->want_subsys, cmd); + xfree(cmd); /* Gather fds from client */ new_fd[0] = mm_receive_fd(client_fd); @@ -692,14 +861,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, SSHMUX_VER, &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); @@ -714,7 +890,7 @@ client_process_control(fd_set * readset) set_nonblock(client_fd); - c = channel_new("session", SSH_CHANNEL_OPENING, + c = channel_new("session", SSH_CHANNEL_OPENING, new_fd[0], new_fd[1], new_fd[2], CHAN_SES_WINDOW_DEFAULT, CHAN_SES_PACKET_DEFAULT, CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); @@ -732,11 +908,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); @@ -752,9 +928,22 @@ process_cmdline(void) if (*s == 'h' || *s == 'H' || *s == '?') { logit("Commands:"); - logit(" -Lport:host:hostport Request local forward"); - logit(" -Rport:host:hostport Request remote forward"); - logit(" -KRhostport Cancel remote forward"); + logit(" -L[bind_address:]port:host:hostport " + "Request local forward"); + logit(" -R[bind_address:]port:host:hostport " + "Request remote forward"); + logit(" -KR[bind_address:]port " + "Cancel remote forward"); + if (!options.permit_local_command) + goto out; + logit(" !args " + "Execute local command"); + goto out; + } + + if (*s == '!' && options.permit_local_command) { + s++; + ssh_local_cmd(s); goto out; } @@ -782,37 +971,41 @@ 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 { + if (channel_request_remote_forwarding(fwd.listen_host, + fwd.listen_port, fwd.connect_host, + fwd.connect_port) < 0) { logit("Port forwarding failed."); goto out; } - } else - channel_request_remote_forwarding(fwd_port, buf, - fwd_host_port); + } + logit("Forwarding port."); } @@ -834,7 +1027,10 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len) u_char ch; char *s; - for (i = 0; i < len; i++) { + if (len <= 0) + return (0); + + for (i = 0; i < (u_int)len; i++) { /* Get one character at a time. */ ch = buf[i]; @@ -999,7 +1195,7 @@ Supported escape sequences:\r\n\ } static void -client_process_input(fd_set * readset) +client_process_input(fd_set *readset) { int len; char buf[8192]; @@ -1052,7 +1248,7 @@ client_process_input(fd_set * readset) } static void -client_process_output(fd_set * writeset) +client_process_output(fd_set *writeset) { int len; char buf[100]; @@ -1147,7 +1343,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) { fd_set *readset = NULL, *writeset = NULL; double start_time, total_time; - int max_fd = 0, max_fd2 = 0, len, rekeying = 0, nalloc = 0; + int max_fd = 0, max_fd2 = 0, len, rekeying = 0; + u_int nalloc = 0; char buf[100]; debug("Entering interactive session."); @@ -1195,14 +1392,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(); @@ -1211,10 +1409,10 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) session_ident = ssh2_chan_id; if (escape_char != SSH_ESCAPECHAR_NONE) channel_register_filter(session_ident, - simple_escape_filter); + simple_escape_filter, NULL); if (session_ident != -1) channel_register_cleanup(session_ident, - client_channel_closed); + client_channel_closed, 0); } else { /* Check if we should immediately send eof on stdin. */ client_check_initial_eof_on_stdin(); @@ -1310,8 +1508,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(); @@ -1514,7 +1711,7 @@ client_request_x11(const char *request_type, int rchan) if (!options.forward_x11) { error("Warning: ssh server tried X11 forwarding."); - error("Warning: this is probably a break in attempt by a malicious server."); + error("Warning: this is probably a break-in attempt by a malicious server."); return NULL; } originator = packet_get_string(NULL); @@ -1547,7 +1744,7 @@ client_request_agent(const char *request_type, int rchan) if (!options.forward_agent) { error("Warning: ssh server tried agent forwarding."); - error("Warning: this is probably a break in attempt by a malicious server."); + error("Warning: this is probably a break-in attempt by a malicious server."); return NULL; } sock = ssh_get_authentication_socket(); @@ -1626,8 +1823,9 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt) debug("client_input_channel_req: channel %d rtype %s reply %d", id, rtype, reply); - c = channel_lookup(id); - if (c == NULL) { + if (id == -1) { + error("client_input_channel_req: request for channel -1"); + } else if ((c = channel_lookup(id)) == NULL) { error("client_input_channel_req: channel %d: unknown channel", id); } else if (strcmp(rtype, "exit-status") == 0) { exitval = packet_get_int(); @@ -1646,7 +1844,7 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt) if (reply) { packet_start(success ? SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); - packet_put_int(c->remote_id); + packet_put_int(id); packet_send(); } xfree(rtype); @@ -1672,14 +1870,18 @@ client_input_global_request(int type, u_int32_t seq, void *ctxt) } void -client_session2_setup(int id, int want_tty, int want_subsystem, +client_session2_setup(int id, int want_tty, int want_subsystem, const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env, 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; @@ -1690,14 +1892,15 @@ client_session2_setup(int id, int want_tty, int want_subsystem, channel_request_start(id, "pty-req", 0); packet_put_cstring(term != NULL ? term : ""); - packet_put_int(ws.ws_col); - packet_put_int(ws.ws_row); - packet_put_int(ws.ws_xpixel); - packet_put_int(ws.ws_ypixel); + packet_put_int((u_int)ws.ws_col); + packet_put_int((u_int)ws.ws_row); + packet_put_int((u_int)ws.ws_xpixel); + packet_put_int((u_int)ws.ws_ypixel); tio = get_saved_tio(); 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 */ @@ -1710,7 +1913,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem, /* Split */ name = xstrdup(env[i]); if ((val = strchr(name, '=')) == NULL) { - free(name); + xfree(name); continue; } *val++ = '\0'; @@ -1724,7 +1927,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem, } if (!matched) { debug3("Ignored env %s", name); - free(name); + xfree(name); continue; } @@ -1733,7 +1936,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem, packet_put_cstring(name); packet_put_cstring(val); packet_send(); - free(name); + xfree(name); } }