summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c110
1 files changed, 75 insertions, 35 deletions
diff --git a/clientloop.c b/clientloop.c
index ed1902363..17628efb5 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.c,v 1.231 2011/01/16 12:05:59 djm Exp $ */ 1/* $OpenBSD: clientloop.c,v 1.236 2011/06/22 22:08:42 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
@@ -134,9 +134,6 @@ extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */
134 */ 134 */
135extern char *host; 135extern char *host;
136 136
137/* Force TTY allocation */
138extern int force_tty_flag;
139
140/* 137/*
141 * Flag to indicate that we have received a window change signal which has 138 * Flag to indicate that we have received a window change signal which has
142 * not yet been processed. This will cause a message indicating the new 139 * not yet been processed. This will cause a message indicating the new
@@ -183,7 +180,8 @@ struct escape_filter_ctx {
183/* Context for channel confirmation replies */ 180/* Context for channel confirmation replies */
184struct channel_reply_ctx { 181struct channel_reply_ctx {
185 const char *request_type; 182 const char *request_type;
186 int id, do_close; 183 int id;
184 enum confirm_action action;
187}; 185};
188 186
189/* Global request success/failure callbacks */ 187/* Global request success/failure callbacks */
@@ -269,10 +267,10 @@ static void
269set_control_persist_exit_time(void) 267set_control_persist_exit_time(void)
270{ 268{
271 if (muxserver_sock == -1 || !options.control_persist 269 if (muxserver_sock == -1 || !options.control_persist
272 || options.control_persist_timeout == 0) 270 || options.control_persist_timeout == 0) {
273 /* not using a ControlPersist timeout */ 271 /* not using a ControlPersist timeout */
274 control_persist_exit_time = 0; 272 control_persist_exit_time = 0;
275 else if (channel_still_open()) { 273 } else if (channel_still_open()) {
276 /* some client connections are still open */ 274 /* some client connections are still open */
277 if (control_persist_exit_time > 0) 275 if (control_persist_exit_time > 0)
278 debug2("%s: cancel scheduled exit", __func__); 276 debug2("%s: cancel scheduled exit", __func__);
@@ -666,7 +664,7 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
666 atomicio(vwrite, fileno(stderr), buffer_ptr(berr), 664 atomicio(vwrite, fileno(stderr), buffer_ptr(berr),
667 buffer_len(berr)); 665 buffer_len(berr));
668 666
669 leave_raw_mode(force_tty_flag); 667 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
670 668
671 /* 669 /*
672 * Free (and clear) the buffer to reduce the amount of data that gets 670 * Free (and clear) the buffer to reduce the amount of data that gets
@@ -687,7 +685,7 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
687 buffer_init(bout); 685 buffer_init(bout);
688 buffer_init(berr); 686 buffer_init(berr);
689 687
690 enter_raw_mode(force_tty_flag); 688 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
691} 689}
692 690
693static void 691static void
@@ -746,6 +744,15 @@ client_status_confirm(int type, Channel *c, void *ctx)
746 char errmsg[256]; 744 char errmsg[256];
747 int tochan; 745 int tochan;
748 746
747 /*
748 * If a TTY was explicitly requested, then a failure to allocate
749 * one is fatal.
750 */
751 if (cr->action == CONFIRM_TTY &&
752 (options.request_tty == REQUEST_TTY_FORCE ||
753 options.request_tty == REQUEST_TTY_YES))
754 cr->action = CONFIRM_CLOSE;
755
749 /* XXX supress on mux _client_ quietmode */ 756 /* XXX supress on mux _client_ quietmode */
750 tochan = options.log_level >= SYSLOG_LEVEL_ERROR && 757 tochan = options.log_level >= SYSLOG_LEVEL_ERROR &&
751 c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE; 758 c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE;
@@ -763,14 +770,27 @@ client_status_confirm(int type, Channel *c, void *ctx)
763 cr->request_type, c->self); 770 cr->request_type, c->self);
764 } 771 }
765 /* If error occurred on primary session channel, then exit */ 772 /* If error occurred on primary session channel, then exit */
766 if (cr->do_close && c->self == session_ident) 773 if (cr->action == CONFIRM_CLOSE && c->self == session_ident)
767 fatal("%s", errmsg); 774 fatal("%s", errmsg);
768 /* If error occurred on mux client, append to their stderr */ 775 /*
769 if (tochan) 776 * If error occurred on mux client, append to
770 buffer_append(&c->extended, errmsg, strlen(errmsg)); 777 * their stderr.
771 else 778 */
779 if (tochan) {
780 buffer_append(&c->extended, errmsg,
781 strlen(errmsg));
782 } else
772 error("%s", errmsg); 783 error("%s", errmsg);
773 if (cr->do_close) { 784 if (cr->action == CONFIRM_TTY) {
785 /*
786 * If a TTY allocation error occurred, then arrange
787 * for the correct TTY to leave raw mode.
788 */
789 if (c->self == session_ident)
790 leave_raw_mode(0);
791 else
792 mux_tty_alloc_failed(c);
793 } else if (cr->action == CONFIRM_CLOSE) {
774 chan_read_failed(c); 794 chan_read_failed(c);
775 chan_write_failed(c); 795 chan_write_failed(c);
776 } 796 }
@@ -784,13 +804,14 @@ client_abandon_status_confirm(Channel *c, void *ctx)
784 xfree(ctx); 804 xfree(ctx);
785} 805}
786 806
787static void 807void
788client_expect_confirm(int id, const char *request, int do_close) 808client_expect_confirm(int id, const char *request,
809 enum confirm_action action)
789{ 810{
790 struct channel_reply_ctx *cr = xmalloc(sizeof(*cr)); 811 struct channel_reply_ctx *cr = xmalloc(sizeof(*cr));
791 812
792 cr->request_type = request; 813 cr->request_type = request;
793 cr->do_close = do_close; 814 cr->action = action;
794 815
795 channel_register_status_confirm(id, client_status_confirm, 816 channel_register_status_confirm(id, client_status_confirm,
796 client_abandon_status_confirm, cr); 817 client_abandon_status_confirm, cr);
@@ -830,7 +851,7 @@ process_cmdline(void)
830 bzero(&fwd, sizeof(fwd)); 851 bzero(&fwd, sizeof(fwd));
831 fwd.listen_host = fwd.connect_host = NULL; 852 fwd.listen_host = fwd.connect_host = NULL;
832 853
833 leave_raw_mode(force_tty_flag); 854 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
834 handler = signal(SIGINT, SIG_IGN); 855 handler = signal(SIGINT, SIG_IGN);
835 cmd = s = read_passphrase("\r\nssh> ", RP_ECHO); 856 cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);
836 if (s == NULL) 857 if (s == NULL)
@@ -934,7 +955,7 @@ process_cmdline(void)
934 955
935out: 956out:
936 signal(SIGINT, handler); 957 signal(SIGINT, handler);
937 enter_raw_mode(force_tty_flag); 958 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
938 if (cmd) 959 if (cmd)
939 xfree(cmd); 960 xfree(cmd);
940 if (fwd.listen_host != NULL) 961 if (fwd.listen_host != NULL)
@@ -1053,7 +1074,8 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
1053 * more new connections). 1074 * more new connections).
1054 */ 1075 */
1055 /* Restore tty modes. */ 1076 /* Restore tty modes. */
1056 leave_raw_mode(force_tty_flag); 1077 leave_raw_mode(
1078 options.request_tty == REQUEST_TTY_FORCE);
1057 1079
1058 /* Stop listening for new connections. */ 1080 /* Stop listening for new connections. */
1059 channel_stop_listening(); 1081 channel_stop_listening();
@@ -1348,7 +1370,7 @@ client_channel_closed(int id, void *arg)
1348{ 1370{
1349 channel_cancel_cleanup(id); 1371 channel_cancel_cleanup(id);
1350 session_closed = 1; 1372 session_closed = 1;
1351 leave_raw_mode(force_tty_flag); 1373 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
1352} 1374}
1353 1375
1354/* 1376/*
@@ -1419,18 +1441,21 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1419 signal(SIGWINCH, window_change_handler); 1441 signal(SIGWINCH, window_change_handler);
1420 1442
1421 if (have_pty) 1443 if (have_pty)
1422 enter_raw_mode(force_tty_flag); 1444 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
1423 1445
1424 if (compat20) { 1446 if (compat20) {
1425 session_ident = ssh2_chan_id; 1447 session_ident = ssh2_chan_id;
1426 if (escape_char_arg != SSH_ESCAPECHAR_NONE) 1448 if (session_ident != -1) {
1427 channel_register_filter(session_ident, 1449 if (escape_char_arg != SSH_ESCAPECHAR_NONE) {
1428 client_simple_escape_filter, NULL, 1450 channel_register_filter(session_ident,
1429 client_filter_cleanup, 1451 client_simple_escape_filter, NULL,
1430 client_new_escape_filter_ctx(escape_char_arg)); 1452 client_filter_cleanup,
1431 if (session_ident != -1) 1453 client_new_escape_filter_ctx(
1454 escape_char_arg));
1455 }
1432 channel_register_cleanup(session_ident, 1456 channel_register_cleanup(session_ident,
1433 client_channel_closed, 0); 1457 client_channel_closed, 0);
1458 }
1434 } else { 1459 } else {
1435 /* Check if we should immediately send eof on stdin. */ 1460 /* Check if we should immediately send eof on stdin. */
1436 client_check_initial_eof_on_stdin(); 1461 client_check_initial_eof_on_stdin();
@@ -1569,7 +1594,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1569 channel_free_all(); 1594 channel_free_all();
1570 1595
1571 if (have_pty) 1596 if (have_pty)
1572 leave_raw_mode(force_tty_flag); 1597 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
1573 1598
1574 /* restore blocking io */ 1599 /* restore blocking io */
1575 if (!isatty(fileno(stdin))) 1600 if (!isatty(fileno(stdin)))
@@ -1995,7 +2020,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
1995 memset(&ws, 0, sizeof(ws)); 2020 memset(&ws, 0, sizeof(ws));
1996 2021
1997 channel_request_start(id, "pty-req", 1); 2022 channel_request_start(id, "pty-req", 1);
1998 client_expect_confirm(id, "PTY allocation", 1); 2023 client_expect_confirm(id, "PTY allocation", CONFIRM_TTY);
1999 packet_put_cstring(term != NULL ? term : ""); 2024 packet_put_cstring(term != NULL ? term : "");
2000 packet_put_int((u_int)ws.ws_col); 2025 packet_put_int((u_int)ws.ws_col);
2001 packet_put_int((u_int)ws.ws_row); 2026 packet_put_int((u_int)ws.ws_row);
@@ -2054,18 +2079,18 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
2054 debug("Sending subsystem: %.*s", 2079 debug("Sending subsystem: %.*s",
2055 len, (u_char*)buffer_ptr(cmd)); 2080 len, (u_char*)buffer_ptr(cmd));
2056 channel_request_start(id, "subsystem", 1); 2081 channel_request_start(id, "subsystem", 1);
2057 client_expect_confirm(id, "subsystem", 1); 2082 client_expect_confirm(id, "subsystem", CONFIRM_CLOSE);
2058 } else { 2083 } else {
2059 debug("Sending command: %.*s", 2084 debug("Sending command: %.*s",
2060 len, (u_char*)buffer_ptr(cmd)); 2085 len, (u_char*)buffer_ptr(cmd));
2061 channel_request_start(id, "exec", 1); 2086 channel_request_start(id, "exec", 1);
2062 client_expect_confirm(id, "exec", 1); 2087 client_expect_confirm(id, "exec", CONFIRM_CLOSE);
2063 } 2088 }
2064 packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); 2089 packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
2065 packet_send(); 2090 packet_send();
2066 } else { 2091 } else {
2067 channel_request_start(id, "shell", 1); 2092 channel_request_start(id, "shell", 1);
2068 client_expect_confirm(id, "shell", 1); 2093 client_expect_confirm(id, "shell", CONFIRM_CLOSE);
2069 packet_send(); 2094 packet_send();
2070 } 2095 }
2071} 2096}
@@ -2135,11 +2160,26 @@ client_init_dispatch(void)
2135 client_init_dispatch_15(); 2160 client_init_dispatch_15();
2136} 2161}
2137 2162
2163void
2164client_stop_mux(void)
2165{
2166 if (options.control_path != NULL && muxserver_sock != -1)
2167 unlink(options.control_path);
2168 /*
2169 * If we are in persist mode, signal that we should close when all
2170 * active channels are closed.
2171 */
2172 if (options.control_persist) {
2173 session_closed = 1;
2174 setproctitle("[stopped mux]");
2175 }
2176}
2177
2138/* client specific fatal cleanup */ 2178/* client specific fatal cleanup */
2139void 2179void
2140cleanup_exit(int i) 2180cleanup_exit(int i)
2141{ 2181{
2142 leave_raw_mode(force_tty_flag); 2182 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
2143 leave_non_blocking(); 2183 leave_non_blocking();
2144 if (options.control_path != NULL && muxserver_sock != -1) 2184 if (options.control_path != NULL && muxserver_sock != -1)
2145 unlink(options.control_path); 2185 unlink(options.control_path);