summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2005-05-25 11:01:01 +0000
committerColin Watson <cjwatson@debian.org>2005-05-25 11:01:01 +0000
commite88de75a1a236779a10e8ccbcc51d25308be8840 (patch)
tree7495477a2a7d0cac17a9fcded020b6ea816182ef /clientloop.c
parent30a0f9443782cd9d7308acd09430bf586186aa55 (diff)
parent5d05471f6657646d1d6500c7c43134462c407ee6 (diff)
Merge 4.0p1 to the trunk.
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c175
1 files changed, 106 insertions, 69 deletions
diff --git a/clientloop.c b/clientloop.c
index 1bcf4392f..90bdcbc39 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.130 2004/08/11 21:43:04 avsm Exp $"); 62RCSID("$OpenBSD: clientloop.c,v 1.135 2005/03/01 10:09:52 djm Exp $");
63 63
64#include "ssh.h" 64#include "ssh.h"
65#include "ssh1.h" 65#include "ssh1.h"
@@ -437,8 +437,6 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
437static void 437static void
438client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) 438client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
439{ 439{
440 struct winsize oldws, newws;
441
442 /* Flush stdout and stderr buffers. */ 440 /* Flush stdout and stderr buffers. */
443 if (buffer_len(bout) > 0) 441 if (buffer_len(bout) > 0)
444 atomicio(vwrite, fileno(stdout), buffer_ptr(bout), buffer_len(bout)); 442 atomicio(vwrite, fileno(stdout), buffer_ptr(bout), buffer_len(bout));
@@ -455,19 +453,11 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
455 buffer_free(bout); 453 buffer_free(bout);
456 buffer_free(berr); 454 buffer_free(berr);
457 455
458 /* Save old window size. */
459 ioctl(fileno(stdin), TIOCGWINSZ, &oldws);
460
461 /* Send the suspend signal to the program itself. */ 456 /* Send the suspend signal to the program itself. */
462 kill(getpid(), SIGTSTP); 457 kill(getpid(), SIGTSTP);
463 458
464 /* Check if the window size has changed. */ 459 /* Reset window sizes in case they have changed */
465 if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 && 460 received_window_change_signal = 1;
466 (oldws.ws_row != newws.ws_row ||
467 oldws.ws_col != newws.ws_col ||
468 oldws.ws_xpixel != newws.ws_xpixel ||
469 oldws.ws_ypixel != newws.ws_ypixel))
470 received_window_change_signal = 1;
471 461
472 /* OK, we have been continued by the user. Reinitialize buffers. */ 462 /* OK, we have been continued by the user. Reinitialize buffers. */
473 buffer_init(bin); 463 buffer_init(bin);
@@ -576,7 +566,7 @@ client_process_control(fd_set * readset)
576 struct sockaddr_storage addr; 566 struct sockaddr_storage addr;
577 struct confirm_ctx *cctx; 567 struct confirm_ctx *cctx;
578 char *cmd; 568 char *cmd;
579 u_int len, env_len; 569 u_int len, env_len, command, flags;
580 uid_t euid; 570 uid_t euid;
581 gid_t egid; 571 gid_t egid;
582 572
@@ -606,39 +596,74 @@ client_process_control(fd_set * readset)
606 return; 596 return;
607 } 597 }
608 598
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); 599 unset_nonblock(client_fd);
630 600
601 /* Read command */
631 buffer_init(&m); 602 buffer_init(&m);
603 if (ssh_msg_recv(client_fd, &m) == -1) {
604 error("%s: client msg_recv failed", __func__);
605 close(client_fd);
606 buffer_free(&m);
607 return;
608 }
609 if ((ver = buffer_get_char(&m)) != 1) {
610 error("%s: wrong client version %d", __func__, ver);
611 buffer_free(&m);
612 close(client_fd);
613 return;
614 }
615
616 allowed = 1;
617 command = buffer_get_int(&m);
618 flags = buffer_get_int(&m);
619
620 buffer_clear(&m);
632 621
622 switch (command) {
623 case SSHMUX_COMMAND_OPEN:
624 if (options.control_master == 2)
625 allowed = ask_permission("Allow shared connection "
626 "to %s? ", host);
627 /* continue below */
628 break;
629 case SSHMUX_COMMAND_TERMINATE:
630 if (options.control_master == 2)
631 allowed = ask_permission("Terminate shared connection "
632 "to %s? ", host);
633 if (allowed)
634 quit_pending = 1;
635 /* FALLTHROUGH */
636 case SSHMUX_COMMAND_ALIVE_CHECK:
637 /* Reply for SSHMUX_COMMAND_TERMINATE and ALIVE_CHECK */
638 buffer_clear(&m);
639 buffer_put_int(&m, allowed);
640 buffer_put_int(&m, getpid());
641 if (ssh_msg_send(client_fd, /* version */1, &m) == -1) {
642 error("%s: client msg_send failed", __func__);
643 close(client_fd);
644 buffer_free(&m);
645 return;
646 }
647 buffer_free(&m);
648 close(client_fd);
649 return;
650 default:
651 error("Unsupported command %d", command);
652 buffer_free(&m);
653 close(client_fd);
654 return;
655 }
656
657 /* Reply for SSHMUX_COMMAND_OPEN */
658 buffer_clear(&m);
633 buffer_put_int(&m, allowed); 659 buffer_put_int(&m, allowed);
634 buffer_put_int(&m, getpid()); 660 buffer_put_int(&m, getpid());
635 if (ssh_msg_send(client_fd, /* version */0, &m) == -1) { 661 if (ssh_msg_send(client_fd, /* version */1, &m) == -1) {
636 error("%s: client msg_send failed", __func__); 662 error("%s: client msg_send failed", __func__);
637 close(client_fd); 663 close(client_fd);
638 buffer_free(&m); 664 buffer_free(&m);
639 return; 665 return;
640 } 666 }
641 buffer_clear(&m);
642 667
643 if (!allowed) { 668 if (!allowed) {
644 error("Refused control connection"); 669 error("Refused control connection");
@@ -647,14 +672,14 @@ client_process_control(fd_set * readset)
647 return; 672 return;
648 } 673 }
649 674
675 buffer_clear(&m);
650 if (ssh_msg_recv(client_fd, &m) == -1) { 676 if (ssh_msg_recv(client_fd, &m) == -1) {
651 error("%s: client msg_recv failed", __func__); 677 error("%s: client msg_recv failed", __func__);
652 close(client_fd); 678 close(client_fd);
653 buffer_free(&m); 679 buffer_free(&m);
654 return; 680 return;
655 } 681 }
656 682 if ((ver = buffer_get_char(&m)) != 1) {
657 if ((ver = buffer_get_char(&m)) != 0) {
658 error("%s: wrong client version %d", __func__, ver); 683 error("%s: wrong client version %d", __func__, ver);
659 buffer_free(&m); 684 buffer_free(&m);
660 close(client_fd); 685 close(client_fd);
@@ -663,9 +688,8 @@ client_process_control(fd_set * readset)
663 688
664 cctx = xmalloc(sizeof(*cctx)); 689 cctx = xmalloc(sizeof(*cctx));
665 memset(cctx, 0, sizeof(*cctx)); 690 memset(cctx, 0, sizeof(*cctx));
666 691 cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0;
667 cctx->want_tty = buffer_get_int(&m); 692 cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0;
668 cctx->want_subsys = buffer_get_int(&m);
669 cctx->term = buffer_get_string(&m, &len); 693 cctx->term = buffer_get_string(&m, &len);
670 694
671 cmd = buffer_get_string(&m, &len); 695 cmd = buffer_get_string(&m, &len);
@@ -697,14 +721,21 @@ client_process_control(fd_set * readset)
697 if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1) 721 if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
698 error("%s: tcgetattr: %s", __func__, strerror(errno)); 722 error("%s: tcgetattr: %s", __func__, strerror(errno));
699 723
724 /* This roundtrip is just for synchronisation of ttymodes */
700 buffer_clear(&m); 725 buffer_clear(&m);
701 if (ssh_msg_send(client_fd, /* version */0, &m) == -1) { 726 if (ssh_msg_send(client_fd, /* version */1, &m) == -1) {
702 error("%s: client msg_send failed", __func__); 727 error("%s: client msg_send failed", __func__);
703 close(client_fd); 728 close(client_fd);
704 close(new_fd[0]); 729 close(new_fd[0]);
705 close(new_fd[1]); 730 close(new_fd[1]);
706 close(new_fd[2]); 731 close(new_fd[2]);
707 buffer_free(&m); 732 buffer_free(&m);
733 xfree(cctx->term);
734 if (env_len != 0) {
735 for (i = 0; i < env_len; i++)
736 xfree(cctx->env[i]);
737 xfree(cctx->env);
738 }
708 return; 739 return;
709 } 740 }
710 buffer_free(&m); 741 buffer_free(&m);
@@ -737,11 +768,11 @@ static void
737process_cmdline(void) 768process_cmdline(void)
738{ 769{
739 void (*handler)(int); 770 void (*handler)(int);
740 char *s, *cmd; 771 char *s, *cmd, *cancel_host;
741 u_short fwd_port, fwd_host_port;
742 char buf[1024], sfwd_port[6], sfwd_host_port[6];
743 int delete = 0; 772 int delete = 0;
744 int local = 0; 773 int local = 0;
774 u_short cancel_port;
775 Forward fwd;
745 776
746 leave_raw_mode(); 777 leave_raw_mode();
747 handler = signal(SIGINT, SIG_IGN); 778 handler = signal(SIGINT, SIG_IGN);
@@ -787,37 +818,38 @@ process_cmdline(void)
787 s++; 818 s++;
788 819
789 if (delete) { 820 if (delete) {
790 if (sscanf(s, "%5[0-9]", sfwd_host_port) != 1) { 821 cancel_port = 0;
791 logit("Bad forwarding specification."); 822 cancel_host = hpdelim(&s); /* may be NULL */
792 goto out; 823 if (s != NULL) {
824 cancel_port = a2port(s);
825 cancel_host = cleanhostname(cancel_host);
826 } else {
827 cancel_port = a2port(cancel_host);
828 cancel_host = NULL;
793 } 829 }
794 if ((fwd_host_port = a2port(sfwd_host_port)) == 0) { 830 if (cancel_port == 0) {
795 logit("Bad forwarding port(s)."); 831 logit("Bad forwarding close port");
796 goto out; 832 goto out;
797 } 833 }
798 channel_request_rforward_cancel(fwd_host_port); 834 channel_request_rforward_cancel(cancel_host, cancel_port);
799 } else { 835 } else {
800 if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]", 836 if (!parse_forward(&fwd, s)) {
801 sfwd_port, buf, sfwd_host_port) != 3 &&
802 sscanf(s, "%5[0-9]/%255[^/]/%5[0-9]",
803 sfwd_port, buf, sfwd_host_port) != 3) {
804 logit("Bad forwarding specification."); 837 logit("Bad forwarding specification.");
805 goto out; 838 goto out;
806 } 839 }
807 if ((fwd_port = a2port(sfwd_port)) == 0 ||
808 (fwd_host_port = a2port(sfwd_host_port)) == 0) {
809 logit("Bad forwarding port(s).");
810 goto out;
811 }
812 if (local) { 840 if (local) {
813 if (channel_setup_local_fwd_listener(fwd_port, buf, 841 if (channel_setup_local_fwd_listener(fwd.listen_host,
814 fwd_host_port, options.gateway_ports) < 0) { 842 fwd.listen_port, fwd.connect_host,
843 fwd.connect_port, options.gateway_ports) < 0) {
815 logit("Port forwarding failed."); 844 logit("Port forwarding failed.");
816 goto out; 845 goto out;
817 } 846 }
818 } else 847 } else {
819 channel_request_remote_forwarding(fwd_port, buf, 848 channel_request_remote_forwarding(fwd.listen_host,
820 fwd_host_port); 849 fwd.listen_port, fwd.connect_host,
850 fwd.connect_port);
851 }
852
821 logit("Forwarding port."); 853 logit("Forwarding port.");
822 } 854 }
823 855
@@ -1201,14 +1233,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1201 * Set signal handlers, (e.g. to restore non-blocking mode) 1233 * Set signal handlers, (e.g. to restore non-blocking mode)
1202 * but don't overwrite SIG_IGN, matches behaviour from rsh(1) 1234 * but don't overwrite SIG_IGN, matches behaviour from rsh(1)
1203 */ 1235 */
1236 if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
1237 signal(SIGHUP, signal_handler);
1204 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 1238 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
1205 signal(SIGINT, signal_handler); 1239 signal(SIGINT, signal_handler);
1206 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 1240 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
1207 signal(SIGQUIT, signal_handler); 1241 signal(SIGQUIT, signal_handler);
1208 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 1242 if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
1209 signal(SIGTERM, signal_handler); 1243 signal(SIGTERM, signal_handler);
1210 if (have_pty) 1244 signal(SIGWINCH, window_change_handler);
1211 signal(SIGWINCH, window_change_handler);
1212 1245
1213 if (have_pty) 1246 if (have_pty)
1214 enter_raw_mode(); 1247 enter_raw_mode();
@@ -1316,8 +1349,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1316 /* Terminate the session. */ 1349 /* Terminate the session. */
1317 1350
1318 /* Stop watching for window change. */ 1351 /* Stop watching for window change. */
1319 if (have_pty) 1352 signal(SIGWINCH, SIG_DFL);
1320 signal(SIGWINCH, SIG_DFL);
1321 1353
1322 channel_free_all(); 1354 channel_free_all();
1323 1355
@@ -1684,9 +1716,13 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
1684 dispatch_fn *subsys_repl) 1716 dispatch_fn *subsys_repl)
1685{ 1717{
1686 int len; 1718 int len;
1719 Channel *c = NULL;
1687 1720
1688 debug2("%s: id %d", __func__, id); 1721 debug2("%s: id %d", __func__, id);
1689 1722
1723 if ((c = channel_lookup(id)) == NULL)
1724 fatal("client_session2_setup: channel %d: unknown channel", id);
1725
1690 if (want_tty) { 1726 if (want_tty) {
1691 struct winsize ws; 1727 struct winsize ws;
1692 struct termios tio; 1728 struct termios tio;
@@ -1705,6 +1741,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
1705 tty_make_modes(-1, tiop != NULL ? tiop : &tio); 1741 tty_make_modes(-1, tiop != NULL ? tiop : &tio);
1706 packet_send(); 1742 packet_send();
1707 /* XXX wait for reply */ 1743 /* XXX wait for reply */
1744 c->client_tty = 1;
1708 } 1745 }
1709 1746
1710 /* Transfer any environment variables from client to server */ 1747 /* Transfer any environment variables from client to server */