diff options
author | djm@openbsd.org <djm@openbsd.org> | 2017-04-30 23:13:25 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2017-05-01 09:42:37 +1000 |
commit | 97f4d3083b036ce3e68d6346a6140a22123d5864 (patch) | |
tree | 301c95453934721eca9855cd01b1d0da089e3246 /clientloop.c | |
parent | 99f95ba82673d33215dce17bfa1512b57f54ec09 (diff) |
upstream commit
remove compat20/compat13/compat15 variables
ok markus@
Upstream-ID: 43802c035ceb3fef6c50c400e4ecabf12354691c
Diffstat (limited to 'clientloop.c')
-rw-r--r-- | clientloop.c | 542 |
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 | |||
212 | static void | ||
213 | enter_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 | |||
463 | static void | ||
464 | client_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 | |||
518 | static void | ||
519 | client_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) | |||
549 | static void | 455 | static void |
550 | client_check_window_change(void) | 456 | client_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 | ||
575 | static int | 468 | static 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 */ | ||
1034 | struct escape_help_text { | 901 | struct 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 | ||
1054 | static void | 921 | static void |
1055 | print_escape_help(Buffer *b, int escape_char, int protocol2, int mux_client, | 922 | print_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 | ||
1328 | static void | ||
1329 | client_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 | |||
1384 | static void | ||
1385 | client_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 | ||
1799 | static int | ||
1800 | client_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 | } | ||
1810 | static int | ||
1811 | client_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 | } | ||
1821 | static int | ||
1822 | client_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 | |||
1839 | static int | ||
1840 | client_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 | |||
1885 | static Channel * | 1495 | static Channel * |
1886 | client_request_forwarded_tcpip(const char *request_type, int rchan, | 1496 | client_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 | ||
2689 | static void | 2294 | static void |
2690 | client_init_dispatch_20(void) | 2295 | client_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 | ||
2715 | static void | ||
2716 | client_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 | |||
2735 | static void | ||
2736 | client_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 | |||
2743 | static void | ||
2744 | client_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 | |||
2754 | void | 2320 | void |
2755 | client_stop_mux(void) | 2321 | client_stop_mux(void) |
2756 | { | 2322 | { |