summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c755
1 files changed, 346 insertions, 409 deletions
diff --git a/clientloop.c b/clientloop.c
index b57fda042..f10fab769 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.c,v 1.181 2007/08/15 08:14:46 markus Exp $ */ 1/* $OpenBSD: clientloop.c,v 1.201 2008/07/16 11:51:14 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -86,6 +86,7 @@
86#include <pwd.h> 86#include <pwd.h>
87#include <unistd.h> 87#include <unistd.h>
88 88
89#include "openbsd-compat/sys-queue.h"
89#include "xmalloc.h" 90#include "xmalloc.h"
90#include "ssh.h" 91#include "ssh.h"
91#include "ssh1.h" 92#include "ssh1.h"
@@ -120,7 +121,7 @@ extern int stdin_null_flag;
120extern int no_shell_flag; 121extern int no_shell_flag;
121 122
122/* Control socket */ 123/* Control socket */
123extern int control_fd; 124extern int muxserver_sock;
124 125
125/* 126/*
126 * Name of the host we are connecting to. This is the name given on the 127 * Name of the host we are connecting to. This is the name given on the
@@ -143,36 +144,46 @@ static int in_non_blocking_mode = 0;
143 144
144/* Common data for the client loop code. */ 145/* Common data for the client loop code. */
145static volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ 146static volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
146static int escape_char; /* Escape character. */ 147static int escape_char1; /* Escape character. (proto1 only) */
147static int escape_pending; /* Last character was the escape character */ 148static int escape_pending1; /* Last character was an escape (proto1 only) */
148static int last_was_cr; /* Last character was a newline. */ 149static int last_was_cr; /* Last character was a newline. */
149static int exit_status; /* Used to store the exit status of the command. */ 150static int exit_status; /* Used to store the command exit status. */
150static int stdin_eof; /* EOF has been encountered on standard error. */ 151static int stdin_eof; /* EOF has been encountered on stderr. */
151static Buffer stdin_buffer; /* Buffer for stdin data. */ 152static Buffer stdin_buffer; /* Buffer for stdin data. */
152static Buffer stdout_buffer; /* Buffer for stdout data. */ 153static Buffer stdout_buffer; /* Buffer for stdout data. */
153static Buffer stderr_buffer; /* Buffer for stderr data. */ 154static Buffer stderr_buffer; /* Buffer for stderr data. */
154static u_long stdin_bytes, stdout_bytes, stderr_bytes;
155static u_int buffer_high;/* Soft max buffer size. */ 155static u_int buffer_high;/* Soft max buffer size. */
156static int connection_in; /* Connection to server (input). */ 156static int connection_in; /* Connection to server (input). */
157static int connection_out; /* Connection to server (output). */ 157static int connection_out; /* Connection to server (output). */
158static int need_rekeying; /* Set to non-zero if rekeying is requested. */ 158static int need_rekeying; /* Set to non-zero if rekeying is requested. */
159static int session_closed = 0; /* In SSH2: login session closed. */ 159static int session_closed = 0; /* In SSH2: login session closed. */
160static int server_alive_timeouts = 0;
161 160
162static void client_init_dispatch(void); 161static void client_init_dispatch(void);
163int session_ident = -1; 162int session_ident = -1;
164 163
165struct confirm_ctx { 164/* Track escape per proto2 channel */
166 int want_tty; 165struct escape_filter_ctx {
167 int want_subsys; 166 int escape_pending;
168 int want_x_fwd; 167 int escape_char;
169 int want_agent_fwd;
170 Buffer cmd;
171 char *term;
172 struct termios tio;
173 char **env;
174}; 168};
175 169
170/* Context for channel confirmation replies */
171struct channel_reply_ctx {
172 const char *request_type;
173 int id, do_close;
174};
175
176/* Global request success/failure callbacks */
177struct global_confirm {
178 TAILQ_ENTRY(global_confirm) entry;
179 global_confirm_cb *cb;
180 void *ctx;
181 int ref_count;
182};
183TAILQ_HEAD(global_confirms, global_confirm);
184static struct global_confirms global_confirms =
185 TAILQ_HEAD_INITIALIZER(global_confirms);
186
176/*XXX*/ 187/*XXX*/
177extern Kex *xxx_kex; 188extern Kex *xxx_kex;
178 189
@@ -380,7 +391,10 @@ client_check_initial_eof_on_stdin(void)
380 /* Check for immediate EOF on stdin. */ 391 /* Check for immediate EOF on stdin. */
381 len = read(fileno(stdin), buf, 1); 392 len = read(fileno(stdin), buf, 1);
382 if (len == 0) { 393 if (len == 0) {
383 /* EOF. Record that we have seen it and send EOF to server. */ 394 /*
395 * EOF. Record that we have seen it and send
396 * EOF to server.
397 */
384 debug("Sending eof."); 398 debug("Sending eof.");
385 stdin_eof = 1; 399 stdin_eof = 1;
386 packet_start(SSH_CMSG_EOF); 400 packet_start(SSH_CMSG_EOF);
@@ -391,8 +405,8 @@ client_check_initial_eof_on_stdin(void)
391 * and also process it as an escape character if 405 * and also process it as an escape character if
392 * appropriate. 406 * appropriate.
393 */ 407 */
394 if ((u_char) buf[0] == escape_char) 408 if ((u_char) buf[0] == escape_char1)
395 escape_pending = 1; 409 escape_pending1 = 1;
396 else 410 else
397 buffer_append(&stdin_buffer, buf, 1); 411 buffer_append(&stdin_buffer, buf, 1);
398 } 412 }
@@ -422,7 +436,6 @@ client_make_packets_from_stdin_data(void)
422 packet_put_string(buffer_ptr(&stdin_buffer), len); 436 packet_put_string(buffer_ptr(&stdin_buffer), len);
423 packet_send(); 437 packet_send();
424 buffer_consume(&stdin_buffer, len); 438 buffer_consume(&stdin_buffer, len);
425 stdin_bytes += len;
426 /* If we have a pending EOF, send it now. */ 439 /* If we have a pending EOF, send it now. */
427 if (stdin_eof && buffer_len(&stdin_buffer) == 0) { 440 if (stdin_eof && buffer_len(&stdin_buffer) == 0) {
428 packet_start(SSH_CMSG_EOF); 441 packet_start(SSH_CMSG_EOF);
@@ -467,14 +480,25 @@ client_check_window_change(void)
467static void 480static void
468client_global_request_reply(int type, u_int32_t seq, void *ctxt) 481client_global_request_reply(int type, u_int32_t seq, void *ctxt)
469{ 482{
470 server_alive_timeouts = 0; 483 struct global_confirm *gc;
471 client_global_request_reply_fwd(type, seq, ctxt); 484
485 if ((gc = TAILQ_FIRST(&global_confirms)) == NULL)
486 return;
487 if (gc->cb != NULL)
488 gc->cb(type, seq, gc->ctx);
489 if (--gc->ref_count <= 0) {
490 TAILQ_REMOVE(&global_confirms, gc, entry);
491 bzero(gc, sizeof(*gc));
492 xfree(gc);
493 }
494
495 keep_alive_timeouts = 0;
472} 496}
473 497
474static void 498static void
475server_alive_check(void) 499server_alive_check(void)
476{ 500{
477 if (++server_alive_timeouts > options.server_alive_count_max) { 501 if (++keep_alive_timeouts > options.server_alive_count_max) {
478 logit("Timeout, server not responding."); 502 logit("Timeout, server not responding.");
479 cleanup_exit(255); 503 cleanup_exit(255);
480 } 504 }
@@ -482,6 +506,8 @@ server_alive_check(void)
482 packet_put_cstring("keepalive@openssh.com"); 506 packet_put_cstring("keepalive@openssh.com");
483 packet_put_char(1); /* boolean: want reply */ 507 packet_put_char(1); /* boolean: want reply */
484 packet_send(); 508 packet_send();
509 /* Insert an empty placeholder to maintain ordering */
510 client_register_global_confirm(NULL, NULL);
485} 511}
486 512
487/* 513/*
@@ -533,8 +559,8 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
533 if (packet_have_data_to_write()) 559 if (packet_have_data_to_write())
534 FD_SET(connection_out, *writesetp); 560 FD_SET(connection_out, *writesetp);
535 561
536 if (control_fd != -1) 562 if (muxserver_sock != -1)
537 FD_SET(control_fd, *readsetp); 563 FD_SET(muxserver_sock, *readsetp);
538 564
539 /* 565 /*
540 * Wait for something to happen. This will suspend the process until 566 * Wait for something to happen. This will suspend the process until
@@ -576,9 +602,11 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
576{ 602{
577 /* Flush stdout and stderr buffers. */ 603 /* Flush stdout and stderr buffers. */
578 if (buffer_len(bout) > 0) 604 if (buffer_len(bout) > 0)
579 atomicio(vwrite, fileno(stdout), buffer_ptr(bout), buffer_len(bout)); 605 atomicio(vwrite, fileno(stdout), buffer_ptr(bout),
606 buffer_len(bout));
580 if (buffer_len(berr) > 0) 607 if (buffer_len(berr) > 0)
581 atomicio(vwrite, fileno(stderr), buffer_ptr(berr), buffer_len(berr)); 608 atomicio(vwrite, fileno(stderr), buffer_ptr(berr),
609 buffer_len(berr));
582 610
583 leave_raw_mode(); 611 leave_raw_mode();
584 612
@@ -618,9 +646,13 @@ client_process_net_input(fd_set *readset)
618 /* Read as much as possible. */ 646 /* Read as much as possible. */
619 len = read(connection_in, buf, sizeof(buf)); 647 len = read(connection_in, buf, sizeof(buf));
620 if (len == 0) { 648 if (len == 0) {
621 /* Received EOF. The remote host has closed the connection. */ 649 /*
622 snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n", 650 * Received EOF. The remote host has closed the
623 host); 651 * connection.
652 */
653 snprintf(buf, sizeof buf,
654 "Connection to %.300s closed by remote host.\r\n",
655 host);
624 buffer_append(&stderr_buffer, buf, strlen(buf)); 656 buffer_append(&stderr_buffer, buf, strlen(buf));
625 quit_pending = 1; 657 quit_pending = 1;
626 return; 658 return;
@@ -629,13 +661,18 @@ client_process_net_input(fd_set *readset)
629 * There is a kernel bug on Solaris that causes select to 661 * There is a kernel bug on Solaris that causes select to
630 * sometimes wake up even though there is no data available. 662 * sometimes wake up even though there is no data available.
631 */ 663 */
632 if (len < 0 && (errno == EAGAIN || errno == EINTR)) 664 if (len < 0 &&
665 (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
633 len = 0; 666 len = 0;
634 667
635 if (len < 0) { 668 if (len < 0) {
636 /* An error has encountered. Perhaps there is a network problem. */ 669 /*
637 snprintf(buf, sizeof buf, "Read from remote host %.300s: %.100s\r\n", 670 * An error has encountered. Perhaps there is a
638 host, strerror(errno)); 671 * network problem.
672 */
673 snprintf(buf, sizeof buf,
674 "Read from remote host %.300s: %.100s\r\n",
675 host, strerror(errno));
639 buffer_append(&stderr_buffer, buf, strlen(buf)); 676 buffer_append(&stderr_buffer, buf, strlen(buf));
640 quit_pending = 1; 677 quit_pending = 1;
641 return; 678 return;
@@ -645,289 +682,81 @@ client_process_net_input(fd_set *readset)
645} 682}
646 683
647static void 684static void
648client_subsystem_reply(int type, u_int32_t seq, void *ctxt) 685client_status_confirm(int type, Channel *c, void *ctx)
649{ 686{
650 int id; 687 struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx;
651 Channel *c; 688 char errmsg[256];
652 689 int tochan;
653 id = packet_get_int(); 690
654 packet_check_eom(); 691 /* XXX supress on mux _client_ quietmode */
655 692 tochan = options.log_level >= SYSLOG_LEVEL_ERROR &&
656 if ((c = channel_lookup(id)) == NULL) { 693 c->ctl_fd != -1 && c->extended_usage == CHAN_EXTENDED_WRITE;
657 error("%s: no channel for id %d", __func__, id); 694
658 return; 695 if (type == SSH2_MSG_CHANNEL_SUCCESS) {
659 } 696 debug2("%s request accepted on channel %d",
660 697 cr->request_type, c->self);
661 if (type == SSH2_MSG_CHANNEL_SUCCESS) 698 } else if (type == SSH2_MSG_CHANNEL_FAILURE) {
662 debug2("Request suceeded on channel %d", id); 699 if (tochan) {
663 else if (type == SSH2_MSG_CHANNEL_FAILURE) { 700 snprintf(errmsg, sizeof(errmsg),
664 error("Request failed on channel %d", id); 701 "%s request failed\r\n", cr->request_type);
665 channel_free(c); 702 } else {
703 snprintf(errmsg, sizeof(errmsg),
704 "%s request failed on channel %d",
705 cr->request_type, c->self);
706 }
707 /* If error occurred on primary session channel, then exit */
708 if (cr->do_close && c->self == session_ident)
709 fatal("%s", errmsg);
710 /* If error occurred on mux client, append to their stderr */
711 if (tochan)
712 buffer_append(&c->extended, errmsg, strlen(errmsg));
713 else
714 error("%s", errmsg);
715 if (cr->do_close) {
716 chan_read_failed(c);
717 chan_write_failed(c);
718 }
666 } 719 }
720 xfree(cr);
667} 721}
668 722
669static void 723static void
670client_extra_session2_setup(int id, void *arg) 724client_abandon_status_confirm(Channel *c, void *ctx)
671{ 725{
672 struct confirm_ctx *cctx = arg; 726 xfree(ctx);
673 const char *display;
674 Channel *c;
675 int i;
676
677 if (cctx == NULL)
678 fatal("%s: cctx == NULL", __func__);
679 if ((c = channel_lookup(id)) == NULL)
680 fatal("%s: no channel for id %d", __func__, id);
681
682 display = getenv("DISPLAY");
683 if (cctx->want_x_fwd && options.forward_x11 && display != NULL) {
684 char *proto, *data;
685 /* Get reasonable local authentication information. */
686 client_x11_get_proto(display, options.xauth_location,
687 options.forward_x11_trusted, &proto, &data);
688 /* Request forwarding with authentication spoofing. */
689 debug("Requesting X11 forwarding with authentication spoofing.");
690 x11_request_forwarding_with_spoofing(id, display, proto, data);
691 /* XXX wait for reply */
692 }
693
694 if (cctx->want_agent_fwd && options.forward_agent) {
695 debug("Requesting authentication agent forwarding.");
696 channel_request_start(id, "auth-agent-req@openssh.com", 0);
697 packet_send();
698 }
699
700 client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
701 cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env,
702 client_subsystem_reply);
703
704 c->confirm_ctx = NULL;
705 buffer_free(&cctx->cmd);
706 xfree(cctx->term);
707 if (cctx->env != NULL) {
708 for (i = 0; cctx->env[i] != NULL; i++)
709 xfree(cctx->env[i]);
710 xfree(cctx->env);
711 }
712 xfree(cctx);
713} 727}
714 728
715static void 729static void
716client_process_control(fd_set *readset) 730client_expect_confirm(int id, const char *request, int do_close)
717{ 731{
718 Buffer m; 732 struct channel_reply_ctx *cr = xmalloc(sizeof(*cr));
719 Channel *c;
720 int client_fd, new_fd[3], ver, allowed, window, packetmax;
721 socklen_t addrlen;
722 struct sockaddr_storage addr;
723 struct confirm_ctx *cctx;
724 char *cmd;
725 u_int i, len, env_len, command, flags;
726 uid_t euid;
727 gid_t egid;
728
729 /*
730 * Accept connection on control socket
731 */
732 if (control_fd == -1 || !FD_ISSET(control_fd, readset))
733 return;
734
735 memset(&addr, 0, sizeof(addr));
736 addrlen = sizeof(addr);
737 if ((client_fd = accept(control_fd,
738 (struct sockaddr*)&addr, &addrlen)) == -1) {
739 error("%s accept: %s", __func__, strerror(errno));
740 return;
741 }
742
743 if (getpeereid(client_fd, &euid, &egid) < 0) {
744 error("%s getpeereid failed: %s", __func__, strerror(errno));
745 close(client_fd);
746 return;
747 }
748 if ((euid != 0) && (getuid() != euid)) {
749 error("control mode uid mismatch: peer euid %u != uid %u",
750 (u_int) euid, (u_int) getuid());
751 close(client_fd);
752 return;
753 }
754
755 unset_nonblock(client_fd);
756
757 /* Read command */
758 buffer_init(&m);
759 if (ssh_msg_recv(client_fd, &m) == -1) {
760 error("%s: client msg_recv failed", __func__);
761 close(client_fd);
762 buffer_free(&m);
763 return;
764 }
765 if ((ver = buffer_get_char(&m)) != SSHMUX_VER) {
766 error("%s: wrong client version %d", __func__, ver);
767 buffer_free(&m);
768 close(client_fd);
769 return;
770 }
771
772 allowed = 1;
773 command = buffer_get_int(&m);
774 flags = buffer_get_int(&m);
775
776 buffer_clear(&m);
777
778 switch (command) {
779 case SSHMUX_COMMAND_OPEN:
780 if (options.control_master == SSHCTL_MASTER_ASK ||
781 options.control_master == SSHCTL_MASTER_AUTO_ASK)
782 allowed = ask_permission("Allow shared connection "
783 "to %s? ", host);
784 /* continue below */
785 break;
786 case SSHMUX_COMMAND_TERMINATE:
787 if (options.control_master == SSHCTL_MASTER_ASK ||
788 options.control_master == SSHCTL_MASTER_AUTO_ASK)
789 allowed = ask_permission("Terminate shared connection "
790 "to %s? ", host);
791 if (allowed)
792 quit_pending = 1;
793 /* FALLTHROUGH */
794 case SSHMUX_COMMAND_ALIVE_CHECK:
795 /* Reply for SSHMUX_COMMAND_TERMINATE and ALIVE_CHECK */
796 buffer_clear(&m);
797 buffer_put_int(&m, allowed);
798 buffer_put_int(&m, getpid());
799 if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
800 error("%s: client msg_send failed", __func__);
801 close(client_fd);
802 buffer_free(&m);
803 return;
804 }
805 buffer_free(&m);
806 close(client_fd);
807 return;
808 default:
809 error("Unsupported command %d", command);
810 buffer_free(&m);
811 close(client_fd);
812 return;
813 }
814
815 /* Reply for SSHMUX_COMMAND_OPEN */
816 buffer_clear(&m);
817 buffer_put_int(&m, allowed);
818 buffer_put_int(&m, getpid());
819 if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
820 error("%s: client msg_send failed", __func__);
821 close(client_fd);
822 buffer_free(&m);
823 return;
824 }
825
826 if (!allowed) {
827 error("Refused control connection");
828 close(client_fd);
829 buffer_free(&m);
830 return;
831 }
832 733
833 buffer_clear(&m); 734 cr->request_type = request;
834 if (ssh_msg_recv(client_fd, &m) == -1) { 735 cr->do_close = do_close;
835 error("%s: client msg_recv failed", __func__);
836 close(client_fd);
837 buffer_free(&m);
838 return;
839 }
840 if ((ver = buffer_get_char(&m)) != SSHMUX_VER) {
841 error("%s: wrong client version %d", __func__, ver);
842 buffer_free(&m);
843 close(client_fd);
844 return;
845 }
846 736
847 cctx = xcalloc(1, sizeof(*cctx)); 737 channel_register_status_confirm(id, client_status_confirm,
848 cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0; 738 client_abandon_status_confirm, cr);
849 cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0; 739}
850 cctx->want_x_fwd = (flags & SSHMUX_FLAG_X11_FWD) != 0;
851 cctx->want_agent_fwd = (flags & SSHMUX_FLAG_AGENT_FWD) != 0;
852 cctx->term = buffer_get_string(&m, &len);
853
854 cmd = buffer_get_string(&m, &len);
855 buffer_init(&cctx->cmd);
856 buffer_append(&cctx->cmd, cmd, strlen(cmd));
857
858 env_len = buffer_get_int(&m);
859 env_len = MIN(env_len, 4096);
860 debug3("%s: receiving %d env vars", __func__, env_len);
861 if (env_len != 0) {
862 cctx->env = xcalloc(env_len + 1, sizeof(*cctx->env));
863 for (i = 0; i < env_len; i++)
864 cctx->env[i] = buffer_get_string(&m, &len);
865 cctx->env[i] = NULL;
866 }
867 740
868 debug2("%s: accepted tty %d, subsys %d, cmd %s", __func__, 741void
869 cctx->want_tty, cctx->want_subsys, cmd); 742client_register_global_confirm(global_confirm_cb *cb, void *ctx)
870 xfree(cmd); 743{
871 744 struct global_confirm *gc, *last_gc;
872 /* Gather fds from client */ 745
873 new_fd[0] = mm_receive_fd(client_fd); 746 /* Coalesce identical callbacks */
874 new_fd[1] = mm_receive_fd(client_fd); 747 last_gc = TAILQ_LAST(&global_confirms, global_confirms);
875 new_fd[2] = mm_receive_fd(client_fd); 748 if (last_gc && last_gc->cb == cb && last_gc->ctx == ctx) {
876 749 if (++last_gc->ref_count >= INT_MAX)
877 debug2("%s: got fds stdin %d, stdout %d, stderr %d", __func__, 750 fatal("%s: last_gc->ref_count = %d",
878 new_fd[0], new_fd[1], new_fd[2]); 751 __func__, last_gc->ref_count);
879
880 /* Try to pick up ttymodes from client before it goes raw */
881 if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
882 error("%s: tcgetattr: %s", __func__, strerror(errno));
883
884 /* This roundtrip is just for synchronisation of ttymodes */
885 buffer_clear(&m);
886 if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
887 error("%s: client msg_send failed", __func__);
888 close(client_fd);
889 close(new_fd[0]);
890 close(new_fd[1]);
891 close(new_fd[2]);
892 buffer_free(&m);
893 xfree(cctx->term);
894 if (env_len != 0) {
895 for (i = 0; i < env_len; i++)
896 xfree(cctx->env[i]);
897 xfree(cctx->env);
898 }
899 return; 752 return;
900 } 753 }
901 buffer_free(&m);
902
903 /* enable nonblocking unless tty */
904 if (!isatty(new_fd[0]))
905 set_nonblock(new_fd[0]);
906 if (!isatty(new_fd[1]))
907 set_nonblock(new_fd[1]);
908 if (!isatty(new_fd[2]))
909 set_nonblock(new_fd[2]);
910
911 set_nonblock(client_fd);
912
913 window = CHAN_SES_WINDOW_DEFAULT;
914 packetmax = CHAN_SES_PACKET_DEFAULT;
915 if (cctx->want_tty) {
916 window >>= 1;
917 packetmax >>= 1;
918 }
919
920 c = channel_new("session", SSH_CHANNEL_OPENING,
921 new_fd[0], new_fd[1], new_fd[2], window, packetmax,
922 CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
923 754
924 /* XXX */ 755 gc = xmalloc(sizeof(*gc));
925 c->ctl_fd = client_fd; 756 gc->cb = cb;
926 757 gc->ctx = ctx;
927 debug3("%s: channel_new: %d", __func__, c->self); 758 gc->ref_count = 1;
928 759 TAILQ_INSERT_TAIL(&global_confirms, gc, entry);
929 channel_send_open(c->self);
930 channel_register_confirm(c->self, client_extra_session2_setup, cctx);
931} 760}
932 761
933static void 762static void
@@ -940,6 +769,9 @@ process_cmdline(void)
940 u_short cancel_port; 769 u_short cancel_port;
941 Forward fwd; 770 Forward fwd;
942 771
772 bzero(&fwd, sizeof(fwd));
773 fwd.listen_host = fwd.connect_host = NULL;
774
943 leave_raw_mode(); 775 leave_raw_mode();
944 handler = signal(SIGINT, SIG_IGN); 776 handler = signal(SIGINT, SIG_IGN);
945 cmd = s = read_passphrase("\r\nssh> ", RP_ECHO); 777 cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);
@@ -1039,11 +871,18 @@ out:
1039 enter_raw_mode(); 871 enter_raw_mode();
1040 if (cmd) 872 if (cmd)
1041 xfree(cmd); 873 xfree(cmd);
874 if (fwd.listen_host != NULL)
875 xfree(fwd.listen_host);
876 if (fwd.connect_host != NULL)
877 xfree(fwd.connect_host);
1042} 878}
1043 879
1044/* process the characters one by one */ 880/*
881 * Process the characters one by one, call with c==NULL for proto1 case.
882 */
1045static int 883static int
1046process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len) 884process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
885 char *buf, int len)
1047{ 886{
1048 char string[1024]; 887 char string[1024];
1049 pid_t pid; 888 pid_t pid;
@@ -1051,7 +890,20 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
1051 u_int i; 890 u_int i;
1052 u_char ch; 891 u_char ch;
1053 char *s; 892 char *s;
893 int *escape_pendingp, escape_char;
894 struct escape_filter_ctx *efc;
1054 895
896 if (c == NULL) {
897 escape_pendingp = &escape_pending1;
898 escape_char = escape_char1;
899 } else {
900 if (c->filter_ctx == NULL)
901 return 0;
902 efc = (struct escape_filter_ctx *)c->filter_ctx;
903 escape_pendingp = &efc->escape_pending;
904 escape_char = efc->escape_char;
905 }
906
1055 if (len <= 0) 907 if (len <= 0)
1056 return (0); 908 return (0);
1057 909
@@ -1059,25 +911,42 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
1059 /* Get one character at a time. */ 911 /* Get one character at a time. */
1060 ch = buf[i]; 912 ch = buf[i];
1061 913
1062 if (escape_pending) { 914 if (*escape_pendingp) {
1063 /* We have previously seen an escape character. */ 915 /* We have previously seen an escape character. */
1064 /* Clear the flag now. */ 916 /* Clear the flag now. */
1065 escape_pending = 0; 917 *escape_pendingp = 0;
1066 918
1067 /* Process the escaped character. */ 919 /* Process the escaped character. */
1068 switch (ch) { 920 switch (ch) {
1069 case '.': 921 case '.':
1070 /* Terminate the connection. */ 922 /* Terminate the connection. */
1071 snprintf(string, sizeof string, "%c.\r\n", escape_char); 923 snprintf(string, sizeof string, "%c.\r\n",
924 escape_char);
1072 buffer_append(berr, string, strlen(string)); 925 buffer_append(berr, string, strlen(string));
1073 926
1074 quit_pending = 1; 927 if (c && c->ctl_fd != -1) {
928 chan_read_failed(c);
929 chan_write_failed(c);
930 return 0;
931 } else
932 quit_pending = 1;
1075 return -1; 933 return -1;
1076 934
1077 case 'Z' - 64: 935 case 'Z' - 64:
1078 /* Suspend the program. */ 936 /* XXX support this for mux clients */
1079 /* Print a message to that effect to the user. */ 937 if (c && c->ctl_fd != -1) {
1080 snprintf(string, sizeof string, "%c^Z [suspend ssh]\r\n", escape_char); 938 noescape:
939 snprintf(string, sizeof string,
940 "%c%c escape not available to "
941 "multiplexed sessions\r\n",
942 escape_char, ch);
943 buffer_append(berr, string,
944 strlen(string));
945 continue;
946 }
947 /* Suspend the program. Inform the user */
948 snprintf(string, sizeof string,
949 "%c^Z [suspend ssh]\r\n", escape_char);
1081 buffer_append(berr, string, strlen(string)); 950 buffer_append(berr, string, strlen(string));
1082 951
1083 /* Restore terminal modes and suspend. */ 952 /* Restore terminal modes and suspend. */
@@ -1102,16 +971,20 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
1102 case 'R': 971 case 'R':
1103 if (compat20) { 972 if (compat20) {
1104 if (datafellows & SSH_BUG_NOREKEY) 973 if (datafellows & SSH_BUG_NOREKEY)
1105 logit("Server does not support re-keying"); 974 logit("Server does not "
975 "support re-keying");
1106 else 976 else
1107 need_rekeying = 1; 977 need_rekeying = 1;
1108 } 978 }
1109 continue; 979 continue;
1110 980
1111 case '&': 981 case '&':
982 if (c && c->ctl_fd != -1)
983 goto noescape;
1112 /* 984 /*
1113 * Detach the program (continue to serve connections, 985 * Detach the program (continue to serve
1114 * but put in background and no more new connections). 986 * connections, but put in background and no
987 * more new connections).
1115 */ 988 */
1116 /* Restore tty modes. */ 989 /* Restore tty modes. */
1117 leave_raw_mode(); 990 leave_raw_mode();
@@ -1140,9 +1013,9 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
1140 return -1; 1013 return -1;
1141 } else if (!stdin_eof) { 1014 } else if (!stdin_eof) {
1142 /* 1015 /*
1143 * Sending SSH_CMSG_EOF alone does not always appear 1016 * Sending SSH_CMSG_EOF alone does not
1144 * to be enough. So we try to send an EOF character 1017 * always appear to be enough. So we
1145 * first. 1018 * try to send an EOF character first.
1146 */ 1019 */
1147 packet_start(SSH_CMSG_STDIN_DATA); 1020 packet_start(SSH_CMSG_STDIN_DATA);
1148 packet_put_string("\004", 1); 1021 packet_put_string("\004", 1);
@@ -1157,27 +1030,50 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
1157 continue; 1030 continue;
1158 1031
1159 case '?': 1032 case '?':
1160 snprintf(string, sizeof string, 1033 if (c && c->ctl_fd != -1) {
1034 snprintf(string, sizeof string,
1161"%c?\r\n\ 1035"%c?\r\n\
1162Supported escape sequences:\r\n\ 1036Supported escape sequences:\r\n\
1163%c. - terminate connection\r\n\ 1037 %c. - terminate session\r\n\
1164%cB - send a BREAK to the remote system\r\n\ 1038 %cB - send a BREAK to the remote system\r\n\
1165%cC - open a command line\r\n\ 1039 %cC - open a command line\r\n\
1166%cR - Request rekey (SSH protocol 2 only)\r\n\ 1040 %cR - Request rekey (SSH protocol 2 only)\r\n\
1167%c^Z - suspend ssh\r\n\ 1041 %c# - list forwarded connections\r\n\
1168%c# - list forwarded connections\r\n\ 1042 %c? - this message\r\n\
1169%c& - background ssh (when waiting for connections to terminate)\r\n\ 1043 %c%c - send the escape character by typing it twice\r\n\
1170%c? - this message\r\n\
1171%c%c - send the escape character by typing it twice\r\n\
1172(Note that escapes are only recognized immediately after newline.)\r\n", 1044(Note that escapes are only recognized immediately after newline.)\r\n",
1173 escape_char, escape_char, escape_char, escape_char, 1045 escape_char, escape_char,
1174 escape_char, escape_char, escape_char, escape_char, 1046 escape_char, escape_char,
1175 escape_char, escape_char, escape_char); 1047 escape_char, escape_char,
1048 escape_char, escape_char,
1049 escape_char);
1050 } else {
1051 snprintf(string, sizeof string,
1052"%c?\r\n\
1053Supported escape sequences:\r\n\
1054 %c. - terminate connection (and any multiplexed sessions)\r\n\
1055 %cB - send a BREAK to the remote system\r\n\
1056 %cC - open a command line\r\n\
1057 %cR - Request rekey (SSH protocol 2 only)\r\n\
1058 %c^Z - suspend ssh\r\n\
1059 %c# - list forwarded connections\r\n\
1060 %c& - background ssh (when waiting for connections to terminate)\r\n\
1061 %c? - this message\r\n\
1062 %c%c - send the escape character by typing it twice\r\n\
1063(Note that escapes are only recognized immediately after newline.)\r\n",
1064 escape_char, escape_char,
1065 escape_char, escape_char,
1066 escape_char, escape_char,
1067 escape_char, escape_char,
1068 escape_char, escape_char,
1069 escape_char);
1070 }
1176 buffer_append(berr, string, strlen(string)); 1071 buffer_append(berr, string, strlen(string));
1177 continue; 1072 continue;
1178 1073
1179 case '#': 1074 case '#':
1180 snprintf(string, sizeof string, "%c#\r\n", escape_char); 1075 snprintf(string, sizeof string, "%c#\r\n",
1076 escape_char);
1181 buffer_append(berr, string, strlen(string)); 1077 buffer_append(berr, string, strlen(string));
1182 s = channel_open_message(); 1078 s = channel_open_message();
1183 buffer_append(berr, s, strlen(s)); 1079 buffer_append(berr, s, strlen(s));
@@ -1198,12 +1094,15 @@ Supported escape sequences:\r\n\
1198 } 1094 }
1199 } else { 1095 } else {
1200 /* 1096 /*
1201 * The previous character was not an escape char. Check if this 1097 * The previous character was not an escape char.
1202 * is an escape. 1098 * Check if this is an escape.
1203 */ 1099 */
1204 if (last_was_cr && ch == escape_char) { 1100 if (last_was_cr && ch == escape_char) {
1205 /* It is. Set the flag and continue to next character. */ 1101 /*
1206 escape_pending = 1; 1102 * It is. Set the flag and continue to
1103 * next character.
1104 */
1105 *escape_pendingp = 1;
1207 continue; 1106 continue;
1208 } 1107 }
1209 } 1108 }
@@ -1229,7 +1128,8 @@ client_process_input(fd_set *readset)
1229 if (FD_ISSET(fileno(stdin), readset)) { 1128 if (FD_ISSET(fileno(stdin), readset)) {
1230 /* Read as much as possible. */ 1129 /* Read as much as possible. */
1231 len = read(fileno(stdin), buf, sizeof(buf)); 1130 len = read(fileno(stdin), buf, sizeof(buf));
1232 if (len < 0 && (errno == EAGAIN || errno == EINTR)) 1131 if (len < 0 &&
1132 (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
1233 return; /* we'll try again later */ 1133 return; /* we'll try again later */
1234 if (len <= 0) { 1134 if (len <= 0) {
1235 /* 1135 /*
@@ -1238,7 +1138,8 @@ client_process_input(fd_set *readset)
1238 * if it was an error condition. 1138 * if it was an error condition.
1239 */ 1139 */
1240 if (len < 0) { 1140 if (len < 0) {
1241 snprintf(buf, sizeof buf, "read: %.100s\r\n", strerror(errno)); 1141 snprintf(buf, sizeof buf, "read: %.100s\r\n",
1142 strerror(errno));
1242 buffer_append(&stderr_buffer, buf, strlen(buf)); 1143 buffer_append(&stderr_buffer, buf, strlen(buf));
1243 } 1144 }
1244 /* Mark that we have seen EOF. */ 1145 /* Mark that we have seen EOF. */
@@ -1254,7 +1155,7 @@ client_process_input(fd_set *readset)
1254 packet_start(SSH_CMSG_EOF); 1155 packet_start(SSH_CMSG_EOF);
1255 packet_send(); 1156 packet_send();
1256 } 1157 }
1257 } else if (escape_char == SSH_ESCAPECHAR_NONE) { 1158 } else if (escape_char1 == SSH_ESCAPECHAR_NONE) {
1258 /* 1159 /*
1259 * Normal successful read, and no escape character. 1160 * Normal successful read, and no escape character.
1260 * Just append the data to buffer. 1161 * Just append the data to buffer.
@@ -1262,11 +1163,12 @@ client_process_input(fd_set *readset)
1262 buffer_append(&stdin_buffer, buf, len); 1163 buffer_append(&stdin_buffer, buf, len);
1263 } else { 1164 } else {
1264 /* 1165 /*
1265 * Normal, successful read. But we have an escape character 1166 * Normal, successful read. But we have an escape
1266 * and have to process the characters one by one. 1167 * character and have to process the characters one
1168 * by one.
1267 */ 1169 */
1268 if (process_escapes(&stdin_buffer, &stdout_buffer, 1170 if (process_escapes(NULL, &stdin_buffer,
1269 &stderr_buffer, buf, len) == -1) 1171 &stdout_buffer, &stderr_buffer, buf, len) == -1)
1270 return; 1172 return;
1271 } 1173 }
1272 } 1174 }
@@ -1284,14 +1186,16 @@ client_process_output(fd_set *writeset)
1284 len = write(fileno(stdout), buffer_ptr(&stdout_buffer), 1186 len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
1285 buffer_len(&stdout_buffer)); 1187 buffer_len(&stdout_buffer));
1286 if (len <= 0) { 1188 if (len <= 0) {
1287 if (errno == EINTR || errno == EAGAIN) 1189 if (errno == EINTR || errno == EAGAIN ||
1190 errno == EWOULDBLOCK)
1288 len = 0; 1191 len = 0;
1289 else { 1192 else {
1290 /* 1193 /*
1291 * An error or EOF was encountered. Put an 1194 * An error or EOF was encountered. Put an
1292 * error message to stderr buffer. 1195 * error message to stderr buffer.
1293 */ 1196 */
1294 snprintf(buf, sizeof buf, "write stdout: %.50s\r\n", strerror(errno)); 1197 snprintf(buf, sizeof buf,
1198 "write stdout: %.50s\r\n", strerror(errno));
1295 buffer_append(&stderr_buffer, buf, strlen(buf)); 1199 buffer_append(&stderr_buffer, buf, strlen(buf));
1296 quit_pending = 1; 1200 quit_pending = 1;
1297 return; 1201 return;
@@ -1299,7 +1203,6 @@ client_process_output(fd_set *writeset)
1299 } 1203 }
1300 /* Consume printed data from the buffer. */ 1204 /* Consume printed data from the buffer. */
1301 buffer_consume(&stdout_buffer, len); 1205 buffer_consume(&stdout_buffer, len);
1302 stdout_bytes += len;
1303 } 1206 }
1304 /* Write buffered output to stderr. */ 1207 /* Write buffered output to stderr. */
1305 if (FD_ISSET(fileno(stderr), writeset)) { 1208 if (FD_ISSET(fileno(stderr), writeset)) {
@@ -1307,17 +1210,20 @@ client_process_output(fd_set *writeset)
1307 len = write(fileno(stderr), buffer_ptr(&stderr_buffer), 1210 len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
1308 buffer_len(&stderr_buffer)); 1211 buffer_len(&stderr_buffer));
1309 if (len <= 0) { 1212 if (len <= 0) {
1310 if (errno == EINTR || errno == EAGAIN) 1213 if (errno == EINTR || errno == EAGAIN ||
1214 errno == EWOULDBLOCK)
1311 len = 0; 1215 len = 0;
1312 else { 1216 else {
1313 /* EOF or error, but can't even print error message. */ 1217 /*
1218 * EOF or error, but can't even print
1219 * error message.
1220 */
1314 quit_pending = 1; 1221 quit_pending = 1;
1315 return; 1222 return;
1316 } 1223 }
1317 } 1224 }
1318 /* Consume printed characters from the buffer. */ 1225 /* Consume printed characters from the buffer. */
1319 buffer_consume(&stderr_buffer, len); 1226 buffer_consume(&stderr_buffer, len);
1320 stderr_bytes += len;
1321 } 1227 }
1322} 1228}
1323 1229
@@ -1336,16 +1242,39 @@ client_process_output(fd_set *writeset)
1336static void 1242static void
1337client_process_buffered_input_packets(void) 1243client_process_buffered_input_packets(void)
1338{ 1244{
1339 dispatch_run(DISPATCH_NONBLOCK, &quit_pending, compat20 ? xxx_kex : NULL); 1245 dispatch_run(DISPATCH_NONBLOCK, &quit_pending,
1246 compat20 ? xxx_kex : NULL);
1340} 1247}
1341 1248
1342/* scan buf[] for '~' before sending data to the peer */ 1249/* scan buf[] for '~' before sending data to the peer */
1343 1250
1344static int 1251/* Helper: allocate a new escape_filter_ctx and fill in its escape char */
1345simple_escape_filter(Channel *c, char *buf, int len) 1252void *
1253client_new_escape_filter_ctx(int escape_char)
1254{
1255 struct escape_filter_ctx *ret;
1256
1257 ret = xmalloc(sizeof(*ret));
1258 ret->escape_pending = 0;
1259 ret->escape_char = escape_char;
1260 return (void *)ret;
1261}
1262
1263/* Free the escape filter context on channel free */
1264void
1265client_filter_cleanup(int cid, void *ctx)
1266{
1267 xfree(ctx);
1268}
1269
1270int
1271client_simple_escape_filter(Channel *c, char *buf, int len)
1346{ 1272{
1347 /* XXX we assume c->extended is writeable */ 1273 if (c->extended_usage != CHAN_EXTENDED_WRITE)
1348 return process_escapes(&c->input, &c->output, &c->extended, buf, len); 1274 return 0;
1275
1276 return process_escapes(c, &c->input, &c->output, &c->extended,
1277 buf, len);
1349} 1278}
1350 1279
1351static void 1280static void
@@ -1369,6 +1298,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1369 fd_set *readset = NULL, *writeset = NULL; 1298 fd_set *readset = NULL, *writeset = NULL;
1370 double start_time, total_time; 1299 double start_time, total_time;
1371 int max_fd = 0, max_fd2 = 0, len, rekeying = 0; 1300 int max_fd = 0, max_fd2 = 0, len, rekeying = 0;
1301 u_int64_t ibytes, obytes;
1372 u_int nalloc = 0; 1302 u_int nalloc = 0;
1373 char buf[100]; 1303 char buf[100];
1374 1304
@@ -1377,7 +1307,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1377 start_time = get_current_time(); 1307 start_time = get_current_time();
1378 1308
1379 /* Initialize variables. */ 1309 /* Initialize variables. */
1380 escape_pending = 0; 1310 escape_pending1 = 0;
1381 last_was_cr = 1; 1311 last_was_cr = 1;
1382 exit_status = -1; 1312 exit_status = -1;
1383 stdin_eof = 0; 1313 stdin_eof = 0;
@@ -1385,8 +1315,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1385 connection_in = packet_get_connection_in(); 1315 connection_in = packet_get_connection_in();
1386 connection_out = packet_get_connection_out(); 1316 connection_out = packet_get_connection_out();
1387 max_fd = MAX(connection_in, connection_out); 1317 max_fd = MAX(connection_in, connection_out);
1388 if (control_fd != -1) 1318 if (muxserver_sock != -1)
1389 max_fd = MAX(max_fd, control_fd); 1319 max_fd = MAX(max_fd, muxserver_sock);
1390 1320
1391 if (!compat20) { 1321 if (!compat20) {
1392 /* enable nonblocking unless tty */ 1322 /* enable nonblocking unless tty */
@@ -1400,11 +1330,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1400 max_fd = MAX(max_fd, fileno(stdout)); 1330 max_fd = MAX(max_fd, fileno(stdout));
1401 max_fd = MAX(max_fd, fileno(stderr)); 1331 max_fd = MAX(max_fd, fileno(stderr));
1402 } 1332 }
1403 stdin_bytes = 0;
1404 stdout_bytes = 0;
1405 stderr_bytes = 0;
1406 quit_pending = 0; 1333 quit_pending = 0;
1407 escape_char = escape_char_arg; 1334 escape_char1 = escape_char_arg;
1408 1335
1409 /* Initialize buffers. */ 1336 /* Initialize buffers. */
1410 buffer_init(&stdin_buffer); 1337 buffer_init(&stdin_buffer);
@@ -1432,9 +1359,11 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1432 1359
1433 if (compat20) { 1360 if (compat20) {
1434 session_ident = ssh2_chan_id; 1361 session_ident = ssh2_chan_id;
1435 if (escape_char != SSH_ESCAPECHAR_NONE) 1362 if (escape_char_arg != SSH_ESCAPECHAR_NONE)
1436 channel_register_filter(session_ident, 1363 channel_register_filter(session_ident,
1437 simple_escape_filter, NULL); 1364 client_simple_escape_filter, NULL,
1365 client_filter_cleanup,
1366 client_new_escape_filter_ctx(escape_char_arg));
1438 if (session_ident != -1) 1367 if (session_ident != -1)
1439 channel_register_cleanup(session_ident, 1368 channel_register_cleanup(session_ident,
1440 client_channel_closed, 0); 1369 client_channel_closed, 0);
@@ -1506,7 +1435,10 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1506 client_process_net_input(readset); 1435 client_process_net_input(readset);
1507 1436
1508 /* Accept control connections. */ 1437 /* Accept control connections. */
1509 client_process_control(readset); 1438 if (muxserver_sock != -1 &&FD_ISSET(muxserver_sock, readset)) {
1439 if (muxserver_accept_control())
1440 quit_pending = 1;
1441 }
1510 1442
1511 if (quit_pending) 1443 if (quit_pending)
1512 break; 1444 break;
@@ -1521,7 +1453,10 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1521 client_process_output(writeset); 1453 client_process_output(writeset);
1522 } 1454 }
1523 1455
1524 /* Send as much buffered packet data as possible to the sender. */ 1456 /*
1457 * Send as much buffered packet data as possible to the
1458 * sender.
1459 */
1525 if (FD_ISSET(connection_out, writeset)) 1460 if (FD_ISSET(connection_out, writeset))
1526 packet_write_poll(); 1461 packet_write_poll();
1527 } 1462 }
@@ -1566,7 +1501,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1566 * that the connection has been closed. 1501 * that the connection has been closed.
1567 */ 1502 */
1568 if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) { 1503 if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
1569 snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host); 1504 snprintf(buf, sizeof buf,
1505 "Connection to %.64s closed.\r\n", host);
1570 buffer_append(&stderr_buffer, buf, strlen(buf)); 1506 buffer_append(&stderr_buffer, buf, strlen(buf));
1571 } 1507 }
1572 1508
@@ -1579,7 +1515,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1579 break; 1515 break;
1580 } 1516 }
1581 buffer_consume(&stdout_buffer, len); 1517 buffer_consume(&stdout_buffer, len);
1582 stdout_bytes += len;
1583 } 1518 }
1584 1519
1585 /* Output any buffered data for stderr. */ 1520 /* Output any buffered data for stderr. */
@@ -1591,7 +1526,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1591 break; 1526 break;
1592 } 1527 }
1593 buffer_consume(&stderr_buffer, len); 1528 buffer_consume(&stderr_buffer, len);
1594 stderr_bytes += len;
1595 } 1529 }
1596 1530
1597 /* Clear and free any buffers. */ 1531 /* Clear and free any buffers. */
@@ -1602,13 +1536,13 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1602 1536
1603 /* Report bytes transferred, and transfer rates. */ 1537 /* Report bytes transferred, and transfer rates. */
1604 total_time = get_current_time() - start_time; 1538 total_time = get_current_time() - start_time;
1605 debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds", 1539 packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes);
1606 stdin_bytes, stdout_bytes, stderr_bytes, total_time); 1540 packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes);
1541 verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds",
1542 obytes, ibytes, total_time);
1607 if (total_time > 0) 1543 if (total_time > 0)
1608 debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f", 1544 verbose("Bytes per second: sent %.1f, received %.1f",
1609 stdin_bytes / total_time, stdout_bytes / total_time, 1545 obytes / total_time, ibytes / total_time);
1610 stderr_bytes / total_time);
1611
1612 /* Return the exit status of the program. */ 1546 /* Return the exit status of the program. */
1613 debug("Exit status %d", exit_status); 1547 debug("Exit status %d", exit_status);
1614 return exit_status; 1548 return exit_status;
@@ -1699,7 +1633,6 @@ client_request_forwarded_tcpip(const char *request_type, int rchan)
1699 Channel *c = NULL; 1633 Channel *c = NULL;
1700 char *listen_address, *originator_address; 1634 char *listen_address, *originator_address;
1701 int listen_port, originator_port; 1635 int listen_port, originator_port;
1702 int sock;
1703 1636
1704 /* Get rest of the packet */ 1637 /* Get rest of the packet */
1705 listen_address = packet_get_string(NULL); 1638 listen_address = packet_get_string(NULL);
@@ -1708,19 +1641,13 @@ client_request_forwarded_tcpip(const char *request_type, int rchan)
1708 originator_port = packet_get_int(); 1641 originator_port = packet_get_int();
1709 packet_check_eom(); 1642 packet_check_eom();
1710 1643
1711 debug("client_request_forwarded_tcpip: listen %s port %d, originator %s port %d", 1644 debug("client_request_forwarded_tcpip: listen %s port %d, "
1712 listen_address, listen_port, originator_address, originator_port); 1645 "originator %s port %d", listen_address, listen_port,
1646 originator_address, originator_port);
1647
1648 c = channel_connect_by_listen_address(listen_port,
1649 "forwarded-tcpip", originator_address);
1713 1650
1714 sock = channel_connect_by_listen_address(listen_port);
1715 if (sock < 0) {
1716 xfree(originator_address);
1717 xfree(listen_address);
1718 return NULL;
1719 }
1720 c = channel_new("forwarded-tcpip",
1721 SSH_CHANNEL_CONNECTING, sock, sock, -1,
1722 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,
1723 originator_address, 1);
1724 xfree(originator_address); 1651 xfree(originator_address);
1725 xfree(listen_address); 1652 xfree(listen_address);
1726 return c; 1653 return c;
@@ -1736,7 +1663,8 @@ client_request_x11(const char *request_type, int rchan)
1736 1663
1737 if (!options.forward_x11) { 1664 if (!options.forward_x11) {
1738 error("Warning: ssh server tried X11 forwarding."); 1665 error("Warning: ssh server tried X11 forwarding.");
1739 error("Warning: this is probably a break-in attempt by a malicious server."); 1666 error("Warning: this is probably a break-in attempt by a "
1667 "malicious server.");
1740 return NULL; 1668 return NULL;
1741 } 1669 }
1742 originator = packet_get_string(NULL); 1670 originator = packet_get_string(NULL);
@@ -1769,7 +1697,8 @@ client_request_agent(const char *request_type, int rchan)
1769 1697
1770 if (!options.forward_agent) { 1698 if (!options.forward_agent) {
1771 error("Warning: ssh server tried agent forwarding."); 1699 error("Warning: ssh server tried agent forwarding.");
1772 error("Warning: this is probably a break-in attempt by a malicious server."); 1700 error("Warning: this is probably a break-in attempt by a "
1701 "malicious server.");
1773 return NULL; 1702 return NULL;
1774 } 1703 }
1775 sock = ssh_get_authentication_socket(); 1704 sock = ssh_get_authentication_socket();
@@ -1777,7 +1706,7 @@ client_request_agent(const char *request_type, int rchan)
1777 return NULL; 1706 return NULL;
1778 c = channel_new("authentication agent connection", 1707 c = channel_new("authentication agent connection",
1779 SSH_CHANNEL_OPEN, sock, sock, -1, 1708 SSH_CHANNEL_OPEN, sock, sock, -1,
1780 CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, 1709 CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
1781 "authentication agent connection", 1); 1710 "authentication agent connection", 1);
1782 c->force_drain = 1; 1711 c->force_drain = 1;
1783 return c; 1712 return c;
@@ -1812,7 +1741,7 @@ client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun)
1812#if defined(SSH_TUN_FILTER) 1741#if defined(SSH_TUN_FILTER)
1813 if (options.tun_open == SSH_TUNMODE_POINTOPOINT) 1742 if (options.tun_open == SSH_TUNMODE_POINTOPOINT)
1814 channel_register_filter(c->self, sys_tun_infilter, 1743 channel_register_filter(c->self, sys_tun_infilter,
1815 sys_tun_outfilter); 1744 sys_tun_outfilter, NULL, NULL);
1816#endif 1745#endif
1817 1746
1818 packet_start(SSH2_MSG_CHANNEL_OPEN); 1747 packet_start(SSH2_MSG_CHANNEL_OPEN);
@@ -1895,7 +1824,11 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt)
1895 if (id == -1) { 1824 if (id == -1) {
1896 error("client_input_channel_req: request for channel -1"); 1825 error("client_input_channel_req: request for channel -1");
1897 } else if ((c = channel_lookup(id)) == NULL) { 1826 } else if ((c = channel_lookup(id)) == NULL) {
1898 error("client_input_channel_req: channel %d: unknown channel", id); 1827 error("client_input_channel_req: channel %d: "
1828 "unknown channel", id);
1829 } else if (strcmp(rtype, "eow@openssh.com") == 0) {
1830 packet_check_eom();
1831 chan_rcvd_eow(c);
1899 } else if (strcmp(rtype, "exit-status") == 0) { 1832 } else if (strcmp(rtype, "exit-status") == 0) {
1900 exitval = packet_get_int(); 1833 exitval = packet_get_int();
1901 if (id == session_ident) { 1834 if (id == session_ident) {
@@ -1940,8 +1873,7 @@ client_input_global_request(int type, u_int32_t seq, void *ctxt)
1940 1873
1941void 1874void
1942client_session2_setup(int id, int want_tty, int want_subsystem, 1875client_session2_setup(int id, int want_tty, int want_subsystem,
1943 const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env, 1876 const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env)
1944 dispatch_fn *subsys_repl)
1945{ 1877{
1946 int len; 1878 int len;
1947 Channel *c = NULL; 1879 Channel *c = NULL;
@@ -1953,20 +1885,21 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
1953 1885
1954 if (want_tty) { 1886 if (want_tty) {
1955 struct winsize ws; 1887 struct winsize ws;
1956 struct termios tio;
1957 1888
1958 /* Store window size in the packet. */ 1889 /* Store window size in the packet. */
1959 if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0) 1890 if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0)
1960 memset(&ws, 0, sizeof(ws)); 1891 memset(&ws, 0, sizeof(ws));
1961 1892
1962 channel_request_start(id, "pty-req", 0); 1893 channel_request_start(id, "pty-req", 1);
1894 client_expect_confirm(id, "PTY allocation", 0);
1963 packet_put_cstring(term != NULL ? term : ""); 1895 packet_put_cstring(term != NULL ? term : "");
1964 packet_put_int((u_int)ws.ws_col); 1896 packet_put_int((u_int)ws.ws_col);
1965 packet_put_int((u_int)ws.ws_row); 1897 packet_put_int((u_int)ws.ws_row);
1966 packet_put_int((u_int)ws.ws_xpixel); 1898 packet_put_int((u_int)ws.ws_xpixel);
1967 packet_put_int((u_int)ws.ws_ypixel); 1899 packet_put_int((u_int)ws.ws_ypixel);
1968 tio = get_saved_tio(); 1900 if (tiop == NULL)
1969 tty_make_modes(-1, tiop != NULL ? tiop : &tio); 1901 tiop = get_saved_tio();
1902 tty_make_modes(-1, tiop);
1970 packet_send(); 1903 packet_send();
1971 /* XXX wait for reply */ 1904 /* XXX wait for reply */
1972 c->client_tty = 1; 1905 c->client_tty = 1;
@@ -2014,22 +1947,21 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
2014 if (len > 900) 1947 if (len > 900)
2015 len = 900; 1948 len = 900;
2016 if (want_subsystem) { 1949 if (want_subsystem) {
2017 debug("Sending subsystem: %.*s", len, (u_char*)buffer_ptr(cmd)); 1950 debug("Sending subsystem: %.*s",
2018 channel_request_start(id, "subsystem", subsys_repl != NULL); 1951 len, (u_char*)buffer_ptr(cmd));
2019 if (subsys_repl != NULL) { 1952 channel_request_start(id, "subsystem", 1);
2020 /* register callback for reply */ 1953 client_expect_confirm(id, "subsystem", 1);
2021 /* XXX we assume that client_loop has already been called */
2022 dispatch_set(SSH2_MSG_CHANNEL_FAILURE, subsys_repl);
2023 dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, subsys_repl);
2024 }
2025 } else { 1954 } else {
2026 debug("Sending command: %.*s", len, (u_char*)buffer_ptr(cmd)); 1955 debug("Sending command: %.*s",
2027 channel_request_start(id, "exec", 0); 1956 len, (u_char*)buffer_ptr(cmd));
1957 channel_request_start(id, "exec", 1);
1958 client_expect_confirm(id, "exec", 1);
2028 } 1959 }
2029 packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); 1960 packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
2030 packet_send(); 1961 packet_send();
2031 } else { 1962 } else {
2032 channel_request_start(id, "shell", 0); 1963 channel_request_start(id, "shell", 1);
1964 client_expect_confirm(id, "shell", 1);
2033 packet_send(); 1965 packet_send();
2034 } 1966 }
2035} 1967}
@@ -2048,6 +1980,8 @@ client_init_dispatch_20(void)
2048 dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); 1980 dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
2049 dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req); 1981 dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req);
2050 dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); 1982 dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
1983 dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &channel_input_status_confirm);
1984 dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &channel_input_status_confirm);
2051 dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request); 1985 dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request);
2052 1986
2053 /* rekeying */ 1987 /* rekeying */
@@ -2057,6 +1991,7 @@ client_init_dispatch_20(void)
2057 dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply); 1991 dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply);
2058 dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply); 1992 dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply);
2059} 1993}
1994
2060static void 1995static void
2061client_init_dispatch_13(void) 1996client_init_dispatch_13(void)
2062{ 1997{
@@ -2076,6 +2011,7 @@ client_init_dispatch_13(void)
2076 dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ? 2011 dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ?
2077 &x11_input_open : &deny_input_open); 2012 &x11_input_open : &deny_input_open);
2078} 2013}
2014
2079static void 2015static void
2080client_init_dispatch_15(void) 2016client_init_dispatch_15(void)
2081{ 2017{
@@ -2083,6 +2019,7 @@ client_init_dispatch_15(void)
2083 dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof); 2019 dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
2084 dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose); 2020 dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose);
2085} 2021}
2022
2086static void 2023static void
2087client_init_dispatch(void) 2024client_init_dispatch(void)
2088{ 2025{
@@ -2100,7 +2037,7 @@ cleanup_exit(int i)
2100{ 2037{
2101 leave_raw_mode(); 2038 leave_raw_mode();
2102 leave_non_blocking(); 2039 leave_non_blocking();
2103 if (options.control_path != NULL && control_fd != -1) 2040 if (options.control_path != NULL && muxserver_sock != -1)
2104 unlink(options.control_path); 2041 unlink(options.control_path);
2105 _exit(i); 2042 _exit(i);
2106} 2043}