summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2017-04-30 23:13:25 +0000
committerDamien Miller <djm@mindrot.org>2017-05-01 09:42:37 +1000
commit97f4d3083b036ce3e68d6346a6140a22123d5864 (patch)
tree301c95453934721eca9855cd01b1d0da089e3246 /clientloop.c
parent99f95ba82673d33215dce17bfa1512b57f54ec09 (diff)
upstream commit
remove compat20/compat13/compat15 variables ok markus@ Upstream-ID: 43802c035ceb3fef6c50c400e4ecabf12354691c
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c542
1 files changed, 54 insertions, 488 deletions
diff --git a/clientloop.c b/clientloop.c
index 064816234..469a2f00a 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.c,v 1.291 2017/03/10 05:01:13 djm Exp $ */ 1/* $OpenBSD: clientloop.c,v 1.292 2017/04/30 23:13:25 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
@@ -207,15 +207,6 @@ leave_non_blocking(void)
207 } 207 }
208} 208}
209 209
210/* Puts stdin terminal in non-blocking mode. */
211
212static void
213enter_non_blocking(void)
214{
215 in_non_blocking_mode = 1;
216 set_nonblock(fileno(stdin));
217}
218
219/* 210/*
220 * Signal handler for the window change signal (SIGWINCH). This just sets a 211 * Signal handler for the window change signal (SIGWINCH). This just sets a
221 * flag indicating that the window has changed. 212 * flag indicating that the window has changed.
@@ -455,91 +446,6 @@ client_x11_get_proto(const char *display, const char *xauth_path,
455} 446}
456 447
457/* 448/*
458 * This is called when the interactive is entered. This checks if there is
459 * an EOF coming on stdin. We must check this explicitly, as select() does
460 * not appear to wake up when redirecting from /dev/null.
461 */
462
463static void
464client_check_initial_eof_on_stdin(void)
465{
466 int len;
467 char buf[1];
468
469 /*
470 * If standard input is to be "redirected from /dev/null", we simply
471 * mark that we have seen an EOF and send an EOF message to the
472 * server. Otherwise, we try to read a single character; it appears
473 * that for some files, such /dev/null, select() never wakes up for
474 * read for this descriptor, which means that we never get EOF. This
475 * way we will get the EOF if stdin comes from /dev/null or similar.
476 */
477 if (stdin_null_flag) {
478 /* Fake EOF on stdin. */
479 debug("Sending eof.");
480 stdin_eof = 1;
481 packet_start(SSH_CMSG_EOF);
482 packet_send();
483 } else {
484 enter_non_blocking();
485
486 /* Check for immediate EOF on stdin. */
487 len = read(fileno(stdin), buf, 1);
488 if (len == 0) {
489 /*
490 * EOF. Record that we have seen it and send
491 * EOF to server.
492 */
493 debug("Sending eof.");
494 stdin_eof = 1;
495 packet_start(SSH_CMSG_EOF);
496 packet_send();
497 } else if (len > 0) {
498 /*
499 * Got data. We must store the data in the buffer,
500 * and also process it as an escape character if
501 * appropriate.
502 */
503 if ((u_char) buf[0] == escape_char1)
504 escape_pending1 = 1;
505 else
506 buffer_append(&stdin_buffer, buf, 1);
507 }
508 leave_non_blocking();
509 }
510}
511
512
513/*
514 * Make packets from buffered stdin data, and buffer them for sending to the
515 * connection.
516 */
517
518static void
519client_make_packets_from_stdin_data(void)
520{
521 u_int len;
522
523 /* Send buffered stdin data to the server. */
524 while (buffer_len(&stdin_buffer) > 0 &&
525 packet_not_very_much_data_to_write()) {
526 len = buffer_len(&stdin_buffer);
527 /* Keep the packets at reasonable size. */
528 if (len > packet_get_maxsize())
529 len = packet_get_maxsize();
530 packet_start(SSH_CMSG_STDIN_DATA);
531 packet_put_string(buffer_ptr(&stdin_buffer), len);
532 packet_send();
533 buffer_consume(&stdin_buffer, len);
534 /* If we have a pending EOF, send it now. */
535 if (stdin_eof && buffer_len(&stdin_buffer) == 0) {
536 packet_start(SSH_CMSG_EOF);
537 packet_send();
538 }
539 }
540}
541
542/*
543 * Checks if the client window has changed, and sends a packet about it to 449 * Checks if the client window has changed, and sends a packet about it to
544 * the server if so. The actual change is detected elsewhere (by a software 450 * the server if so. The actual change is detected elsewhere (by a software
545 * interrupt on Unix); this just checks the flag and sends a message if 451 * interrupt on Unix); this just checks the flag and sends a message if
@@ -549,27 +455,14 @@ client_make_packets_from_stdin_data(void)
549static void 455static void
550client_check_window_change(void) 456client_check_window_change(void)
551{ 457{
552 struct winsize ws; 458 if (!received_window_change_signal)
553
554 if (! received_window_change_signal)
555 return; 459 return;
556 /** XXX race */ 460 /** XXX race */
557 received_window_change_signal = 0; 461 received_window_change_signal = 0;
558 462
559 debug2("client_check_window_change: changed"); 463 debug2("%s: changed", __func__);
560 464
561 if (compat20) { 465 channel_send_window_changes();
562 channel_send_window_changes();
563 } else {
564 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
565 return;
566 packet_start(SSH_CMSG_WINDOW_SIZE);
567 packet_put_int((u_int)ws.ws_row);
568 packet_put_int((u_int)ws.ws_col);
569 packet_put_int((u_int)ws.ws_xpixel);
570 packet_put_int((u_int)ws.ws_ypixel);
571 packet_send();
572 }
573} 466}
574 467
575static int 468static int
@@ -623,35 +516,15 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
623 channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, 516 channel_prepare_select(readsetp, writesetp, maxfdp, nallocp,
624 &minwait_secs, rekeying); 517 &minwait_secs, rekeying);
625 518
626 if (!compat20) { 519 /* channel_prepare_select could have closed the last channel */
627 /* Read from the connection, unless our buffers are full. */ 520 if (session_closed && !channel_still_open() &&
628 if (buffer_len(&stdout_buffer) < buffer_high && 521 !packet_have_data_to_write()) {
629 buffer_len(&stderr_buffer) < buffer_high && 522 /* clear mask since we did not call select() */
630 channel_not_very_much_buffered_data()) 523 memset(*readsetp, 0, *nallocp);
631 FD_SET(connection_in, *readsetp); 524 memset(*writesetp, 0, *nallocp);
632 /* 525 return;
633 * Read from stdin, unless we have seen EOF or have very much
634 * buffered data to send to the server.
635 */
636 if (!stdin_eof && packet_not_very_much_data_to_write())
637 FD_SET(fileno(stdin), *readsetp);
638
639 /* Select stdout/stderr if have data in buffer. */
640 if (buffer_len(&stdout_buffer) > 0)
641 FD_SET(fileno(stdout), *writesetp);
642 if (buffer_len(&stderr_buffer) > 0)
643 FD_SET(fileno(stderr), *writesetp);
644 } else { 526 } else {
645 /* channel_prepare_select could have closed the last channel */ 527 FD_SET(connection_in, *readsetp);
646 if (session_closed && !channel_still_open() &&
647 !packet_have_data_to_write()) {
648 /* clear mask since we did not call select() */
649 memset(*readsetp, 0, *nallocp);
650 memset(*writesetp, 0, *nallocp);
651 return;
652 } else {
653 FD_SET(connection_in, *readsetp);
654 }
655 } 528 }
656 529
657 /* Select server connection if have data to write to the server. */ 530 /* Select server connection if have data to write to the server. */
@@ -665,11 +538,11 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
665 */ 538 */
666 539
667 timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */ 540 timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
668 if (options.server_alive_interval > 0 && compat20) { 541 if (options.server_alive_interval > 0) {
669 timeout_secs = options.server_alive_interval; 542 timeout_secs = options.server_alive_interval;
670 server_alive_time = now + options.server_alive_interval; 543 server_alive_time = now + options.server_alive_interval;
671 } 544 }
672 if (options.rekey_interval > 0 && compat20 && !rekeying) 545 if (options.rekey_interval > 0 && !rekeying)
673 timeout_secs = MINIMUM(timeout_secs, packet_get_rekey_timeout()); 546 timeout_secs = MINIMUM(timeout_secs, packet_get_rekey_timeout());
674 set_control_persist_exit_time(); 547 set_control_persist_exit_time();
675 if (control_persist_exit_time > 0) { 548 if (control_persist_exit_time > 0) {
@@ -966,11 +839,6 @@ process_cmdline(void)
966 goto out; 839 goto out;
967 } 840 }
968 841
969 if (delete && !compat20) {
970 logit("Not supported for SSH protocol version 1.");
971 goto out;
972 }
973
974 while (isspace((u_char)*++s)) 842 while (isspace((u_char)*++s))
975 ; 843 ;
976 844
@@ -1027,10 +895,9 @@ out:
1027 895
1028/* reasons to suppress output of an escape command in help output */ 896/* reasons to suppress output of an escape command in help output */
1029#define SUPPRESS_NEVER 0 /* never suppress, always show */ 897#define SUPPRESS_NEVER 0 /* never suppress, always show */
1030#define SUPPRESS_PROTO1 1 /* don't show in protocol 1 sessions */ 898#define SUPPRESS_MUXCLIENT 1 /* don't show in mux client sessions */
1031#define SUPPRESS_MUXCLIENT 2 /* don't show in mux client sessions */ 899#define SUPPRESS_MUXMASTER 2 /* don't show in mux master sessions */
1032#define SUPPRESS_MUXMASTER 4 /* don't show in mux master sessions */ 900#define SUPPRESS_SYSLOG 4 /* don't show when logging to syslog */
1033#define SUPPRESS_SYSLOG 8 /* don't show when logging to syslog */
1034struct escape_help_text { 901struct escape_help_text {
1035 const char *cmd; 902 const char *cmd;
1036 const char *text; 903 const char *text;
@@ -1040,9 +907,9 @@ static struct escape_help_text esc_txt[] = {
1040 {".", "terminate session", SUPPRESS_MUXMASTER}, 907 {".", "terminate session", SUPPRESS_MUXMASTER},
1041 {".", "terminate connection (and any multiplexed sessions)", 908 {".", "terminate connection (and any multiplexed sessions)",
1042 SUPPRESS_MUXCLIENT}, 909 SUPPRESS_MUXCLIENT},
1043 {"B", "send a BREAK to the remote system", SUPPRESS_PROTO1}, 910 {"B", "send a BREAK to the remote system", SUPPRESS_NEVER},
1044 {"C", "open a command line", SUPPRESS_MUXCLIENT}, 911 {"C", "open a command line", SUPPRESS_MUXCLIENT},
1045 {"R", "request rekey", SUPPRESS_PROTO1}, 912 {"R", "request rekey", SUPPRESS_NEVER},
1046 {"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT}, 913 {"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT},
1047 {"^Z", "suspend ssh", SUPPRESS_MUXCLIENT}, 914 {"^Z", "suspend ssh", SUPPRESS_MUXCLIENT},
1048 {"#", "list forwarded connections", SUPPRESS_NEVER}, 915 {"#", "list forwarded connections", SUPPRESS_NEVER},
@@ -1052,8 +919,7 @@ static struct escape_help_text esc_txt[] = {
1052}; 919};
1053 920
1054static void 921static void
1055print_escape_help(Buffer *b, int escape_char, int protocol2, int mux_client, 922print_escape_help(Buffer *b, int escape_char, int mux_client, int using_stderr)
1056 int using_stderr)
1057{ 923{
1058 unsigned int i, suppress_flags; 924 unsigned int i, suppress_flags;
1059 char string[1024]; 925 char string[1024];
@@ -1062,7 +928,7 @@ print_escape_help(Buffer *b, int escape_char, int protocol2, int mux_client,
1062 "Supported escape sequences:\r\n", escape_char); 928 "Supported escape sequences:\r\n", escape_char);
1063 buffer_append(b, string, strlen(string)); 929 buffer_append(b, string, strlen(string));
1064 930
1065 suppress_flags = (protocol2 ? 0 : SUPPRESS_PROTO1) | 931 suppress_flags =
1066 (mux_client ? SUPPRESS_MUXCLIENT : 0) | 932 (mux_client ? SUPPRESS_MUXCLIENT : 0) |
1067 (mux_client ? 0 : SUPPRESS_MUXMASTER) | 933 (mux_client ? 0 : SUPPRESS_MUXMASTER) |
1068 (using_stderr ? 0 : SUPPRESS_SYSLOG); 934 (using_stderr ? 0 : SUPPRESS_SYSLOG);
@@ -1171,26 +1037,20 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
1171 continue; 1037 continue;
1172 1038
1173 case 'B': 1039 case 'B':
1174 if (compat20) { 1040 snprintf(string, sizeof string,
1175 snprintf(string, sizeof string, 1041 "%cB\r\n", escape_char);
1176 "%cB\r\n", escape_char); 1042 buffer_append(berr, string, strlen(string));
1177 buffer_append(berr, string, 1043 channel_request_start(c->self, "break", 0);
1178 strlen(string)); 1044 packet_put_int(1000);
1179 channel_request_start(c->self, 1045 packet_send();
1180 "break", 0);
1181 packet_put_int(1000);
1182 packet_send();
1183 }
1184 continue; 1046 continue;
1185 1047
1186 case 'R': 1048 case 'R':
1187 if (compat20) { 1049 if (datafellows & SSH_BUG_NOREKEY)
1188 if (datafellows & SSH_BUG_NOREKEY) 1050 logit("Server does not "
1189 logit("Server does not " 1051 "support re-keying");
1190 "support re-keying"); 1052 else
1191 else 1053 need_rekeying = 1;
1192 need_rekeying = 1;
1193 }
1194 continue; 1054 continue;
1195 1055
1196 case 'V': 1056 case 'V':
@@ -1248,30 +1108,11 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
1248 exit(0); 1108 exit(0);
1249 } 1109 }
1250 /* The child continues serving connections. */ 1110 /* The child continues serving connections. */
1251 if (compat20) { 1111 buffer_append(bin, "\004", 1);
1252 buffer_append(bin, "\004", 1); 1112 /* fake EOF on stdin */
1253 /* fake EOF on stdin */ 1113 return -1;
1254 return -1;
1255 } else if (!stdin_eof) {
1256 /*
1257 * Sending SSH_CMSG_EOF alone does not
1258 * always appear to be enough. So we
1259 * try to send an EOF character first.
1260 */
1261 packet_start(SSH_CMSG_STDIN_DATA);
1262 packet_put_string("\004", 1);
1263 packet_send();
1264 /* Close stdin. */
1265 stdin_eof = 1;
1266 if (buffer_len(bin) == 0) {
1267 packet_start(SSH_CMSG_EOF);
1268 packet_send();
1269 }
1270 }
1271 continue;
1272
1273 case '?': 1114 case '?':
1274 print_escape_help(berr, escape_char, compat20, 1115 print_escape_help(berr, escape_char,
1275 (c && c->ctl_chan != -1), 1116 (c && c->ctl_chan != -1),
1276 log_is_on_stderr()); 1117 log_is_on_stderr());
1277 continue; 1118 continue;
@@ -1325,115 +1166,6 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
1325 return bytes; 1166 return bytes;
1326} 1167}
1327 1168
1328static void
1329client_process_input(fd_set *readset)
1330{
1331 int len;
1332 char buf[SSH_IOBUFSZ];
1333
1334 /* Read input from stdin. */
1335 if (FD_ISSET(fileno(stdin), readset)) {
1336 /* Read as much as possible. */
1337 len = read(fileno(stdin), buf, sizeof(buf));
1338 if (len < 0 &&
1339 (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
1340 return; /* we'll try again later */
1341 if (len <= 0) {
1342 /*
1343 * Received EOF or error. They are treated
1344 * similarly, except that an error message is printed
1345 * if it was an error condition.
1346 */
1347 if (len < 0) {
1348 snprintf(buf, sizeof buf, "read: %.100s\r\n",
1349 strerror(errno));
1350 buffer_append(&stderr_buffer, buf, strlen(buf));
1351 }
1352 /* Mark that we have seen EOF. */
1353 stdin_eof = 1;
1354 /*
1355 * Send an EOF message to the server unless there is
1356 * data in the buffer. If there is data in the
1357 * buffer, no message will be sent now. Code
1358 * elsewhere will send the EOF when the buffer
1359 * becomes empty if stdin_eof is set.
1360 */
1361 if (buffer_len(&stdin_buffer) == 0) {
1362 packet_start(SSH_CMSG_EOF);
1363 packet_send();
1364 }
1365 } else if (escape_char1 == SSH_ESCAPECHAR_NONE) {
1366 /*
1367 * Normal successful read, and no escape character.
1368 * Just append the data to buffer.
1369 */
1370 buffer_append(&stdin_buffer, buf, len);
1371 } else {
1372 /*
1373 * Normal, successful read. But we have an escape
1374 * character and have to process the characters one
1375 * by one.
1376 */
1377 if (process_escapes(NULL, &stdin_buffer,
1378 &stdout_buffer, &stderr_buffer, buf, len) == -1)
1379 return;
1380 }
1381 }
1382}
1383
1384static void
1385client_process_output(fd_set *writeset)
1386{
1387 int len;
1388 char buf[100];
1389
1390 /* Write buffered output to stdout. */
1391 if (FD_ISSET(fileno(stdout), writeset)) {
1392 /* Write as much data as possible. */
1393 len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
1394 buffer_len(&stdout_buffer));
1395 if (len <= 0) {
1396 if (errno == EINTR || errno == EAGAIN ||
1397 errno == EWOULDBLOCK)
1398 len = 0;
1399 else {
1400 /*
1401 * An error or EOF was encountered. Put an
1402 * error message to stderr buffer.
1403 */
1404 snprintf(buf, sizeof buf,
1405 "write stdout: %.50s\r\n", strerror(errno));
1406 buffer_append(&stderr_buffer, buf, strlen(buf));
1407 quit_pending = 1;
1408 return;
1409 }
1410 }
1411 /* Consume printed data from the buffer. */
1412 buffer_consume(&stdout_buffer, len);
1413 }
1414 /* Write buffered output to stderr. */
1415 if (FD_ISSET(fileno(stderr), writeset)) {
1416 /* Write as much data as possible. */
1417 len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
1418 buffer_len(&stderr_buffer));
1419 if (len <= 0) {
1420 if (errno == EINTR || errno == EAGAIN ||
1421 errno == EWOULDBLOCK)
1422 len = 0;
1423 else {
1424 /*
1425 * EOF or error, but can't even print
1426 * error message.
1427 */
1428 quit_pending = 1;
1429 return;
1430 }
1431 }
1432 /* Consume printed characters from the buffer. */
1433 buffer_consume(&stderr_buffer, len);
1434 }
1435}
1436
1437/* 1169/*
1438 * Get packets from the connection input buffer, and process them as long as 1170 * Get packets from the connection input buffer, and process them as long as
1439 * there are packets available. 1171 * there are packets available.
@@ -1553,18 +1285,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1553 connection_out = packet_get_connection_out(); 1285 connection_out = packet_get_connection_out();
1554 max_fd = MAXIMUM(connection_in, connection_out); 1286 max_fd = MAXIMUM(connection_in, connection_out);
1555 1287
1556 if (!compat20) {
1557 /* enable nonblocking unless tty */
1558 if (!isatty(fileno(stdin)))
1559 set_nonblock(fileno(stdin));
1560 if (!isatty(fileno(stdout)))
1561 set_nonblock(fileno(stdout));
1562 if (!isatty(fileno(stderr)))
1563 set_nonblock(fileno(stderr));
1564 max_fd = MAXIMUM(max_fd, fileno(stdin));
1565 max_fd = MAXIMUM(max_fd, fileno(stdout));
1566 max_fd = MAXIMUM(max_fd, fileno(stderr));
1567 }
1568 quit_pending = 0; 1288 quit_pending = 0;
1569 escape_char1 = escape_char_arg; 1289 escape_char1 = escape_char_arg;
1570 1290
@@ -1592,22 +1312,17 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1592 if (have_pty) 1312 if (have_pty)
1593 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); 1313 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
1594 1314
1595 if (compat20) { 1315 session_ident = ssh2_chan_id;
1596 session_ident = ssh2_chan_id; 1316 if (session_ident != -1) {
1597 if (session_ident != -1) { 1317 if (escape_char_arg != SSH_ESCAPECHAR_NONE) {
1598 if (escape_char_arg != SSH_ESCAPECHAR_NONE) { 1318 channel_register_filter(session_ident,
1599 channel_register_filter(session_ident, 1319 client_simple_escape_filter, NULL,
1600 client_simple_escape_filter, NULL, 1320 client_filter_cleanup,
1601 client_filter_cleanup, 1321 client_new_escape_filter_ctx(
1602 client_new_escape_filter_ctx( 1322 escape_char_arg));
1603 escape_char_arg));
1604 }
1605 channel_register_cleanup(session_ident,
1606 client_channel_closed, 0);
1607 } 1323 }
1608 } else { 1324 channel_register_cleanup(session_ident,
1609 /* Check if we should immediately send eof on stdin. */ 1325 client_channel_closed, 0);
1610 client_check_initial_eof_on_stdin();
1611 } 1326 }
1612 1327
1613 /* Main loop of the client for the interactive session mode. */ 1328 /* Main loop of the client for the interactive session mode. */
@@ -1616,7 +1331,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1616 /* Process buffered packets sent by the server. */ 1331 /* Process buffered packets sent by the server. */
1617 client_process_buffered_input_packets(); 1332 client_process_buffered_input_packets();
1618 1333
1619 if (compat20 && session_closed && !channel_still_open()) 1334 if (session_closed && !channel_still_open())
1620 break; 1335 break;
1621 1336
1622 if (ssh_packet_is_rekeying(active_state)) { 1337 if (ssh_packet_is_rekeying(active_state)) {
@@ -1630,13 +1345,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1630 need_rekeying = 0; 1345 need_rekeying = 0;
1631 } else { 1346 } else {
1632 /* 1347 /*
1633 * Make packets of buffered stdin data, and buffer
1634 * them for sending to the server.
1635 */
1636 if (!compat20)
1637 client_make_packets_from_stdin_data();
1638
1639 /*
1640 * Make packets from buffered channel data, and 1348 * Make packets from buffered channel data, and
1641 * enqueue them for sending to the server. 1349 * enqueue them for sending to the server.
1642 */ 1350 */
@@ -1673,16 +1381,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1673 if (quit_pending) 1381 if (quit_pending)
1674 break; 1382 break;
1675 1383
1676 if (!compat20) {
1677 /* Buffer data from stdin */
1678 client_process_input(readset);
1679 /*
1680 * Process output to stdout and stderr. Output to
1681 * the connection is processed elsewhere (above).
1682 */
1683 client_process_output(writeset);
1684 }
1685
1686 /* 1384 /*
1687 * Send as much buffered packet data as possible to the 1385 * Send as much buffered packet data as possible to the
1688 * sender. 1386 * sender.
@@ -1710,14 +1408,12 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1710 /* Stop watching for window change. */ 1408 /* Stop watching for window change. */
1711 signal(SIGWINCH, SIG_DFL); 1409 signal(SIGWINCH, SIG_DFL);
1712 1410
1713 if (compat20) { 1411 packet_start(SSH2_MSG_DISCONNECT);
1714 packet_start(SSH2_MSG_DISCONNECT); 1412 packet_put_int(SSH2_DISCONNECT_BY_APPLICATION);
1715 packet_put_int(SSH2_DISCONNECT_BY_APPLICATION); 1413 packet_put_cstring("disconnected by user");
1716 packet_put_cstring("disconnected by user"); 1414 packet_put_cstring(""); /* language tag */
1717 packet_put_cstring(""); /* language tag */ 1415 packet_send();
1718 packet_send(); 1416 packet_write_wait();
1719 packet_write_wait();
1720 }
1721 1417
1722 channel_free_all(); 1418 channel_free_all();
1723 1419
@@ -1796,92 +1492,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1796 1492
1797/*********/ 1493/*********/
1798 1494
1799static int
1800client_input_stdout_data(int type, u_int32_t seq, void *ctxt)
1801{
1802 u_int data_len;
1803 char *data = packet_get_string(&data_len);
1804 packet_check_eom();
1805 buffer_append(&stdout_buffer, data, data_len);
1806 explicit_bzero(data, data_len);
1807 free(data);
1808 return 0;
1809}
1810static int
1811client_input_stderr_data(int type, u_int32_t seq, void *ctxt)
1812{
1813 u_int data_len;
1814 char *data = packet_get_string(&data_len);
1815 packet_check_eom();
1816 buffer_append(&stderr_buffer, data, data_len);
1817 explicit_bzero(data, data_len);
1818 free(data);
1819 return 0;
1820}
1821static int
1822client_input_exit_status(int type, u_int32_t seq, void *ctxt)
1823{
1824 exit_status = packet_get_int();
1825 packet_check_eom();
1826 /* Acknowledge the exit. */
1827 packet_start(SSH_CMSG_EXIT_CONFIRMATION);
1828 packet_send();
1829 /*
1830 * Must wait for packet to be sent since we are
1831 * exiting the loop.
1832 */
1833 packet_write_wait();
1834 /* Flag that we want to exit. */
1835 quit_pending = 1;
1836 return 0;
1837}
1838
1839static int
1840client_input_agent_open(int type, u_int32_t seq, void *ctxt)
1841{
1842 Channel *c = NULL;
1843 int r, remote_id, sock;
1844
1845 /* Read the remote channel number from the message. */
1846 remote_id = packet_get_int();
1847 packet_check_eom();
1848
1849 /*
1850 * Get a connection to the local authentication agent (this may again
1851 * get forwarded).
1852 */
1853 if ((r = ssh_get_authentication_socket(&sock)) != 0 &&
1854 r != SSH_ERR_AGENT_NOT_PRESENT)
1855 debug("%s: ssh_get_authentication_socket: %s",
1856 __func__, ssh_err(r));
1857
1858
1859 /*
1860 * If we could not connect the agent, send an error message back to
1861 * the server. This should never happen unless the agent dies,
1862 * because authentication forwarding is only enabled if we have an
1863 * agent.
1864 */
1865 if (sock >= 0) {
1866 c = channel_new("", SSH_CHANNEL_OPEN, sock, sock,
1867 -1, 0, 0, 0, "authentication agent connection", 1);
1868 c->remote_id = remote_id;
1869 c->force_drain = 1;
1870 }
1871 if (c == NULL) {
1872 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
1873 packet_put_int(remote_id);
1874 } else {
1875 /* Send a confirmation to the remote host. */
1876 debug("Forwarding authentication connection.");
1877 packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
1878 packet_put_int(remote_id);
1879 packet_put_int(c->self);
1880 }
1881 packet_send();
1882 return 0;
1883}
1884
1885static Channel * 1495static Channel *
1886client_request_forwarded_tcpip(const char *request_type, int rchan, 1496client_request_forwarded_tcpip(const char *request_type, int rchan,
1887 u_int rwindow, u_int rmaxpack) 1497 u_int rwindow, u_int rmaxpack)
@@ -2032,11 +1642,6 @@ client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun)
2032 if (tun_mode == SSH_TUNMODE_NO) 1642 if (tun_mode == SSH_TUNMODE_NO)
2033 return 0; 1643 return 0;
2034 1644
2035 if (!compat20) {
2036 error("Tunnel forwarding is not supported for protocol 1");
2037 return -1;
2038 }
2039
2040 debug("Requesting tun unit %d in mode %d", local_tun, tun_mode); 1645 debug("Requesting tun unit %d in mode %d", local_tun, tun_mode);
2041 1646
2042 /* Open local tunnel device */ 1647 /* Open local tunnel device */
@@ -2687,7 +2292,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
2687} 2292}
2688 2293
2689static void 2294static void
2690client_init_dispatch_20(void) 2295client_init_dispatch(void)
2691{ 2296{
2692 dispatch_init(&dispatch_protocol_error); 2297 dispatch_init(&dispatch_protocol_error);
2693 2298
@@ -2712,45 +2317,6 @@ client_init_dispatch_20(void)
2712 dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply); 2317 dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply);
2713} 2318}
2714 2319
2715static void
2716client_init_dispatch_13(void)
2717{
2718 dispatch_init(NULL);
2719 dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
2720 dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
2721 dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
2722 dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
2723 dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
2724 dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
2725 dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status);
2726 dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data);
2727 dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data);
2728
2729 dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ?
2730 &client_input_agent_open : &deny_input_open);
2731 dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ?
2732 &x11_input_open : &deny_input_open);
2733}
2734
2735static void
2736client_init_dispatch_15(void)
2737{
2738 client_init_dispatch_13();
2739 dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
2740 dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose);
2741}
2742
2743static void
2744client_init_dispatch(void)
2745{
2746 if (compat20)
2747 client_init_dispatch_20();
2748 else if (compat13)
2749 client_init_dispatch_13();
2750 else
2751 client_init_dispatch_15();
2752}
2753
2754void 2320void
2755client_stop_mux(void) 2321client_stop_mux(void)
2756{ 2322{