summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2005-01-04 13:07:27 +0000
committerColin Watson <cjwatson@debian.org>2005-01-04 13:07:27 +0000
commitfd0f611b70a83d80fe8793af785542ee5541b7cd (patch)
treebededd22bb7eeec52e20083237ab7e4113445a16 /clientloop.c
parentc44fe9a5b9d3db96a7249b04d915f17e4a3a3b04 (diff)
parentebd2ce335af5861020c79fddb1ae35c03bf036cf (diff)
Merge 3.9p1 to the trunk.
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c478
1 files changed, 420 insertions, 58 deletions
diff --git a/clientloop.c b/clientloop.c
index a13d06ddf..1bcf4392f 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -59,7 +59,7 @@
59 */ 59 */
60 60
61#include "includes.h" 61#include "includes.h"
62RCSID("$OpenBSD: clientloop.c,v 1.117 2003/12/16 15:49:51 markus Exp $"); 62RCSID("$OpenBSD: clientloop.c,v 1.130 2004/08/11 21:43:04 avsm Exp $");
63 63
64#include "ssh.h" 64#include "ssh.h"
65#include "ssh1.h" 65#include "ssh1.h"
@@ -79,9 +79,11 @@ RCSID("$OpenBSD: clientloop.c,v 1.117 2003/12/16 15:49:51 markus Exp $");
79#include "clientloop.h" 79#include "clientloop.h"
80#include "authfd.h" 80#include "authfd.h"
81#include "atomicio.h" 81#include "atomicio.h"
82#include "sshtty.h" 82#include "sshpty.h"
83#include "misc.h" 83#include "misc.h"
84#include "readpass.h" 84#include "monitor_fdpass.h"
85#include "match.h"
86#include "msg.h"
85 87
86/* import options */ 88/* import options */
87extern Options options; 89extern Options options;
@@ -92,6 +94,9 @@ extern int stdin_null_flag;
92/* Flag indicating that no shell has been requested */ 94/* Flag indicating that no shell has been requested */
93extern int no_shell_flag; 95extern int no_shell_flag;
94 96
97/* Control socket */
98extern int control_fd;
99
95/* 100/*
96 * Name of the host we are connecting to. This is the name given on the 101 * Name of the host we are connecting to. This is the name given on the
97 * command line, or the HostName specified for the user-supplied name in a 102 * command line, or the HostName specified for the user-supplied name in a
@@ -132,16 +137,27 @@ static int server_alive_timeouts = 0;
132static void client_init_dispatch(void); 137static void client_init_dispatch(void);
133int session_ident = -1; 138int session_ident = -1;
134 139
140struct confirm_ctx {
141 int want_tty;
142 int want_subsys;
143 Buffer cmd;
144 char *term;
145 struct termios tio;
146 char **env;
147};
148
135/*XXX*/ 149/*XXX*/
136extern Kex *xxx_kex; 150extern Kex *xxx_kex;
137 151
152void ssh_process_session2_setup(int, int, int, Buffer *);
153
138/* Restores stdin to blocking mode. */ 154/* Restores stdin to blocking mode. */
139 155
140static void 156static void
141leave_non_blocking(void) 157leave_non_blocking(void)
142{ 158{
143 if (in_non_blocking_mode) { 159 if (in_non_blocking_mode) {
144 (void) fcntl(fileno(stdin), F_SETFL, 0); 160 unset_nonblock(fileno(stdin));
145 in_non_blocking_mode = 0; 161 in_non_blocking_mode = 0;
146 } 162 }
147} 163}
@@ -152,7 +168,7 @@ static void
152enter_non_blocking(void) 168enter_non_blocking(void)
153{ 169{
154 in_non_blocking_mode = 1; 170 in_non_blocking_mode = 1;
155 (void) fcntl(fileno(stdin), F_SETFL, O_NONBLOCK); 171 set_nonblock(fileno(stdin));
156} 172}
157 173
158/* 174/*
@@ -292,19 +308,13 @@ client_check_window_change(void)
292 /** XXX race */ 308 /** XXX race */
293 received_window_change_signal = 0; 309 received_window_change_signal = 0;
294 310
295 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
296 return;
297
298 debug2("client_check_window_change: changed"); 311 debug2("client_check_window_change: changed");
299 312
300 if (compat20) { 313 if (compat20) {
301 channel_request_start(session_ident, "window-change", 0); 314 channel_send_window_changes();
302 packet_put_int(ws.ws_col);
303 packet_put_int(ws.ws_row);
304 packet_put_int(ws.ws_xpixel);
305 packet_put_int(ws.ws_ypixel);
306 packet_send();
307 } else { 315 } else {
316 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
317 return;
308 packet_start(SSH_CMSG_WINDOW_SIZE); 318 packet_start(SSH_CMSG_WINDOW_SIZE);
309 packet_put_int(ws.ws_row); 319 packet_put_int(ws.ws_row);
310 packet_put_int(ws.ws_col); 320 packet_put_int(ws.ws_col);
@@ -341,10 +351,9 @@ server_alive_check(void)
341 * Waits until the client can do something (some data becomes available on 351 * Waits until the client can do something (some data becomes available on
342 * one of the file descriptors). 352 * one of the file descriptors).
343 */ 353 */
344
345static void 354static void
346client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, 355client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
347 int *maxfdp, int *nallocp, int rekeying) 356 int *maxfdp, u_int *nallocp, int rekeying)
348{ 357{
349 struct timeval tv, *tvp; 358 struct timeval tv, *tvp;
350 int ret; 359 int ret;
@@ -387,6 +396,9 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
387 if (packet_have_data_to_write()) 396 if (packet_have_data_to_write())
388 FD_SET(connection_out, *writesetp); 397 FD_SET(connection_out, *writesetp);
389 398
399 if (control_fd != -1)
400 FD_SET(control_fd, *readsetp);
401
390 /* 402 /*
391 * Wait for something to happen. This will suspend the process until 403 * Wait for something to happen. This will suspend the process until
392 * some selected descriptor can be read, written, or has some other 404 * some selected descriptor can be read, written, or has some other
@@ -395,7 +407,7 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
395 407
396 if (options.server_alive_interval == 0) 408 if (options.server_alive_interval == 0)
397 tvp = NULL; 409 tvp = NULL;
398 else { 410 else {
399 tv.tv_sec = options.server_alive_interval; 411 tv.tv_sec = options.server_alive_interval;
400 tv.tv_usec = 0; 412 tv.tv_usec = 0;
401 tvp = &tv; 413 tvp = &tv;
@@ -506,12 +518,229 @@ client_process_net_input(fd_set * readset)
506} 518}
507 519
508static void 520static void
521client_subsystem_reply(int type, u_int32_t seq, void *ctxt)
522{
523 int id;
524 Channel *c;
525
526 id = packet_get_int();
527 packet_check_eom();
528
529 if ((c = channel_lookup(id)) == NULL) {
530 error("%s: no channel for id %d", __func__, id);
531 return;
532 }
533
534 if (type == SSH2_MSG_CHANNEL_SUCCESS)
535 debug2("Request suceeded on channel %d", id);
536 else if (type == SSH2_MSG_CHANNEL_FAILURE) {
537 error("Request failed on channel %d", id);
538 channel_free(c);
539 }
540}
541
542static void
543client_extra_session2_setup(int id, void *arg)
544{
545 struct confirm_ctx *cctx = arg;
546 Channel *c;
547 int i;
548
549 if (cctx == NULL)
550 fatal("%s: cctx == NULL", __func__);
551 if ((c = channel_lookup(id)) == NULL)
552 fatal("%s: no channel for id %d", __func__, id);
553
554 client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
555 cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env,
556 client_subsystem_reply);
557
558 c->confirm_ctx = NULL;
559 buffer_free(&cctx->cmd);
560 xfree(cctx->term);
561 if (cctx->env != NULL) {
562 for (i = 0; cctx->env[i] != NULL; i++)
563 xfree(cctx->env[i]);
564 xfree(cctx->env);
565 }
566 xfree(cctx);
567}
568
569static void
570client_process_control(fd_set * readset)
571{
572 Buffer m;
573 Channel *c;
574 int client_fd, new_fd[3], ver, i, allowed;
575 socklen_t addrlen;
576 struct sockaddr_storage addr;
577 struct confirm_ctx *cctx;
578 char *cmd;
579 u_int len, env_len;
580 uid_t euid;
581 gid_t egid;
582
583 /*
584 * Accept connection on control socket
585 */
586 if (control_fd == -1 || !FD_ISSET(control_fd, readset))
587 return;
588
589 memset(&addr, 0, sizeof(addr));
590 addrlen = sizeof(addr);
591 if ((client_fd = accept(control_fd,
592 (struct sockaddr*)&addr, &addrlen)) == -1) {
593 error("%s accept: %s", __func__, strerror(errno));
594 return;
595 }
596
597 if (getpeereid(client_fd, &euid, &egid) < 0) {
598 error("%s getpeereid failed: %s", __func__, strerror(errno));
599 close(client_fd);
600 return;
601 }
602 if ((euid != 0) && (getuid() != euid)) {
603 error("control mode uid mismatch: peer euid %u != uid %u",
604 (u_int) euid, (u_int) getuid());
605 close(client_fd);
606 return;
607 }
608
609 allowed = 1;
610 if (options.control_master == 2) {
611 char *p, prompt[1024];
612
613 allowed = 0;
614 snprintf(prompt, sizeof(prompt),
615 "Allow shared connection to %s? ", host);
616 p = read_passphrase(prompt, RP_USE_ASKPASS|RP_ALLOW_EOF);
617 if (p != NULL) {
618 /*
619 * Accept empty responses and responses consisting
620 * of the word "yes" as affirmative.
621 */
622 if (*p == '\0' || *p == '\n' ||
623 strcasecmp(p, "yes") == 0)
624 allowed = 1;
625 xfree(p);
626 }
627 }
628
629 unset_nonblock(client_fd);
630
631 buffer_init(&m);
632
633 buffer_put_int(&m, allowed);
634 buffer_put_int(&m, getpid());
635 if (ssh_msg_send(client_fd, /* version */0, &m) == -1) {
636 error("%s: client msg_send failed", __func__);
637 close(client_fd);
638 buffer_free(&m);
639 return;
640 }
641 buffer_clear(&m);
642
643 if (!allowed) {
644 error("Refused control connection");
645 close(client_fd);
646 buffer_free(&m);
647 return;
648 }
649
650 if (ssh_msg_recv(client_fd, &m) == -1) {
651 error("%s: client msg_recv failed", __func__);
652 close(client_fd);
653 buffer_free(&m);
654 return;
655 }
656
657 if ((ver = buffer_get_char(&m)) != 0) {
658 error("%s: wrong client version %d", __func__, ver);
659 buffer_free(&m);
660 close(client_fd);
661 return;
662 }
663
664 cctx = xmalloc(sizeof(*cctx));
665 memset(cctx, 0, sizeof(*cctx));
666
667 cctx->want_tty = buffer_get_int(&m);
668 cctx->want_subsys = buffer_get_int(&m);
669 cctx->term = buffer_get_string(&m, &len);
670
671 cmd = buffer_get_string(&m, &len);
672 buffer_init(&cctx->cmd);
673 buffer_append(&cctx->cmd, cmd, strlen(cmd));
674
675 env_len = buffer_get_int(&m);
676 env_len = MIN(env_len, 4096);
677 debug3("%s: receiving %d env vars", __func__, env_len);
678 if (env_len != 0) {
679 cctx->env = xmalloc(sizeof(*cctx->env) * (env_len + 1));
680 for (i = 0; i < env_len; i++)
681 cctx->env[i] = buffer_get_string(&m, &len);
682 cctx->env[i] = NULL;
683 }
684
685 debug2("%s: accepted tty %d, subsys %d, cmd %s", __func__,
686 cctx->want_tty, cctx->want_subsys, cmd);
687
688 /* Gather fds from client */
689 new_fd[0] = mm_receive_fd(client_fd);
690 new_fd[1] = mm_receive_fd(client_fd);
691 new_fd[2] = mm_receive_fd(client_fd);
692
693 debug2("%s: got fds stdin %d, stdout %d, stderr %d", __func__,
694 new_fd[0], new_fd[1], new_fd[2]);
695
696 /* Try to pick up ttymodes from client before it goes raw */
697 if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
698 error("%s: tcgetattr: %s", __func__, strerror(errno));
699
700 buffer_clear(&m);
701 if (ssh_msg_send(client_fd, /* version */0, &m) == -1) {
702 error("%s: client msg_send failed", __func__);
703 close(client_fd);
704 close(new_fd[0]);
705 close(new_fd[1]);
706 close(new_fd[2]);
707 buffer_free(&m);
708 return;
709 }
710 buffer_free(&m);
711
712 /* enable nonblocking unless tty */
713 if (!isatty(new_fd[0]))
714 set_nonblock(new_fd[0]);
715 if (!isatty(new_fd[1]))
716 set_nonblock(new_fd[1]);
717 if (!isatty(new_fd[2]))
718 set_nonblock(new_fd[2]);
719
720 set_nonblock(client_fd);
721
722 c = channel_new("session", SSH_CHANNEL_OPENING,
723 new_fd[0], new_fd[1], new_fd[2],
724 CHAN_SES_WINDOW_DEFAULT, CHAN_SES_PACKET_DEFAULT,
725 CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
726
727 /* XXX */
728 c->ctl_fd = client_fd;
729
730 debug3("%s: channel_new: %d", __func__, c->self);
731
732 channel_send_open(c->self);
733 channel_register_confirm(c->self, client_extra_session2_setup, cctx);
734}
735
736static void
509process_cmdline(void) 737process_cmdline(void)
510{ 738{
511 void (*handler)(int); 739 void (*handler)(int);
512 char *s, *cmd; 740 char *s, *cmd;
513 u_short fwd_port, fwd_host_port; 741 u_short fwd_port, fwd_host_port;
514 char buf[1024], sfwd_port[6], sfwd_host_port[6]; 742 char buf[1024], sfwd_port[6], sfwd_host_port[6];
743 int delete = 0;
515 int local = 0; 744 int local = 0;
516 745
517 leave_raw_mode(); 746 leave_raw_mode();
@@ -521,44 +750,77 @@ process_cmdline(void)
521 goto out; 750 goto out;
522 while (*s && isspace(*s)) 751 while (*s && isspace(*s))
523 s++; 752 s++;
524 if (*s == 0) 753 if (*s == '-')
754 s++; /* Skip cmdline '-', if any */
755 if (*s == '\0')
756 goto out;
757
758 if (*s == 'h' || *s == 'H' || *s == '?') {
759 logit("Commands:");
760 logit(" -Lport:host:hostport Request local forward");
761 logit(" -Rport:host:hostport Request remote forward");
762 logit(" -KRhostport Cancel remote forward");
525 goto out; 763 goto out;
526 if (strlen(s) < 2 || s[0] != '-' || !(s[1] == 'L' || s[1] == 'R')) { 764 }
765
766 if (*s == 'K') {
767 delete = 1;
768 s++;
769 }
770 if (*s != 'L' && *s != 'R') {
527 logit("Invalid command."); 771 logit("Invalid command.");
528 goto out; 772 goto out;
529 } 773 }
530 if (s[1] == 'L') 774 if (*s == 'L')
531 local = 1; 775 local = 1;
532 if (!local && !compat20) { 776 if (local && delete) {
777 logit("Not supported.");
778 goto out;
779 }
780 if ((!local || delete) && !compat20) {
533 logit("Not supported for SSH protocol version 1."); 781 logit("Not supported for SSH protocol version 1.");
534 goto out; 782 goto out;
535 } 783 }
536 s += 2; 784
785 s++;
537 while (*s && isspace(*s)) 786 while (*s && isspace(*s))
538 s++; 787 s++;
539 788
540 if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]", 789 if (delete) {
541 sfwd_port, buf, sfwd_host_port) != 3 && 790 if (sscanf(s, "%5[0-9]", sfwd_host_port) != 1) {
542 sscanf(s, "%5[0-9]/%255[^/]/%5[0-9]", 791 logit("Bad forwarding specification.");
543 sfwd_port, buf, sfwd_host_port) != 3) { 792 goto out;
544 logit("Bad forwarding specification."); 793 }
545 goto out; 794 if ((fwd_host_port = a2port(sfwd_host_port)) == 0) {
546 } 795 logit("Bad forwarding port(s).");
547 if ((fwd_port = a2port(sfwd_port)) == 0 || 796 goto out;
548 (fwd_host_port = a2port(sfwd_host_port)) == 0) { 797 }
549 logit("Bad forwarding port(s)."); 798 channel_request_rforward_cancel(fwd_host_port);
550 goto out; 799 } else {
551 } 800 if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]",
552 if (local) { 801 sfwd_port, buf, sfwd_host_port) != 3 &&
553 if (channel_setup_local_fwd_listener(fwd_port, buf, 802 sscanf(s, "%5[0-9]/%255[^/]/%5[0-9]",
554 fwd_host_port, options.gateway_ports) < 0) { 803 sfwd_port, buf, sfwd_host_port) != 3) {
555 logit("Port forwarding failed."); 804 logit("Bad forwarding specification.");
805 goto out;
806 }
807 if ((fwd_port = a2port(sfwd_port)) == 0 ||
808 (fwd_host_port = a2port(sfwd_host_port)) == 0) {
809 logit("Bad forwarding port(s).");
556 goto out; 810 goto out;
557 } 811 }
558 } else 812 if (local) {
559 channel_request_remote_forwarding(fwd_port, buf, 813 if (channel_setup_local_fwd_listener(fwd_port, buf,
560 fwd_host_port); 814 fwd_host_port, options.gateway_ports) < 0) {
561 logit("Forwarding port."); 815 logit("Port forwarding failed.");
816 goto out;
817 }
818 } else
819 channel_request_remote_forwarding(fwd_port, buf,
820 fwd_host_port);
821 logit("Forwarding port.");
822 }
823
562out: 824out:
563 signal(SIGINT, handler); 825 signal(SIGINT, handler);
564 enter_raw_mode(); 826 enter_raw_mode();
@@ -873,9 +1135,6 @@ simple_escape_filter(Channel *c, char *buf, int len)
873static void 1135static void
874client_channel_closed(int id, void *arg) 1136client_channel_closed(int id, void *arg)
875{ 1137{
876 if (id != session_ident)
877 error("client_channel_closed: id %d != session_ident %d",
878 id, session_ident);
879 channel_cancel_cleanup(id); 1138 channel_cancel_cleanup(id);
880 session_closed = 1; 1139 session_closed = 1;
881 leave_raw_mode(); 1140 leave_raw_mode();
@@ -893,7 +1152,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
893{ 1152{
894 fd_set *readset = NULL, *writeset = NULL; 1153 fd_set *readset = NULL, *writeset = NULL;
895 double start_time, total_time; 1154 double start_time, total_time;
896 int max_fd = 0, max_fd2 = 0, len, rekeying = 0, nalloc = 0; 1155 int max_fd = 0, max_fd2 = 0, len, rekeying = 0;
1156 u_int nalloc = 0;
897 char buf[100]; 1157 char buf[100];
898 1158
899 debug("Entering interactive session."); 1159 debug("Entering interactive session.");
@@ -909,6 +1169,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
909 connection_in = packet_get_connection_in(); 1169 connection_in = packet_get_connection_in();
910 connection_out = packet_get_connection_out(); 1170 connection_out = packet_get_connection_out();
911 max_fd = MAX(connection_in, connection_out); 1171 max_fd = MAX(connection_in, connection_out);
1172 if (control_fd != -1)
1173 max_fd = MAX(max_fd, control_fd);
912 1174
913 if (!compat20) { 1175 if (!compat20) {
914 /* enable nonblocking unless tty */ 1176 /* enable nonblocking unless tty */
@@ -1026,6 +1288,9 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1026 /* Buffer input from the connection. */ 1288 /* Buffer input from the connection. */
1027 client_process_net_input(readset); 1289 client_process_net_input(readset);
1028 1290
1291 /* Accept control connections. */
1292 client_process_control(readset);
1293
1029 if (quit_pending) 1294 if (quit_pending)
1030 break; 1295 break;
1031 1296
@@ -1357,7 +1622,7 @@ static void
1357client_input_channel_req(int type, u_int32_t seq, void *ctxt) 1622client_input_channel_req(int type, u_int32_t seq, void *ctxt)
1358{ 1623{
1359 Channel *c = NULL; 1624 Channel *c = NULL;
1360 int id, reply, success = 0; 1625 int exitval, id, reply, success = 0;
1361 char *rtype; 1626 char *rtype;
1362 1627
1363 id = packet_get_int(); 1628 id = packet_get_int();
@@ -1367,24 +1632,28 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt)
1367 debug("client_input_channel_req: channel %d rtype %s reply %d", 1632 debug("client_input_channel_req: channel %d rtype %s reply %d",
1368 id, rtype, reply); 1633 id, rtype, reply);
1369 1634
1370 if (session_ident == -1) { 1635 if (id == -1) {
1371 error("client_input_channel_req: no channel %d", session_ident); 1636 error("client_input_channel_req: request for channel -1");
1372 } else if (id != session_ident) { 1637 } else if ((c = channel_lookup(id)) == NULL) {
1373 error("client_input_channel_req: channel %d: wrong channel: %d",
1374 session_ident, id);
1375 }
1376 c = channel_lookup(id);
1377 if (c == NULL) {
1378 error("client_input_channel_req: channel %d: unknown channel", id); 1638 error("client_input_channel_req: channel %d: unknown channel", id);
1379 } else if (strcmp(rtype, "exit-status") == 0) { 1639 } else if (strcmp(rtype, "exit-status") == 0) {
1380 success = 1; 1640 exitval = packet_get_int();
1381 exit_status = packet_get_int(); 1641 if (id == session_ident) {
1642 success = 1;
1643 exit_status = exitval;
1644 } else if (c->ctl_fd == -1) {
1645 error("client_input_channel_req: unexpected channel %d",
1646 session_ident);
1647 } else {
1648 atomicio(vwrite, c->ctl_fd, &exitval, sizeof(exitval));
1649 success = 1;
1650 }
1382 packet_check_eom(); 1651 packet_check_eom();
1383 } 1652 }
1384 if (reply) { 1653 if (reply) {
1385 packet_start(success ? 1654 packet_start(success ?
1386 SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); 1655 SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
1387 packet_put_int(c->remote_id); 1656 packet_put_int(id);
1388 packet_send(); 1657 packet_send();
1389 } 1658 }
1390 xfree(rtype); 1659 xfree(rtype);
@@ -1409,6 +1678,97 @@ client_input_global_request(int type, u_int32_t seq, void *ctxt)
1409 xfree(rtype); 1678 xfree(rtype);
1410} 1679}
1411 1680
1681void
1682client_session2_setup(int id, int want_tty, int want_subsystem,
1683 const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env,
1684 dispatch_fn *subsys_repl)
1685{
1686 int len;
1687
1688 debug2("%s: id %d", __func__, id);
1689
1690 if (want_tty) {
1691 struct winsize ws;
1692 struct termios tio;
1693
1694 /* Store window size in the packet. */
1695 if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0)
1696 memset(&ws, 0, sizeof(ws));
1697
1698 channel_request_start(id, "pty-req", 0);
1699 packet_put_cstring(term != NULL ? term : "");
1700 packet_put_int(ws.ws_col);
1701 packet_put_int(ws.ws_row);
1702 packet_put_int(ws.ws_xpixel);
1703 packet_put_int(ws.ws_ypixel);
1704 tio = get_saved_tio();
1705 tty_make_modes(-1, tiop != NULL ? tiop : &tio);
1706 packet_send();
1707 /* XXX wait for reply */
1708 }
1709
1710 /* Transfer any environment variables from client to server */
1711 if (options.num_send_env != 0 && env != NULL) {
1712 int i, j, matched;
1713 char *name, *val;
1714
1715 debug("Sending environment.");
1716 for (i = 0; env[i] != NULL; i++) {
1717 /* Split */
1718 name = xstrdup(env[i]);
1719 if ((val = strchr(name, '=')) == NULL) {
1720 free(name);
1721 continue;
1722 }
1723 *val++ = '\0';
1724
1725 matched = 0;
1726 for (j = 0; j < options.num_send_env; j++) {
1727 if (match_pattern(name, options.send_env[j])) {
1728 matched = 1;
1729 break;
1730 }
1731 }
1732 if (!matched) {
1733 debug3("Ignored env %s", name);
1734 free(name);
1735 continue;
1736 }
1737
1738 debug("Sending env %s = %s", name, val);
1739 channel_request_start(id, "env", 0);
1740 packet_put_cstring(name);
1741 packet_put_cstring(val);
1742 packet_send();
1743 free(name);
1744 }
1745 }
1746
1747 len = buffer_len(cmd);
1748 if (len > 0) {
1749 if (len > 900)
1750 len = 900;
1751 if (want_subsystem) {
1752 debug("Sending subsystem: %.*s", len, (u_char*)buffer_ptr(cmd));
1753 channel_request_start(id, "subsystem", subsys_repl != NULL);
1754 if (subsys_repl != NULL) {
1755 /* register callback for reply */
1756 /* XXX we assume that client_loop has already been called */
1757 dispatch_set(SSH2_MSG_CHANNEL_FAILURE, subsys_repl);
1758 dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, subsys_repl);
1759 }
1760 } else {
1761 debug("Sending command: %.*s", len, (u_char*)buffer_ptr(cmd));
1762 channel_request_start(id, "exec", 0);
1763 }
1764 packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
1765 packet_send();
1766 } else {
1767 channel_request_start(id, "shell", 0);
1768 packet_send();
1769 }
1770}
1771
1412static void 1772static void
1413client_init_dispatch_20(void) 1773client_init_dispatch_20(void)
1414{ 1774{
@@ -1475,5 +1835,7 @@ cleanup_exit(int i)
1475{ 1835{
1476 leave_raw_mode(); 1836 leave_raw_mode();
1477 leave_non_blocking(); 1837 leave_non_blocking();
1838 if (options.control_path != NULL && control_fd != -1)
1839 unlink(options.control_path);
1478 _exit(i); 1840 _exit(i);
1479} 1841}