diff options
Diffstat (limited to 'clientloop.c')
-rw-r--r-- | clientloop.c | 75 |
1 files changed, 40 insertions, 35 deletions
diff --git a/clientloop.c b/clientloop.c index 141e0fff5..e5ea74e26 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.213 2009/07/05 19:28:33 stevesk Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.218 2010/01/28 00:21:18 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 |
@@ -125,7 +125,7 @@ extern int stdin_null_flag; | |||
125 | extern int no_shell_flag; | 125 | extern int no_shell_flag; |
126 | 126 | ||
127 | /* Control socket */ | 127 | /* Control socket */ |
128 | extern int muxserver_sock; | 128 | extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */ |
129 | 129 | ||
130 | /* | 130 | /* |
131 | * Name of the host we are connecting to. This is the name given on the | 131 | * Name of the host we are connecting to. This is the name given on the |
@@ -134,6 +134,9 @@ extern int muxserver_sock; | |||
134 | */ | 134 | */ |
135 | extern char *host; | 135 | extern char *host; |
136 | 136 | ||
137 | /* Force TTY allocation */ | ||
138 | extern int force_tty_flag; | ||
139 | |||
137 | /* | 140 | /* |
138 | * Flag to indicate that we have received a window change signal which has | 141 | * Flag to indicate that we have received a window change signal which has |
139 | * not yet been processed. This will cause a message indicating the new | 142 | * not yet been processed. This will cause a message indicating the new |
@@ -147,7 +150,7 @@ static volatile sig_atomic_t received_signal = 0; | |||
147 | static int in_non_blocking_mode = 0; | 150 | static int in_non_blocking_mode = 0; |
148 | 151 | ||
149 | /* Common data for the client loop code. */ | 152 | /* Common data for the client loop code. */ |
150 | static volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ | 153 | volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ |
151 | static int escape_char1; /* Escape character. (proto1 only) */ | 154 | static int escape_char1; /* Escape character. (proto1 only) */ |
152 | static int escape_pending1; /* Last character was an escape (proto1 only) */ | 155 | static int escape_pending1; /* Last character was an escape (proto1 only) */ |
153 | static int last_was_cr; /* Last character was a newline. */ | 156 | static int last_was_cr; /* Last character was a newline. */ |
@@ -165,6 +168,8 @@ static int session_closed = 0; /* In SSH2: login session closed. */ | |||
165 | static void client_init_dispatch(void); | 168 | static void client_init_dispatch(void); |
166 | int session_ident = -1; | 169 | int session_ident = -1; |
167 | 170 | ||
171 | int session_resumed = 0; | ||
172 | |||
168 | /* Track escape per proto2 channel */ | 173 | /* Track escape per proto2 channel */ |
169 | struct escape_filter_ctx { | 174 | struct escape_filter_ctx { |
170 | int escape_pending; | 175 | int escape_pending; |
@@ -563,9 +568,6 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | |||
563 | if (packet_have_data_to_write()) | 568 | if (packet_have_data_to_write()) |
564 | FD_SET(connection_out, *writesetp); | 569 | FD_SET(connection_out, *writesetp); |
565 | 570 | ||
566 | if (muxserver_sock != -1) | ||
567 | FD_SET(muxserver_sock, *readsetp); | ||
568 | |||
569 | /* | 571 | /* |
570 | * Wait for something to happen. This will suspend the process until | 572 | * Wait for something to happen. This will suspend the process until |
571 | * some selected descriptor can be read, written, or has some other | 573 | * some selected descriptor can be read, written, or has some other |
@@ -612,7 +614,7 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) | |||
612 | atomicio(vwrite, fileno(stderr), buffer_ptr(berr), | 614 | atomicio(vwrite, fileno(stderr), buffer_ptr(berr), |
613 | buffer_len(berr)); | 615 | buffer_len(berr)); |
614 | 616 | ||
615 | leave_raw_mode(); | 617 | leave_raw_mode(force_tty_flag); |
616 | 618 | ||
617 | /* | 619 | /* |
618 | * Free (and clear) the buffer to reduce the amount of data that gets | 620 | * Free (and clear) the buffer to reduce the amount of data that gets |
@@ -633,7 +635,7 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) | |||
633 | buffer_init(bout); | 635 | buffer_init(bout); |
634 | buffer_init(berr); | 636 | buffer_init(berr); |
635 | 637 | ||
636 | enter_raw_mode(); | 638 | enter_raw_mode(force_tty_flag); |
637 | } | 639 | } |
638 | 640 | ||
639 | static void | 641 | static void |
@@ -694,7 +696,7 @@ client_status_confirm(int type, Channel *c, void *ctx) | |||
694 | 696 | ||
695 | /* XXX supress on mux _client_ quietmode */ | 697 | /* XXX supress on mux _client_ quietmode */ |
696 | tochan = options.log_level >= SYSLOG_LEVEL_ERROR && | 698 | tochan = options.log_level >= SYSLOG_LEVEL_ERROR && |
697 | c->ctl_fd != -1 && c->extended_usage == CHAN_EXTENDED_WRITE; | 699 | c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE; |
698 | 700 | ||
699 | if (type == SSH2_MSG_CHANNEL_SUCCESS) { | 701 | if (type == SSH2_MSG_CHANNEL_SUCCESS) { |
700 | debug2("%s request accepted on channel %d", | 702 | debug2("%s request accepted on channel %d", |
@@ -776,7 +778,7 @@ process_cmdline(void) | |||
776 | bzero(&fwd, sizeof(fwd)); | 778 | bzero(&fwd, sizeof(fwd)); |
777 | fwd.listen_host = fwd.connect_host = NULL; | 779 | fwd.listen_host = fwd.connect_host = NULL; |
778 | 780 | ||
779 | leave_raw_mode(); | 781 | leave_raw_mode(force_tty_flag); |
780 | handler = signal(SIGINT, SIG_IGN); | 782 | handler = signal(SIGINT, SIG_IGN); |
781 | cmd = s = read_passphrase("\r\nssh> ", RP_ECHO); | 783 | cmd = s = read_passphrase("\r\nssh> ", RP_ECHO); |
782 | if (s == NULL) | 784 | if (s == NULL) |
@@ -838,6 +840,7 @@ process_cmdline(void) | |||
838 | while (isspace(*++s)) | 840 | while (isspace(*++s)) |
839 | ; | 841 | ; |
840 | 842 | ||
843 | /* XXX update list of forwards in options */ | ||
841 | if (delete) { | 844 | if (delete) { |
842 | cancel_port = 0; | 845 | cancel_port = 0; |
843 | cancel_host = hpdelim(&s); /* may be NULL */ | 846 | cancel_host = hpdelim(&s); /* may be NULL */ |
@@ -879,7 +882,7 @@ process_cmdline(void) | |||
879 | 882 | ||
880 | out: | 883 | out: |
881 | signal(SIGINT, handler); | 884 | signal(SIGINT, handler); |
882 | enter_raw_mode(); | 885 | enter_raw_mode(force_tty_flag); |
883 | if (cmd) | 886 | if (cmd) |
884 | xfree(cmd); | 887 | xfree(cmd); |
885 | if (fwd.listen_host != NULL) | 888 | if (fwd.listen_host != NULL) |
@@ -935,7 +938,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
935 | escape_char); | 938 | escape_char); |
936 | buffer_append(berr, string, strlen(string)); | 939 | buffer_append(berr, string, strlen(string)); |
937 | 940 | ||
938 | if (c && c->ctl_fd != -1) { | 941 | if (c && c->ctl_chan != -1) { |
939 | chan_read_failed(c); | 942 | chan_read_failed(c); |
940 | chan_write_failed(c); | 943 | chan_write_failed(c); |
941 | return 0; | 944 | return 0; |
@@ -945,7 +948,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
945 | 948 | ||
946 | case 'Z' - 64: | 949 | case 'Z' - 64: |
947 | /* XXX support this for mux clients */ | 950 | /* XXX support this for mux clients */ |
948 | if (c && c->ctl_fd != -1) { | 951 | if (c && c->ctl_chan != -1) { |
949 | noescape: | 952 | noescape: |
950 | snprintf(string, sizeof string, | 953 | snprintf(string, sizeof string, |
951 | "%c%c escape not available to " | 954 | "%c%c escape not available to " |
@@ -990,7 +993,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
990 | continue; | 993 | continue; |
991 | 994 | ||
992 | case '&': | 995 | case '&': |
993 | if (c && c->ctl_fd != -1) | 996 | if (c && c->ctl_chan != -1) |
994 | goto noescape; | 997 | goto noescape; |
995 | /* | 998 | /* |
996 | * Detach the program (continue to serve | 999 | * Detach the program (continue to serve |
@@ -998,7 +1001,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
998 | * more new connections). | 1001 | * more new connections). |
999 | */ | 1002 | */ |
1000 | /* Restore tty modes. */ | 1003 | /* Restore tty modes. */ |
1001 | leave_raw_mode(); | 1004 | leave_raw_mode(force_tty_flag); |
1002 | 1005 | ||
1003 | /* Stop listening for new connections. */ | 1006 | /* Stop listening for new connections. */ |
1004 | channel_stop_listening(); | 1007 | channel_stop_listening(); |
@@ -1041,7 +1044,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1041 | continue; | 1044 | continue; |
1042 | 1045 | ||
1043 | case '?': | 1046 | case '?': |
1044 | if (c && c->ctl_fd != -1) { | 1047 | if (c && c->ctl_chan != -1) { |
1045 | snprintf(string, sizeof string, | 1048 | snprintf(string, sizeof string, |
1046 | "%c?\r\n\ | 1049 | "%c?\r\n\ |
1047 | Supported escape sequences:\r\n\ | 1050 | Supported escape sequences:\r\n\ |
@@ -1090,7 +1093,7 @@ Supported escape sequences:\r\n\ | |||
1090 | continue; | 1093 | continue; |
1091 | 1094 | ||
1092 | case 'C': | 1095 | case 'C': |
1093 | if (c && c->ctl_fd != -1) | 1096 | if (c && c->ctl_chan != -1) |
1094 | goto noescape; | 1097 | goto noescape; |
1095 | process_cmdline(); | 1098 | process_cmdline(); |
1096 | continue; | 1099 | continue; |
@@ -1293,7 +1296,7 @@ client_channel_closed(int id, void *arg) | |||
1293 | { | 1296 | { |
1294 | channel_cancel_cleanup(id); | 1297 | channel_cancel_cleanup(id); |
1295 | session_closed = 1; | 1298 | session_closed = 1; |
1296 | leave_raw_mode(); | 1299 | leave_raw_mode(force_tty_flag); |
1297 | } | 1300 | } |
1298 | 1301 | ||
1299 | /* | 1302 | /* |
@@ -1326,8 +1329,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1326 | connection_in = packet_get_connection_in(); | 1329 | connection_in = packet_get_connection_in(); |
1327 | connection_out = packet_get_connection_out(); | 1330 | connection_out = packet_get_connection_out(); |
1328 | max_fd = MAX(connection_in, connection_out); | 1331 | max_fd = MAX(connection_in, connection_out); |
1329 | if (muxserver_sock != -1) | ||
1330 | max_fd = MAX(max_fd, muxserver_sock); | ||
1331 | 1332 | ||
1332 | if (!compat20) { | 1333 | if (!compat20) { |
1333 | /* enable nonblocking unless tty */ | 1334 | /* enable nonblocking unless tty */ |
@@ -1366,7 +1367,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1366 | signal(SIGWINCH, window_change_handler); | 1367 | signal(SIGWINCH, window_change_handler); |
1367 | 1368 | ||
1368 | if (have_pty) | 1369 | if (have_pty) |
1369 | enter_raw_mode(); | 1370 | enter_raw_mode(force_tty_flag); |
1370 | 1371 | ||
1371 | if (compat20) { | 1372 | if (compat20) { |
1372 | session_ident = ssh2_chan_id; | 1373 | session_ident = ssh2_chan_id; |
@@ -1454,12 +1455,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1454 | /* Buffer input from the connection. */ | 1455 | /* Buffer input from the connection. */ |
1455 | client_process_net_input(readset); | 1456 | client_process_net_input(readset); |
1456 | 1457 | ||
1457 | /* Accept control connections. */ | ||
1458 | if (muxserver_sock != -1 &&FD_ISSET(muxserver_sock, readset)) { | ||
1459 | if (muxserver_accept_control()) | ||
1460 | quit_pending = 1; | ||
1461 | } | ||
1462 | |||
1463 | if (quit_pending) | 1458 | if (quit_pending) |
1464 | break; | 1459 | break; |
1465 | 1460 | ||
@@ -1473,6 +1468,14 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1473 | client_process_output(writeset); | 1468 | client_process_output(writeset); |
1474 | } | 1469 | } |
1475 | 1470 | ||
1471 | if (session_resumed) { | ||
1472 | connection_in = packet_get_connection_in(); | ||
1473 | connection_out = packet_get_connection_out(); | ||
1474 | max_fd = MAX(max_fd, connection_out); | ||
1475 | max_fd = MAX(max_fd, connection_in); | ||
1476 | session_resumed = 0; | ||
1477 | } | ||
1478 | |||
1476 | /* | 1479 | /* |
1477 | * Send as much buffered packet data as possible to the | 1480 | * Send as much buffered packet data as possible to the |
1478 | * sender. | 1481 | * sender. |
@@ -1501,7 +1504,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1501 | channel_free_all(); | 1504 | channel_free_all(); |
1502 | 1505 | ||
1503 | if (have_pty) | 1506 | if (have_pty) |
1504 | leave_raw_mode(); | 1507 | leave_raw_mode(force_tty_flag); |
1505 | 1508 | ||
1506 | /* restore blocking io */ | 1509 | /* restore blocking io */ |
1507 | if (!isatty(fileno(stdin))) | 1510 | if (!isatty(fileno(stdin))) |
@@ -1859,15 +1862,17 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt) | |||
1859 | chan_rcvd_eow(c); | 1862 | chan_rcvd_eow(c); |
1860 | } else if (strcmp(rtype, "exit-status") == 0) { | 1863 | } else if (strcmp(rtype, "exit-status") == 0) { |
1861 | exitval = packet_get_int(); | 1864 | exitval = packet_get_int(); |
1862 | if (id == session_ident) { | 1865 | if (c->ctl_chan != -1) { |
1866 | mux_exit_message(c, exitval); | ||
1867 | success = 1; | ||
1868 | } else if (id == session_ident) { | ||
1869 | /* Record exit value of local session */ | ||
1863 | success = 1; | 1870 | success = 1; |
1864 | exit_status = exitval; | 1871 | exit_status = exitval; |
1865 | } else if (c->ctl_fd == -1) { | ||
1866 | error("client_input_channel_req: unexpected channel %d", | ||
1867 | session_ident); | ||
1868 | } else { | 1872 | } else { |
1869 | atomicio(vwrite, c->ctl_fd, &exitval, sizeof(exitval)); | 1873 | /* Probably for a mux channel that has already closed */ |
1870 | success = 1; | 1874 | debug("%s: no sink for exit-status on channel %d", |
1875 | __func__, id); | ||
1871 | } | 1876 | } |
1872 | packet_check_eom(); | 1877 | packet_check_eom(); |
1873 | } | 1878 | } |
@@ -2063,7 +2068,7 @@ client_init_dispatch(void) | |||
2063 | void | 2068 | void |
2064 | cleanup_exit(int i) | 2069 | cleanup_exit(int i) |
2065 | { | 2070 | { |
2066 | leave_raw_mode(); | 2071 | leave_raw_mode(force_tty_flag); |
2067 | leave_non_blocking(); | 2072 | leave_non_blocking(); |
2068 | if (options.control_path != NULL && muxserver_sock != -1) | 2073 | if (options.control_path != NULL && muxserver_sock != -1) |
2069 | unlink(options.control_path); | 2074 | unlink(options.control_path); |