summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c753
1 files changed, 345 insertions, 408 deletions
diff --git a/clientloop.c b/clientloop.c
index 7037c4192..abe5609de 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,15 +480,26 @@ 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 (compat20) { 501 if (compat20) {
478 if (++server_alive_timeouts > options.server_alive_count_max) { 502 if (++keep_alive_timeouts > options.server_alive_count_max) {
479 logit("Timeout, server not responding."); 503 logit("Timeout, server not responding.");
480 cleanup_exit(255); 504 cleanup_exit(255);
481 } 505 }
@@ -483,6 +507,8 @@ server_alive_check(void)
483 packet_put_cstring("keepalive@openssh.com"); 507 packet_put_cstring("keepalive@openssh.com");
484 packet_put_char(1); /* boolean: want reply */ 508 packet_put_char(1); /* boolean: want reply */
485 packet_send(); 509 packet_send();
510 /* Insert an empty placeholder to maintain ordering */
511 client_register_global_confirm(NULL, NULL);
486 } else { 512 } else {
487 packet_send_ignore(0); 513 packet_send_ignore(0);
488 packet_send(); 514 packet_send();
@@ -538,8 +564,8 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
538 if (packet_have_data_to_write()) 564 if (packet_have_data_to_write())
539 FD_SET(connection_out, *writesetp); 565 FD_SET(connection_out, *writesetp);
540 566
541 if (control_fd != -1) 567 if (muxserver_sock != -1)
542 FD_SET(control_fd, *readsetp); 568 FD_SET(muxserver_sock, *readsetp);
543 569
544 /* 570 /*
545 * Wait for something to happen. This will suspend the process until 571 * Wait for something to happen. This will suspend the process until
@@ -581,9 +607,11 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
581{ 607{
582 /* Flush stdout and stderr buffers. */ 608 /* Flush stdout and stderr buffers. */
583 if (buffer_len(bout) > 0) 609 if (buffer_len(bout) > 0)
584 atomicio(vwrite, fileno(stdout), buffer_ptr(bout), buffer_len(bout)); 610 atomicio(vwrite, fileno(stdout), buffer_ptr(bout),
611 buffer_len(bout));
585 if (buffer_len(berr) > 0) 612 if (buffer_len(berr) > 0)
586 atomicio(vwrite, fileno(stderr), buffer_ptr(berr), buffer_len(berr)); 613 atomicio(vwrite, fileno(stderr), buffer_ptr(berr),
614 buffer_len(berr));
587 615
588 leave_raw_mode(); 616 leave_raw_mode();
589 617
@@ -623,9 +651,13 @@ client_process_net_input(fd_set *readset)
623 /* Read as much as possible. */ 651 /* Read as much as possible. */
624 len = read(connection_in, buf, sizeof(buf)); 652 len = read(connection_in, buf, sizeof(buf));
625 if (len == 0) { 653 if (len == 0) {
626 /* Received EOF. The remote host has closed the connection. */ 654 /*
627 snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n", 655 * Received EOF. The remote host has closed the
628 host); 656 * connection.
657 */
658 snprintf(buf, sizeof buf,
659 "Connection to %.300s closed by remote host.\r\n",
660 host);
629 buffer_append(&stderr_buffer, buf, strlen(buf)); 661 buffer_append(&stderr_buffer, buf, strlen(buf));
630 quit_pending = 1; 662 quit_pending = 1;
631 return; 663 return;
@@ -634,13 +666,18 @@ client_process_net_input(fd_set *readset)
634 * There is a kernel bug on Solaris that causes select to 666 * There is a kernel bug on Solaris that causes select to
635 * sometimes wake up even though there is no data available. 667 * sometimes wake up even though there is no data available.
636 */ 668 */
637 if (len < 0 && (errno == EAGAIN || errno == EINTR)) 669 if (len < 0 &&
670 (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
638 len = 0; 671 len = 0;
639 672
640 if (len < 0) { 673 if (len < 0) {
641 /* An error has encountered. Perhaps there is a network problem. */ 674 /*
642 snprintf(buf, sizeof buf, "Read from remote host %.300s: %.100s\r\n", 675 * An error has encountered. Perhaps there is a
643 host, strerror(errno)); 676 * network problem.
677 */
678 snprintf(buf, sizeof buf,
679 "Read from remote host %.300s: %.100s\r\n",
680 host, strerror(errno));
644 buffer_append(&stderr_buffer, buf, strlen(buf)); 681 buffer_append(&stderr_buffer, buf, strlen(buf));
645 quit_pending = 1; 682 quit_pending = 1;
646 return; 683 return;
@@ -650,289 +687,81 @@ client_process_net_input(fd_set *readset)
650} 687}
651 688
652static void 689static void
653client_subsystem_reply(int type, u_int32_t seq, void *ctxt) 690client_status_confirm(int type, Channel *c, void *ctx)
654{ 691{
655 int id; 692 struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx;
656 Channel *c; 693 char errmsg[256];
657 694 int tochan;
658 id = packet_get_int(); 695
659 packet_check_eom(); 696 /* XXX supress on mux _client_ quietmode */
660 697 tochan = options.log_level >= SYSLOG_LEVEL_ERROR &&
661 if ((c = channel_lookup(id)) == NULL) { 698 c->ctl_fd != -1 && c->extended_usage == CHAN_EXTENDED_WRITE;
662 error("%s: no channel for id %d", __func__, id); 699
663 return; 700 if (type == SSH2_MSG_CHANNEL_SUCCESS) {
664 } 701 debug2("%s request accepted on channel %d",
665 702 cr->request_type, c->self);
666 if (type == SSH2_MSG_CHANNEL_SUCCESS) 703 } else if (type == SSH2_MSG_CHANNEL_FAILURE) {
667 debug2("Request suceeded on channel %d", id); 704 if (tochan) {
668 else if (type == SSH2_MSG_CHANNEL_FAILURE) { 705 snprintf(errmsg, sizeof(errmsg),
669 error("Request failed on channel %d", id); 706 "%s request failed\r\n", cr->request_type);
670 channel_free(c); 707 } else {
708 snprintf(errmsg, sizeof(errmsg),
709 "%s request failed on channel %d",
710 cr->request_type, c->self);
711 }
712 /* If error occurred on primary session channel, then exit */
713 if (cr->do_close && c->self == session_ident)
714 fatal("%s", errmsg);
715 /* If error occurred on mux client, append to their stderr */
716 if (tochan)
717 buffer_append(&c->extended, errmsg, strlen(errmsg));
718 else
719 error("%s", errmsg);
720 if (cr->do_close) {
721 chan_read_failed(c);
722 chan_write_failed(c);
723 }
671 } 724 }
725 xfree(cr);
672} 726}
673 727
674static void 728static void
675client_extra_session2_setup(int id, void *arg) 729client_abandon_status_confirm(Channel *c, void *ctx)
676{ 730{
677 struct confirm_ctx *cctx = arg; 731 xfree(ctx);
678 const char *display;
679 Channel *c;
680 int i;
681
682 if (cctx == NULL)
683 fatal("%s: cctx == NULL", __func__);
684 if ((c = channel_lookup(id)) == NULL)
685 fatal("%s: no channel for id %d", __func__, id);
686
687 display = getenv("DISPLAY");
688 if (cctx->want_x_fwd && options.forward_x11 && display != NULL) {
689 char *proto, *data;
690 /* Get reasonable local authentication information. */
691 client_x11_get_proto(display, options.xauth_location,
692 options.forward_x11_trusted, &proto, &data);
693 /* Request forwarding with authentication spoofing. */
694 debug("Requesting X11 forwarding with authentication spoofing.");
695 x11_request_forwarding_with_spoofing(id, display, proto, data);
696 /* XXX wait for reply */
697 }
698
699 if (cctx->want_agent_fwd && options.forward_agent) {
700 debug("Requesting authentication agent forwarding.");
701 channel_request_start(id, "auth-agent-req@openssh.com", 0);
702 packet_send();
703 }
704
705 client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
706 cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env,
707 client_subsystem_reply);
708
709 c->confirm_ctx = NULL;
710 buffer_free(&cctx->cmd);
711 xfree(cctx->term);
712 if (cctx->env != NULL) {
713 for (i = 0; cctx->env[i] != NULL; i++)
714 xfree(cctx->env[i]);
715 xfree(cctx->env);
716 }
717 xfree(cctx);
718} 732}
719 733
720static void 734static void
721client_process_control(fd_set *readset) 735client_expect_confirm(int id, const char *request, int do_close)
722{ 736{
723 Buffer m; 737 struct channel_reply_ctx *cr = xmalloc(sizeof(*cr));
724 Channel *c;
725 int client_fd, new_fd[3], ver, allowed, window, packetmax;
726 socklen_t addrlen;
727 struct sockaddr_storage addr;
728 struct confirm_ctx *cctx;
729 char *cmd;
730 u_int i, len, env_len, command, flags;
731 uid_t euid;
732 gid_t egid;
733
734 /*
735 * Accept connection on control socket
736 */
737 if (control_fd == -1 || !FD_ISSET(control_fd, readset))
738 return;
739
740 memset(&addr, 0, sizeof(addr));
741 addrlen = sizeof(addr);
742 if ((client_fd = accept(control_fd,
743 (struct sockaddr*)&addr, &addrlen)) == -1) {
744 error("%s accept: %s", __func__, strerror(errno));
745 return;
746 }
747
748 if (getpeereid(client_fd, &euid, &egid) < 0) {
749 error("%s getpeereid failed: %s", __func__, strerror(errno));
750 close(client_fd);
751 return;
752 }
753 if ((euid != 0) && (getuid() != euid)) {
754 error("control mode uid mismatch: peer euid %u != uid %u",
755 (u_int) euid, (u_int) getuid());
756 close(client_fd);
757 return;
758 }
759
760 unset_nonblock(client_fd);
761
762 /* Read command */
763 buffer_init(&m);
764 if (ssh_msg_recv(client_fd, &m) == -1) {
765 error("%s: client msg_recv failed", __func__);
766 close(client_fd);
767 buffer_free(&m);
768 return;
769 }
770 if ((ver = buffer_get_char(&m)) != SSHMUX_VER) {
771 error("%s: wrong client version %d", __func__, ver);
772 buffer_free(&m);
773 close(client_fd);
774 return;
775 }
776
777 allowed = 1;
778 command = buffer_get_int(&m);
779 flags = buffer_get_int(&m);
780
781 buffer_clear(&m);
782
783 switch (command) {
784 case SSHMUX_COMMAND_OPEN:
785 if (options.control_master == SSHCTL_MASTER_ASK ||
786 options.control_master == SSHCTL_MASTER_AUTO_ASK)
787 allowed = ask_permission("Allow shared connection "
788 "to %s? ", host);
789 /* continue below */
790 break;
791 case SSHMUX_COMMAND_TERMINATE:
792 if (options.control_master == SSHCTL_MASTER_ASK ||
793 options.control_master == SSHCTL_MASTER_AUTO_ASK)
794 allowed = ask_permission("Terminate shared connection "
795 "to %s? ", host);
796 if (allowed)
797 quit_pending = 1;
798 /* FALLTHROUGH */
799 case SSHMUX_COMMAND_ALIVE_CHECK:
800 /* Reply for SSHMUX_COMMAND_TERMINATE and ALIVE_CHECK */
801 buffer_clear(&m);
802 buffer_put_int(&m, allowed);
803 buffer_put_int(&m, getpid());
804 if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
805 error("%s: client msg_send failed", __func__);
806 close(client_fd);
807 buffer_free(&m);
808 return;
809 }
810 buffer_free(&m);
811 close(client_fd);
812 return;
813 default:
814 error("Unsupported command %d", command);
815 buffer_free(&m);
816 close(client_fd);
817 return;
818 }
819
820 /* Reply for SSHMUX_COMMAND_OPEN */
821 buffer_clear(&m);
822 buffer_put_int(&m, allowed);
823 buffer_put_int(&m, getpid());
824 if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
825 error("%s: client msg_send failed", __func__);
826 close(client_fd);
827 buffer_free(&m);
828 return;
829 }
830
831 if (!allowed) {
832 error("Refused control connection");
833 close(client_fd);
834 buffer_free(&m);
835 return;
836 }
837 738
838 buffer_clear(&m); 739 cr->request_type = request;
839 if (ssh_msg_recv(client_fd, &m) == -1) { 740 cr->do_close = do_close;
840 error("%s: client msg_recv failed", __func__);
841 close(client_fd);
842 buffer_free(&m);
843 return;
844 }
845 if ((ver = buffer_get_char(&m)) != SSHMUX_VER) {
846 error("%s: wrong client version %d", __func__, ver);
847 buffer_free(&m);
848 close(client_fd);
849 return;
850 }
851 741
852 cctx = xcalloc(1, sizeof(*cctx)); 742 channel_register_status_confirm(id, client_status_confirm,
853 cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0; 743 client_abandon_status_confirm, cr);
854 cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0; 744}
855 cctx->want_x_fwd = (flags & SSHMUX_FLAG_X11_FWD) != 0;
856 cctx->want_agent_fwd = (flags & SSHMUX_FLAG_AGENT_FWD) != 0;
857 cctx->term = buffer_get_string(&m, &len);
858
859 cmd = buffer_get_string(&m, &len);
860 buffer_init(&cctx->cmd);
861 buffer_append(&cctx->cmd, cmd, strlen(cmd));
862
863 env_len = buffer_get_int(&m);
864 env_len = MIN(env_len, 4096);
865 debug3("%s: receiving %d env vars", __func__, env_len);
866 if (env_len != 0) {
867 cctx->env = xcalloc(env_len + 1, sizeof(*cctx->env));
868 for (i = 0; i < env_len; i++)
869 cctx->env[i] = buffer_get_string(&m, &len);
870 cctx->env[i] = NULL;
871 }
872 745
873 debug2("%s: accepted tty %d, subsys %d, cmd %s", __func__, 746void
874 cctx->want_tty, cctx->want_subsys, cmd); 747client_register_global_confirm(global_confirm_cb *cb, void *ctx)
875 xfree(cmd); 748{
876 749 struct global_confirm *gc, *last_gc;
877 /* Gather fds from client */ 750
878 new_fd[0] = mm_receive_fd(client_fd); 751 /* Coalesce identical callbacks */
879 new_fd[1] = mm_receive_fd(client_fd); 752 last_gc = TAILQ_LAST(&global_confirms, global_confirms);
880 new_fd[2] = mm_receive_fd(client_fd); 753 if (last_gc && last_gc->cb == cb && last_gc->ctx == ctx) {
881 754 if (++last_gc->ref_count >= INT_MAX)
882 debug2("%s: got fds stdin %d, stdout %d, stderr %d", __func__, 755 fatal("%s: last_gc->ref_count = %d",
883 new_fd[0], new_fd[1], new_fd[2]); 756 __func__, last_gc->ref_count);
884
885 /* Try to pick up ttymodes from client before it goes raw */
886 if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
887 error("%s: tcgetattr: %s", __func__, strerror(errno));
888
889 /* This roundtrip is just for synchronisation of ttymodes */
890 buffer_clear(&m);
891 if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
892 error("%s: client msg_send failed", __func__);
893 close(client_fd);
894 close(new_fd[0]);
895 close(new_fd[1]);
896 close(new_fd[2]);
897 buffer_free(&m);
898 xfree(cctx->term);
899 if (env_len != 0) {
900 for (i = 0; i < env_len; i++)
901 xfree(cctx->env[i]);
902 xfree(cctx->env);
903 }
904 return; 757 return;
905 } 758 }
906 buffer_free(&m);
907
908 /* enable nonblocking unless tty */
909 if (!isatty(new_fd[0]))
910 set_nonblock(new_fd[0]);
911 if (!isatty(new_fd[1]))
912 set_nonblock(new_fd[1]);
913 if (!isatty(new_fd[2]))
914 set_nonblock(new_fd[2]);
915
916 set_nonblock(client_fd);
917
918 window = CHAN_SES_WINDOW_DEFAULT;
919 packetmax = CHAN_SES_PACKET_DEFAULT;
920 if (cctx->want_tty) {
921 window >>= 1;
922 packetmax >>= 1;
923 }
924
925 c = channel_new("session", SSH_CHANNEL_OPENING,
926 new_fd[0], new_fd[1], new_fd[2], window, packetmax,
927 CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
928 759
929 /* XXX */ 760 gc = xmalloc(sizeof(*gc));
930 c->ctl_fd = client_fd; 761 gc->cb = cb;
931 762 gc->ctx = ctx;
932 debug3("%s: channel_new: %d", __func__, c->self); 763 gc->ref_count = 1;
933 764 TAILQ_INSERT_TAIL(&global_confirms, gc, entry);
934 channel_send_open(c->self);
935 channel_register_confirm(c->self, client_extra_session2_setup, cctx);
936} 765}
937 766
938static void 767static void
@@ -945,6 +774,9 @@ process_cmdline(void)
945 u_short cancel_port; 774 u_short cancel_port;
946 Forward fwd; 775 Forward fwd;
947 776
777 bzero(&fwd, sizeof(fwd));
778 fwd.listen_host = fwd.connect_host = NULL;
779
948 leave_raw_mode(); 780 leave_raw_mode();
949 handler = signal(SIGINT, SIG_IGN); 781 handler = signal(SIGINT, SIG_IGN);
950 cmd = s = read_passphrase("\r\nssh> ", RP_ECHO); 782 cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);
@@ -1044,11 +876,18 @@ out:
1044 enter_raw_mode(); 876 enter_raw_mode();
1045 if (cmd) 877 if (cmd)
1046 xfree(cmd); 878 xfree(cmd);
879 if (fwd.listen_host != NULL)
880 xfree(fwd.listen_host);
881 if (fwd.connect_host != NULL)
882 xfree(fwd.connect_host);
1047} 883}
1048 884
1049/* process the characters one by one */ 885/*
886 * Process the characters one by one, call with c==NULL for proto1 case.
887 */
1050static int 888static int
1051process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len) 889process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
890 char *buf, int len)
1052{ 891{
1053 char string[1024]; 892 char string[1024];
1054 pid_t pid; 893 pid_t pid;
@@ -1056,7 +895,20 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
1056 u_int i; 895 u_int i;
1057 u_char ch; 896 u_char ch;
1058 char *s; 897 char *s;
898 int *escape_pendingp, escape_char;
899 struct escape_filter_ctx *efc;
1059 900
901 if (c == NULL) {
902 escape_pendingp = &escape_pending1;
903 escape_char = escape_char1;
904 } else {
905 if (c->filter_ctx == NULL)
906 return 0;
907 efc = (struct escape_filter_ctx *)c->filter_ctx;
908 escape_pendingp = &efc->escape_pending;
909 escape_char = efc->escape_char;
910 }
911
1060 if (len <= 0) 912 if (len <= 0)
1061 return (0); 913 return (0);
1062 914
@@ -1064,25 +916,42 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
1064 /* Get one character at a time. */ 916 /* Get one character at a time. */
1065 ch = buf[i]; 917 ch = buf[i];
1066 918
1067 if (escape_pending) { 919 if (*escape_pendingp) {
1068 /* We have previously seen an escape character. */ 920 /* We have previously seen an escape character. */
1069 /* Clear the flag now. */ 921 /* Clear the flag now. */
1070 escape_pending = 0; 922 *escape_pendingp = 0;
1071 923
1072 /* Process the escaped character. */ 924 /* Process the escaped character. */
1073 switch (ch) { 925 switch (ch) {
1074 case '.': 926 case '.':
1075 /* Terminate the connection. */ 927 /* Terminate the connection. */
1076 snprintf(string, sizeof string, "%c.\r\n", escape_char); 928 snprintf(string, sizeof string, "%c.\r\n",
929 escape_char);
1077 buffer_append(berr, string, strlen(string)); 930 buffer_append(berr, string, strlen(string));
1078 931
1079 quit_pending = 1; 932 if (c && c->ctl_fd != -1) {
933 chan_read_failed(c);
934 chan_write_failed(c);
935 return 0;
936 } else
937 quit_pending = 1;
1080 return -1; 938 return -1;
1081 939
1082 case 'Z' - 64: 940 case 'Z' - 64:
1083 /* Suspend the program. */ 941 /* XXX support this for mux clients */
1084 /* Print a message to that effect to the user. */ 942 if (c && c->ctl_fd != -1) {
1085 snprintf(string, sizeof string, "%c^Z [suspend ssh]\r\n", escape_char); 943 noescape:
944 snprintf(string, sizeof string,
945 "%c%c escape not available to "
946 "multiplexed sessions\r\n",
947 escape_char, ch);
948 buffer_append(berr, string,
949 strlen(string));
950 continue;
951 }
952 /* Suspend the program. Inform the user */
953 snprintf(string, sizeof string,
954 "%c^Z [suspend ssh]\r\n", escape_char);
1086 buffer_append(berr, string, strlen(string)); 955 buffer_append(berr, string, strlen(string));
1087 956
1088 /* Restore terminal modes and suspend. */ 957 /* Restore terminal modes and suspend. */
@@ -1107,16 +976,20 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
1107 case 'R': 976 case 'R':
1108 if (compat20) { 977 if (compat20) {
1109 if (datafellows & SSH_BUG_NOREKEY) 978 if (datafellows & SSH_BUG_NOREKEY)
1110 logit("Server does not support re-keying"); 979 logit("Server does not "
980 "support re-keying");
1111 else 981 else
1112 need_rekeying = 1; 982 need_rekeying = 1;
1113 } 983 }
1114 continue; 984 continue;
1115 985
1116 case '&': 986 case '&':
987 if (c && c->ctl_fd != -1)
988 goto noescape;
1117 /* 989 /*
1118 * Detach the program (continue to serve connections, 990 * Detach the program (continue to serve
1119 * but put in background and no more new connections). 991 * connections, but put in background and no
992 * more new connections).
1120 */ 993 */
1121 /* Restore tty modes. */ 994 /* Restore tty modes. */
1122 leave_raw_mode(); 995 leave_raw_mode();
@@ -1145,9 +1018,9 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
1145 return -1; 1018 return -1;
1146 } else if (!stdin_eof) { 1019 } else if (!stdin_eof) {
1147 /* 1020 /*
1148 * Sending SSH_CMSG_EOF alone does not always appear 1021 * Sending SSH_CMSG_EOF alone does not
1149 * to be enough. So we try to send an EOF character 1022 * always appear to be enough. So we
1150 * first. 1023 * try to send an EOF character first.
1151 */ 1024 */
1152 packet_start(SSH_CMSG_STDIN_DATA); 1025 packet_start(SSH_CMSG_STDIN_DATA);
1153 packet_put_string("\004", 1); 1026 packet_put_string("\004", 1);
@@ -1162,27 +1035,50 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
1162 continue; 1035 continue;
1163 1036
1164 case '?': 1037 case '?':
1165 snprintf(string, sizeof string, 1038 if (c && c->ctl_fd != -1) {
1039 snprintf(string, sizeof string,
1166"%c?\r\n\ 1040"%c?\r\n\
1167Supported escape sequences:\r\n\ 1041Supported escape sequences:\r\n\
1168%c. - terminate connection\r\n\ 1042 %c. - terminate session\r\n\
1169%cB - send a BREAK to the remote system\r\n\ 1043 %cB - send a BREAK to the remote system\r\n\
1170%cC - open a command line\r\n\ 1044 %cC - open a command line\r\n\
1171%cR - Request rekey (SSH protocol 2 only)\r\n\ 1045 %cR - Request rekey (SSH protocol 2 only)\r\n\
1172%c^Z - suspend ssh\r\n\ 1046 %c# - list forwarded connections\r\n\
1173%c# - list forwarded connections\r\n\ 1047 %c? - this message\r\n\
1174%c& - background ssh (when waiting for connections to terminate)\r\n\ 1048 %c%c - send the escape character by typing it twice\r\n\
1175%c? - this message\r\n\
1176%c%c - send the escape character by typing it twice\r\n\
1177(Note that escapes are only recognized immediately after newline.)\r\n", 1049(Note that escapes are only recognized immediately after newline.)\r\n",
1178 escape_char, escape_char, escape_char, escape_char, 1050 escape_char, escape_char,
1179 escape_char, escape_char, escape_char, escape_char, 1051 escape_char, escape_char,
1180 escape_char, escape_char, escape_char); 1052 escape_char, escape_char,
1053 escape_char, escape_char,
1054 escape_char);
1055 } else {
1056 snprintf(string, sizeof string,
1057"%c?\r\n\
1058Supported escape sequences:\r\n\
1059 %c. - terminate connection (and any multiplexed sessions)\r\n\
1060 %cB - send a BREAK to the remote system\r\n\
1061 %cC - open a command line\r\n\
1062 %cR - Request rekey (SSH protocol 2 only)\r\n\
1063 %c^Z - suspend ssh\r\n\
1064 %c# - list forwarded connections\r\n\
1065 %c& - background ssh (when waiting for connections to terminate)\r\n\
1066 %c? - this message\r\n\
1067 %c%c - send the escape character by typing it twice\r\n\
1068(Note that escapes are only recognized immediately after newline.)\r\n",
1069 escape_char, escape_char,
1070 escape_char, escape_char,
1071 escape_char, escape_char,
1072 escape_char, escape_char,
1073 escape_char, escape_char,
1074 escape_char);
1075 }
1181 buffer_append(berr, string, strlen(string)); 1076 buffer_append(berr, string, strlen(string));
1182 continue; 1077 continue;
1183 1078
1184 case '#': 1079 case '#':
1185 snprintf(string, sizeof string, "%c#\r\n", escape_char); 1080 snprintf(string, sizeof string, "%c#\r\n",
1081 escape_char);
1186 buffer_append(berr, string, strlen(string)); 1082 buffer_append(berr, string, strlen(string));
1187 s = channel_open_message(); 1083 s = channel_open_message();
1188 buffer_append(berr, s, strlen(s)); 1084 buffer_append(berr, s, strlen(s));
@@ -1203,12 +1099,15 @@ Supported escape sequences:\r\n\
1203 } 1099 }
1204 } else { 1100 } else {
1205 /* 1101 /*
1206 * The previous character was not an escape char. Check if this 1102 * The previous character was not an escape char.
1207 * is an escape. 1103 * Check if this is an escape.
1208 */ 1104 */
1209 if (last_was_cr && ch == escape_char) { 1105 if (last_was_cr && ch == escape_char) {
1210 /* It is. Set the flag and continue to next character. */ 1106 /*
1211 escape_pending = 1; 1107 * It is. Set the flag and continue to
1108 * next character.
1109 */
1110 *escape_pendingp = 1;
1212 continue; 1111 continue;
1213 } 1112 }
1214 } 1113 }
@@ -1234,7 +1133,8 @@ client_process_input(fd_set *readset)
1234 if (FD_ISSET(fileno(stdin), readset)) { 1133 if (FD_ISSET(fileno(stdin), readset)) {
1235 /* Read as much as possible. */ 1134 /* Read as much as possible. */
1236 len = read(fileno(stdin), buf, sizeof(buf)); 1135 len = read(fileno(stdin), buf, sizeof(buf));
1237 if (len < 0 && (errno == EAGAIN || errno == EINTR)) 1136 if (len < 0 &&
1137 (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
1238 return; /* we'll try again later */ 1138 return; /* we'll try again later */
1239 if (len <= 0) { 1139 if (len <= 0) {
1240 /* 1140 /*
@@ -1243,7 +1143,8 @@ client_process_input(fd_set *readset)
1243 * if it was an error condition. 1143 * if it was an error condition.
1244 */ 1144 */
1245 if (len < 0) { 1145 if (len < 0) {
1246 snprintf(buf, sizeof buf, "read: %.100s\r\n", strerror(errno)); 1146 snprintf(buf, sizeof buf, "read: %.100s\r\n",
1147 strerror(errno));
1247 buffer_append(&stderr_buffer, buf, strlen(buf)); 1148 buffer_append(&stderr_buffer, buf, strlen(buf));
1248 } 1149 }
1249 /* Mark that we have seen EOF. */ 1150 /* Mark that we have seen EOF. */
@@ -1259,7 +1160,7 @@ client_process_input(fd_set *readset)
1259 packet_start(SSH_CMSG_EOF); 1160 packet_start(SSH_CMSG_EOF);
1260 packet_send(); 1161 packet_send();
1261 } 1162 }
1262 } else if (escape_char == SSH_ESCAPECHAR_NONE) { 1163 } else if (escape_char1 == SSH_ESCAPECHAR_NONE) {
1263 /* 1164 /*
1264 * Normal successful read, and no escape character. 1165 * Normal successful read, and no escape character.
1265 * Just append the data to buffer. 1166 * Just append the data to buffer.
@@ -1267,11 +1168,12 @@ client_process_input(fd_set *readset)
1267 buffer_append(&stdin_buffer, buf, len); 1168 buffer_append(&stdin_buffer, buf, len);
1268 } else { 1169 } else {
1269 /* 1170 /*
1270 * Normal, successful read. But we have an escape character 1171 * Normal, successful read. But we have an escape
1271 * and have to process the characters one by one. 1172 * character and have to process the characters one
1173 * by one.
1272 */ 1174 */
1273 if (process_escapes(&stdin_buffer, &stdout_buffer, 1175 if (process_escapes(NULL, &stdin_buffer,
1274 &stderr_buffer, buf, len) == -1) 1176 &stdout_buffer, &stderr_buffer, buf, len) == -1)
1275 return; 1177 return;
1276 } 1178 }
1277 } 1179 }
@@ -1289,14 +1191,16 @@ client_process_output(fd_set *writeset)
1289 len = write(fileno(stdout), buffer_ptr(&stdout_buffer), 1191 len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
1290 buffer_len(&stdout_buffer)); 1192 buffer_len(&stdout_buffer));
1291 if (len <= 0) { 1193 if (len <= 0) {
1292 if (errno == EINTR || errno == EAGAIN) 1194 if (errno == EINTR || errno == EAGAIN ||
1195 errno == EWOULDBLOCK)
1293 len = 0; 1196 len = 0;
1294 else { 1197 else {
1295 /* 1198 /*
1296 * An error or EOF was encountered. Put an 1199 * An error or EOF was encountered. Put an
1297 * error message to stderr buffer. 1200 * error message to stderr buffer.
1298 */ 1201 */
1299 snprintf(buf, sizeof buf, "write stdout: %.50s\r\n", strerror(errno)); 1202 snprintf(buf, sizeof buf,
1203 "write stdout: %.50s\r\n", strerror(errno));
1300 buffer_append(&stderr_buffer, buf, strlen(buf)); 1204 buffer_append(&stderr_buffer, buf, strlen(buf));
1301 quit_pending = 1; 1205 quit_pending = 1;
1302 return; 1206 return;
@@ -1304,7 +1208,6 @@ client_process_output(fd_set *writeset)
1304 } 1208 }
1305 /* Consume printed data from the buffer. */ 1209 /* Consume printed data from the buffer. */
1306 buffer_consume(&stdout_buffer, len); 1210 buffer_consume(&stdout_buffer, len);
1307 stdout_bytes += len;
1308 } 1211 }
1309 /* Write buffered output to stderr. */ 1212 /* Write buffered output to stderr. */
1310 if (FD_ISSET(fileno(stderr), writeset)) { 1213 if (FD_ISSET(fileno(stderr), writeset)) {
@@ -1312,17 +1215,20 @@ client_process_output(fd_set *writeset)
1312 len = write(fileno(stderr), buffer_ptr(&stderr_buffer), 1215 len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
1313 buffer_len(&stderr_buffer)); 1216 buffer_len(&stderr_buffer));
1314 if (len <= 0) { 1217 if (len <= 0) {
1315 if (errno == EINTR || errno == EAGAIN) 1218 if (errno == EINTR || errno == EAGAIN ||
1219 errno == EWOULDBLOCK)
1316 len = 0; 1220 len = 0;
1317 else { 1221 else {
1318 /* EOF or error, but can't even print error message. */ 1222 /*
1223 * EOF or error, but can't even print
1224 * error message.
1225 */
1319 quit_pending = 1; 1226 quit_pending = 1;
1320 return; 1227 return;
1321 } 1228 }
1322 } 1229 }
1323 /* Consume printed characters from the buffer. */ 1230 /* Consume printed characters from the buffer. */
1324 buffer_consume(&stderr_buffer, len); 1231 buffer_consume(&stderr_buffer, len);
1325 stderr_bytes += len;
1326 } 1232 }
1327} 1233}
1328 1234
@@ -1341,16 +1247,39 @@ client_process_output(fd_set *writeset)
1341static void 1247static void
1342client_process_buffered_input_packets(void) 1248client_process_buffered_input_packets(void)
1343{ 1249{
1344 dispatch_run(DISPATCH_NONBLOCK, &quit_pending, compat20 ? xxx_kex : NULL); 1250 dispatch_run(DISPATCH_NONBLOCK, &quit_pending,
1251 compat20 ? xxx_kex : NULL);
1345} 1252}
1346 1253
1347/* scan buf[] for '~' before sending data to the peer */ 1254/* scan buf[] for '~' before sending data to the peer */
1348 1255
1349static int 1256/* Helper: allocate a new escape_filter_ctx and fill in its escape char */
1350simple_escape_filter(Channel *c, char *buf, int len) 1257void *
1258client_new_escape_filter_ctx(int escape_char)
1259{
1260 struct escape_filter_ctx *ret;
1261
1262 ret = xmalloc(sizeof(*ret));
1263 ret->escape_pending = 0;
1264 ret->escape_char = escape_char;
1265 return (void *)ret;
1266}
1267
1268/* Free the escape filter context on channel free */
1269void
1270client_filter_cleanup(int cid, void *ctx)
1271{
1272 xfree(ctx);
1273}
1274
1275int
1276client_simple_escape_filter(Channel *c, char *buf, int len)
1351{ 1277{
1352 /* XXX we assume c->extended is writeable */ 1278 if (c->extended_usage != CHAN_EXTENDED_WRITE)
1353 return process_escapes(&c->input, &c->output, &c->extended, buf, len); 1279 return 0;
1280
1281 return process_escapes(c, &c->input, &c->output, &c->extended,
1282 buf, len);
1354} 1283}
1355 1284
1356static void 1285static void
@@ -1374,6 +1303,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1374 fd_set *readset = NULL, *writeset = NULL; 1303 fd_set *readset = NULL, *writeset = NULL;
1375 double start_time, total_time; 1304 double start_time, total_time;
1376 int max_fd = 0, max_fd2 = 0, len, rekeying = 0; 1305 int max_fd = 0, max_fd2 = 0, len, rekeying = 0;
1306 u_int64_t ibytes, obytes;
1377 u_int nalloc = 0; 1307 u_int nalloc = 0;
1378 char buf[100]; 1308 char buf[100];
1379 1309
@@ -1382,7 +1312,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1382 start_time = get_current_time(); 1312 start_time = get_current_time();
1383 1313
1384 /* Initialize variables. */ 1314 /* Initialize variables. */
1385 escape_pending = 0; 1315 escape_pending1 = 0;
1386 last_was_cr = 1; 1316 last_was_cr = 1;
1387 exit_status = -1; 1317 exit_status = -1;
1388 stdin_eof = 0; 1318 stdin_eof = 0;
@@ -1390,8 +1320,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1390 connection_in = packet_get_connection_in(); 1320 connection_in = packet_get_connection_in();
1391 connection_out = packet_get_connection_out(); 1321 connection_out = packet_get_connection_out();
1392 max_fd = MAX(connection_in, connection_out); 1322 max_fd = MAX(connection_in, connection_out);
1393 if (control_fd != -1) 1323 if (muxserver_sock != -1)
1394 max_fd = MAX(max_fd, control_fd); 1324 max_fd = MAX(max_fd, muxserver_sock);
1395 1325
1396 if (!compat20) { 1326 if (!compat20) {
1397 /* enable nonblocking unless tty */ 1327 /* enable nonblocking unless tty */
@@ -1405,11 +1335,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1405 max_fd = MAX(max_fd, fileno(stdout)); 1335 max_fd = MAX(max_fd, fileno(stdout));
1406 max_fd = MAX(max_fd, fileno(stderr)); 1336 max_fd = MAX(max_fd, fileno(stderr));
1407 } 1337 }
1408 stdin_bytes = 0;
1409 stdout_bytes = 0;
1410 stderr_bytes = 0;
1411 quit_pending = 0; 1338 quit_pending = 0;
1412 escape_char = escape_char_arg; 1339 escape_char1 = escape_char_arg;
1413 1340
1414 /* Initialize buffers. */ 1341 /* Initialize buffers. */
1415 buffer_init(&stdin_buffer); 1342 buffer_init(&stdin_buffer);
@@ -1437,9 +1364,11 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1437 1364
1438 if (compat20) { 1365 if (compat20) {
1439 session_ident = ssh2_chan_id; 1366 session_ident = ssh2_chan_id;
1440 if (escape_char != SSH_ESCAPECHAR_NONE) 1367 if (escape_char_arg != SSH_ESCAPECHAR_NONE)
1441 channel_register_filter(session_ident, 1368 channel_register_filter(session_ident,
1442 simple_escape_filter, NULL); 1369 client_simple_escape_filter, NULL,
1370 client_filter_cleanup,
1371 client_new_escape_filter_ctx(escape_char_arg));
1443 if (session_ident != -1) 1372 if (session_ident != -1)
1444 channel_register_cleanup(session_ident, 1373 channel_register_cleanup(session_ident,
1445 client_channel_closed, 0); 1374 client_channel_closed, 0);
@@ -1511,7 +1440,10 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1511 client_process_net_input(readset); 1440 client_process_net_input(readset);
1512 1441
1513 /* Accept control connections. */ 1442 /* Accept control connections. */
1514 client_process_control(readset); 1443 if (muxserver_sock != -1 &&FD_ISSET(muxserver_sock, readset)) {
1444 if (muxserver_accept_control())
1445 quit_pending = 1;
1446 }
1515 1447
1516 if (quit_pending) 1448 if (quit_pending)
1517 break; 1449 break;
@@ -1526,7 +1458,10 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1526 client_process_output(writeset); 1458 client_process_output(writeset);
1527 } 1459 }
1528 1460
1529 /* Send as much buffered packet data as possible to the sender. */ 1461 /*
1462 * Send as much buffered packet data as possible to the
1463 * sender.
1464 */
1530 if (FD_ISSET(connection_out, writeset)) 1465 if (FD_ISSET(connection_out, writeset))
1531 packet_write_poll(); 1466 packet_write_poll();
1532 } 1467 }
@@ -1573,7 +1508,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1573 * that the connection has been closed. 1508 * that the connection has been closed.
1574 */ 1509 */
1575 if (have_pty && options.log_level > SYSLOG_LEVEL_QUIET) { 1510 if (have_pty && options.log_level > SYSLOG_LEVEL_QUIET) {
1576 snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host); 1511 snprintf(buf, sizeof buf,
1512 "Connection to %.64s closed.\r\n", host);
1577 buffer_append(&stderr_buffer, buf, strlen(buf)); 1513 buffer_append(&stderr_buffer, buf, strlen(buf));
1578 } 1514 }
1579 1515
@@ -1586,7 +1522,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1586 break; 1522 break;
1587 } 1523 }
1588 buffer_consume(&stdout_buffer, len); 1524 buffer_consume(&stdout_buffer, len);
1589 stdout_bytes += len;
1590 } 1525 }
1591 1526
1592 /* Output any buffered data for stderr. */ 1527 /* Output any buffered data for stderr. */
@@ -1598,7 +1533,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1598 break; 1533 break;
1599 } 1534 }
1600 buffer_consume(&stderr_buffer, len); 1535 buffer_consume(&stderr_buffer, len);
1601 stderr_bytes += len;
1602 } 1536 }
1603 1537
1604 /* Clear and free any buffers. */ 1538 /* Clear and free any buffers. */
@@ -1609,13 +1543,13 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1609 1543
1610 /* Report bytes transferred, and transfer rates. */ 1544 /* Report bytes transferred, and transfer rates. */
1611 total_time = get_current_time() - start_time; 1545 total_time = get_current_time() - start_time;
1612 debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds", 1546 packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes);
1613 stdin_bytes, stdout_bytes, stderr_bytes, total_time); 1547 packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes);
1548 verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds",
1549 obytes, ibytes, total_time);
1614 if (total_time > 0) 1550 if (total_time > 0)
1615 debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f", 1551 verbose("Bytes per second: sent %.1f, received %.1f",
1616 stdin_bytes / total_time, stdout_bytes / total_time, 1552 obytes / total_time, ibytes / total_time);
1617 stderr_bytes / total_time);
1618
1619 /* Return the exit status of the program. */ 1553 /* Return the exit status of the program. */
1620 debug("Exit status %d", exit_status); 1554 debug("Exit status %d", exit_status);
1621 return exit_status; 1555 return exit_status;
@@ -1706,7 +1640,6 @@ client_request_forwarded_tcpip(const char *request_type, int rchan)
1706 Channel *c = NULL; 1640 Channel *c = NULL;
1707 char *listen_address, *originator_address; 1641 char *listen_address, *originator_address;
1708 int listen_port, originator_port; 1642 int listen_port, originator_port;
1709 int sock;
1710 1643
1711 /* Get rest of the packet */ 1644 /* Get rest of the packet */
1712 listen_address = packet_get_string(NULL); 1645 listen_address = packet_get_string(NULL);
@@ -1715,19 +1648,13 @@ client_request_forwarded_tcpip(const char *request_type, int rchan)
1715 originator_port = packet_get_int(); 1648 originator_port = packet_get_int();
1716 packet_check_eom(); 1649 packet_check_eom();
1717 1650
1718 debug("client_request_forwarded_tcpip: listen %s port %d, originator %s port %d", 1651 debug("client_request_forwarded_tcpip: listen %s port %d, "
1719 listen_address, listen_port, originator_address, originator_port); 1652 "originator %s port %d", listen_address, listen_port,
1653 originator_address, originator_port);
1654
1655 c = channel_connect_by_listen_address(listen_port,
1656 "forwarded-tcpip", originator_address);
1720 1657
1721 sock = channel_connect_by_listen_address(listen_port);
1722 if (sock < 0) {
1723 xfree(originator_address);
1724 xfree(listen_address);
1725 return NULL;
1726 }
1727 c = channel_new("forwarded-tcpip",
1728 SSH_CHANNEL_CONNECTING, sock, sock, -1,
1729 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
1730 originator_address, 1);
1731 xfree(originator_address); 1658 xfree(originator_address);
1732 xfree(listen_address); 1659 xfree(listen_address);
1733 return c; 1660 return c;
@@ -1743,7 +1670,8 @@ client_request_x11(const char *request_type, int rchan)
1743 1670
1744 if (!options.forward_x11) { 1671 if (!options.forward_x11) {
1745 error("Warning: ssh server tried X11 forwarding."); 1672 error("Warning: ssh server tried X11 forwarding.");
1746 error("Warning: this is probably a break-in attempt by a malicious server."); 1673 error("Warning: this is probably a break-in attempt by a "
1674 "malicious server.");
1747 return NULL; 1675 return NULL;
1748 } 1676 }
1749 originator = packet_get_string(NULL); 1677 originator = packet_get_string(NULL);
@@ -1776,7 +1704,8 @@ client_request_agent(const char *request_type, int rchan)
1776 1704
1777 if (!options.forward_agent) { 1705 if (!options.forward_agent) {
1778 error("Warning: ssh server tried agent forwarding."); 1706 error("Warning: ssh server tried agent forwarding.");
1779 error("Warning: this is probably a break-in attempt by a malicious server."); 1707 error("Warning: this is probably a break-in attempt by a "
1708 "malicious server.");
1780 return NULL; 1709 return NULL;
1781 } 1710 }
1782 sock = ssh_get_authentication_socket(); 1711 sock = ssh_get_authentication_socket();
@@ -1819,7 +1748,7 @@ client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun)
1819#if defined(SSH_TUN_FILTER) 1748#if defined(SSH_TUN_FILTER)
1820 if (options.tun_open == SSH_TUNMODE_POINTOPOINT) 1749 if (options.tun_open == SSH_TUNMODE_POINTOPOINT)
1821 channel_register_filter(c->self, sys_tun_infilter, 1750 channel_register_filter(c->self, sys_tun_infilter,
1822 sys_tun_outfilter); 1751 sys_tun_outfilter, NULL, NULL);
1823#endif 1752#endif
1824 1753
1825 packet_start(SSH2_MSG_CHANNEL_OPEN); 1754 packet_start(SSH2_MSG_CHANNEL_OPEN);
@@ -1902,7 +1831,11 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt)
1902 if (id == -1) { 1831 if (id == -1) {
1903 error("client_input_channel_req: request for channel -1"); 1832 error("client_input_channel_req: request for channel -1");
1904 } else if ((c = channel_lookup(id)) == NULL) { 1833 } else if ((c = channel_lookup(id)) == NULL) {
1905 error("client_input_channel_req: channel %d: unknown channel", id); 1834 error("client_input_channel_req: channel %d: "
1835 "unknown channel", id);
1836 } else if (strcmp(rtype, "eow@openssh.com") == 0) {
1837 packet_check_eom();
1838 chan_rcvd_eow(c);
1906 } else if (strcmp(rtype, "exit-status") == 0) { 1839 } else if (strcmp(rtype, "exit-status") == 0) {
1907 exitval = packet_get_int(); 1840 exitval = packet_get_int();
1908 if (id == session_ident) { 1841 if (id == session_ident) {
@@ -1947,8 +1880,7 @@ client_input_global_request(int type, u_int32_t seq, void *ctxt)
1947 1880
1948void 1881void
1949client_session2_setup(int id, int want_tty, int want_subsystem, 1882client_session2_setup(int id, int want_tty, int want_subsystem,
1950 const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env, 1883 const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env)
1951 dispatch_fn *subsys_repl)
1952{ 1884{
1953 int len; 1885 int len;
1954 Channel *c = NULL; 1886 Channel *c = NULL;
@@ -1960,20 +1892,21 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
1960 1892
1961 if (want_tty) { 1893 if (want_tty) {
1962 struct winsize ws; 1894 struct winsize ws;
1963 struct termios tio;
1964 1895
1965 /* Store window size in the packet. */ 1896 /* Store window size in the packet. */
1966 if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0) 1897 if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0)
1967 memset(&ws, 0, sizeof(ws)); 1898 memset(&ws, 0, sizeof(ws));
1968 1899
1969 channel_request_start(id, "pty-req", 0); 1900 channel_request_start(id, "pty-req", 1);
1901 client_expect_confirm(id, "PTY allocation", 0);
1970 packet_put_cstring(term != NULL ? term : ""); 1902 packet_put_cstring(term != NULL ? term : "");
1971 packet_put_int((u_int)ws.ws_col); 1903 packet_put_int((u_int)ws.ws_col);
1972 packet_put_int((u_int)ws.ws_row); 1904 packet_put_int((u_int)ws.ws_row);
1973 packet_put_int((u_int)ws.ws_xpixel); 1905 packet_put_int((u_int)ws.ws_xpixel);
1974 packet_put_int((u_int)ws.ws_ypixel); 1906 packet_put_int((u_int)ws.ws_ypixel);
1975 tio = get_saved_tio(); 1907 if (tiop == NULL)
1976 tty_make_modes(-1, tiop != NULL ? tiop : &tio); 1908 tiop = get_saved_tio();
1909 tty_make_modes(-1, tiop);
1977 packet_send(); 1910 packet_send();
1978 /* XXX wait for reply */ 1911 /* XXX wait for reply */
1979 c->client_tty = 1; 1912 c->client_tty = 1;
@@ -2021,22 +1954,21 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
2021 if (len > 900) 1954 if (len > 900)
2022 len = 900; 1955 len = 900;
2023 if (want_subsystem) { 1956 if (want_subsystem) {
2024 debug("Sending subsystem: %.*s", len, (u_char*)buffer_ptr(cmd)); 1957 debug("Sending subsystem: %.*s",
2025 channel_request_start(id, "subsystem", subsys_repl != NULL); 1958 len, (u_char*)buffer_ptr(cmd));
2026 if (subsys_repl != NULL) { 1959 channel_request_start(id, "subsystem", 1);
2027 /* register callback for reply */ 1960 client_expect_confirm(id, "subsystem", 1);
2028 /* XXX we assume that client_loop has already been called */
2029 dispatch_set(SSH2_MSG_CHANNEL_FAILURE, subsys_repl);
2030 dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, subsys_repl);
2031 }
2032 } else { 1961 } else {
2033 debug("Sending command: %.*s", len, (u_char*)buffer_ptr(cmd)); 1962 debug("Sending command: %.*s",
2034 channel_request_start(id, "exec", 0); 1963 len, (u_char*)buffer_ptr(cmd));
1964 channel_request_start(id, "exec", 1);
1965 client_expect_confirm(id, "exec", 1);
2035 } 1966 }
2036 packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); 1967 packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
2037 packet_send(); 1968 packet_send();
2038 } else { 1969 } else {
2039 channel_request_start(id, "shell", 0); 1970 channel_request_start(id, "shell", 1);
1971 client_expect_confirm(id, "shell", 1);
2040 packet_send(); 1972 packet_send();
2041 } 1973 }
2042} 1974}
@@ -2055,6 +1987,8 @@ client_init_dispatch_20(void)
2055 dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); 1987 dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
2056 dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req); 1988 dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req);
2057 dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); 1989 dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
1990 dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &channel_input_status_confirm);
1991 dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &channel_input_status_confirm);
2058 dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request); 1992 dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request);
2059 1993
2060 /* rekeying */ 1994 /* rekeying */
@@ -2064,6 +1998,7 @@ client_init_dispatch_20(void)
2064 dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply); 1998 dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply);
2065 dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply); 1999 dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply);
2066} 2000}
2001
2067static void 2002static void
2068client_init_dispatch_13(void) 2003client_init_dispatch_13(void)
2069{ 2004{
@@ -2083,6 +2018,7 @@ client_init_dispatch_13(void)
2083 dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ? 2018 dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ?
2084 &x11_input_open : &deny_input_open); 2019 &x11_input_open : &deny_input_open);
2085} 2020}
2021
2086static void 2022static void
2087client_init_dispatch_15(void) 2023client_init_dispatch_15(void)
2088{ 2024{
@@ -2090,6 +2026,7 @@ client_init_dispatch_15(void)
2090 dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof); 2026 dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
2091 dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose); 2027 dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose);
2092} 2028}
2029
2093static void 2030static void
2094client_init_dispatch(void) 2031client_init_dispatch(void)
2095{ 2032{
@@ -2107,7 +2044,7 @@ cleanup_exit(int i)
2107{ 2044{
2108 leave_raw_mode(); 2045 leave_raw_mode();
2109 leave_non_blocking(); 2046 leave_non_blocking();
2110 if (options.control_path != NULL && control_fd != -1) 2047 if (options.control_path != NULL && muxserver_sock != -1)
2111 unlink(options.control_path); 2048 unlink(options.control_path);
2112 _exit(i); 2049 _exit(i);
2113} 2050}