diff options
-rw-r--r-- | clientloop.c | 83 |
1 files changed, 25 insertions, 58 deletions
diff --git a/clientloop.c b/clientloop.c index 018688a81..db04098b8 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.293 2017/04/30 23:18:44 djm Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.294 2017/04/30 23:21:54 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 |
@@ -152,15 +152,9 @@ static time_t control_persist_exit_time = 0; | |||
152 | 152 | ||
153 | /* Common data for the client loop code. */ | 153 | /* Common data for the client loop code. */ |
154 | volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ | 154 | volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ |
155 | static int escape_char1; /* Escape character. (proto1 only) */ | ||
156 | static int escape_pending1; /* Last character was an escape (proto1 only) */ | ||
157 | static int last_was_cr; /* Last character was a newline. */ | 155 | static int last_was_cr; /* Last character was a newline. */ |
158 | static int exit_status; /* Used to store the command exit status. */ | 156 | static int exit_status; /* Used to store the command exit status. */ |
159 | static int stdin_eof; /* EOF has been encountered on stderr. */ | 157 | static Buffer stderr_buffer; /* Used for final exit message. */ |
160 | static Buffer stdin_buffer; /* Buffer for stdin data. */ | ||
161 | static Buffer stdout_buffer; /* Buffer for stdout data. */ | ||
162 | static Buffer stderr_buffer; /* Buffer for stderr data. */ | ||
163 | static u_int buffer_high; /* Soft max buffer size. */ | ||
164 | static int connection_in; /* Connection to server (input). */ | 158 | static int connection_in; /* Connection to server (input). */ |
165 | static int connection_out; /* Connection to server (output). */ | 159 | static int connection_out; /* Connection to server (output). */ |
166 | static int need_rekeying; /* Set to non-zero if rekeying is requested. */ | 160 | static int need_rekeying; /* Set to non-zero if rekeying is requested. */ |
@@ -523,10 +517,10 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | |||
523 | memset(*readsetp, 0, *nallocp); | 517 | memset(*readsetp, 0, *nallocp); |
524 | memset(*writesetp, 0, *nallocp); | 518 | memset(*writesetp, 0, *nallocp); |
525 | return; | 519 | return; |
526 | } else { | ||
527 | FD_SET(connection_in, *readsetp); | ||
528 | } | 520 | } |
529 | 521 | ||
522 | FD_SET(connection_in, *readsetp); | ||
523 | |||
530 | /* Select server connection if have data to write to the server. */ | 524 | /* Select server connection if have data to write to the server. */ |
531 | if (packet_have_data_to_write()) | 525 | if (packet_have_data_to_write()) |
532 | FD_SET(connection_out, *writesetp); | 526 | FD_SET(connection_out, *writesetp); |
@@ -961,19 +955,11 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
961 | u_int i; | 955 | u_int i; |
962 | u_char ch; | 956 | u_char ch; |
963 | char *s; | 957 | char *s; |
964 | int *escape_pendingp, escape_char; | 958 | struct escape_filter_ctx *efc = c->filter_ctx == NULL ? |
965 | struct escape_filter_ctx *efc; | 959 | NULL : (struct escape_filter_ctx *)c->filter_ctx; |
966 | 960 | ||
967 | if (c == NULL) { | 961 | if (c->filter_ctx == NULL) |
968 | escape_pendingp = &escape_pending1; | 962 | return 0; |
969 | escape_char = escape_char1; | ||
970 | } else { | ||
971 | if (c->filter_ctx == NULL) | ||
972 | return 0; | ||
973 | efc = (struct escape_filter_ctx *)c->filter_ctx; | ||
974 | escape_pendingp = &efc->escape_pending; | ||
975 | escape_char = efc->escape_char; | ||
976 | } | ||
977 | 963 | ||
978 | if (len <= 0) | 964 | if (len <= 0) |
979 | return (0); | 965 | return (0); |
@@ -982,17 +968,17 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
982 | /* Get one character at a time. */ | 968 | /* Get one character at a time. */ |
983 | ch = buf[i]; | 969 | ch = buf[i]; |
984 | 970 | ||
985 | if (*escape_pendingp) { | 971 | if (efc->escape_pending) { |
986 | /* We have previously seen an escape character. */ | 972 | /* We have previously seen an escape character. */ |
987 | /* Clear the flag now. */ | 973 | /* Clear the flag now. */ |
988 | *escape_pendingp = 0; | 974 | efc->escape_pending = 0; |
989 | 975 | ||
990 | /* Process the escaped character. */ | 976 | /* Process the escaped character. */ |
991 | switch (ch) { | 977 | switch (ch) { |
992 | case '.': | 978 | case '.': |
993 | /* Terminate the connection. */ | 979 | /* Terminate the connection. */ |
994 | snprintf(string, sizeof string, "%c.\r\n", | 980 | snprintf(string, sizeof string, "%c.\r\n", |
995 | escape_char); | 981 | efc->escape_char); |
996 | buffer_append(berr, string, strlen(string)); | 982 | buffer_append(berr, string, strlen(string)); |
997 | 983 | ||
998 | if (c && c->ctl_chan != -1) { | 984 | if (c && c->ctl_chan != -1) { |
@@ -1020,14 +1006,14 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1020 | snprintf(string, sizeof string, | 1006 | snprintf(string, sizeof string, |
1021 | "%c%s escape not available to " | 1007 | "%c%s escape not available to " |
1022 | "multiplexed sessions\r\n", | 1008 | "multiplexed sessions\r\n", |
1023 | escape_char, b); | 1009 | efc->escape_char, b); |
1024 | buffer_append(berr, string, | 1010 | buffer_append(berr, string, |
1025 | strlen(string)); | 1011 | strlen(string)); |
1026 | continue; | 1012 | continue; |
1027 | } | 1013 | } |
1028 | /* Suspend the program. Inform the user */ | 1014 | /* Suspend the program. Inform the user */ |
1029 | snprintf(string, sizeof string, | 1015 | snprintf(string, sizeof string, |
1030 | "%c^Z [suspend ssh]\r\n", escape_char); | 1016 | "%c^Z [suspend ssh]\r\n", efc->escape_char); |
1031 | buffer_append(berr, string, strlen(string)); | 1017 | buffer_append(berr, string, strlen(string)); |
1032 | 1018 | ||
1033 | /* Restore terminal modes and suspend. */ | 1019 | /* Restore terminal modes and suspend. */ |
@@ -1038,7 +1024,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1038 | 1024 | ||
1039 | case 'B': | 1025 | case 'B': |
1040 | snprintf(string, sizeof string, | 1026 | snprintf(string, sizeof string, |
1041 | "%cB\r\n", escape_char); | 1027 | "%cB\r\n", efc->escape_char); |
1042 | buffer_append(berr, string, strlen(string)); | 1028 | buffer_append(berr, string, strlen(string)); |
1043 | channel_request_start(c->self, "break", 0); | 1029 | channel_request_start(c->self, "break", 0); |
1044 | packet_put_int(1000); | 1030 | packet_put_int(1000); |
@@ -1061,7 +1047,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1061 | if (!log_is_on_stderr()) { | 1047 | if (!log_is_on_stderr()) { |
1062 | snprintf(string, sizeof string, | 1048 | snprintf(string, sizeof string, |
1063 | "%c%c [Logging to syslog]\r\n", | 1049 | "%c%c [Logging to syslog]\r\n", |
1064 | escape_char, ch); | 1050 | efc->escape_char, ch); |
1065 | buffer_append(berr, string, | 1051 | buffer_append(berr, string, |
1066 | strlen(string)); | 1052 | strlen(string)); |
1067 | continue; | 1053 | continue; |
@@ -1073,7 +1059,8 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1073 | SYSLOG_LEVEL_DEBUG3) | 1059 | SYSLOG_LEVEL_DEBUG3) |
1074 | log_change_level(++options.log_level); | 1060 | log_change_level(++options.log_level); |
1075 | snprintf(string, sizeof string, | 1061 | snprintf(string, sizeof string, |
1076 | "%c%c [LogLevel %s]\r\n", escape_char, ch, | 1062 | "%c%c [LogLevel %s]\r\n", |
1063 | efc->escape_char, ch, | ||
1077 | log_level_name(options.log_level)); | 1064 | log_level_name(options.log_level)); |
1078 | buffer_append(berr, string, strlen(string)); | 1065 | buffer_append(berr, string, strlen(string)); |
1079 | continue; | 1066 | continue; |
@@ -1094,7 +1081,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1094 | channel_stop_listening(); | 1081 | channel_stop_listening(); |
1095 | 1082 | ||
1096 | snprintf(string, sizeof string, | 1083 | snprintf(string, sizeof string, |
1097 | "%c& [backgrounded]\n", escape_char); | 1084 | "%c& [backgrounded]\n", efc->escape_char); |
1098 | buffer_append(berr, string, strlen(string)); | 1085 | buffer_append(berr, string, strlen(string)); |
1099 | 1086 | ||
1100 | /* Fork into background. */ | 1087 | /* Fork into background. */ |
@@ -1112,14 +1099,14 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1112 | /* fake EOF on stdin */ | 1099 | /* fake EOF on stdin */ |
1113 | return -1; | 1100 | return -1; |
1114 | case '?': | 1101 | case '?': |
1115 | print_escape_help(berr, escape_char, | 1102 | print_escape_help(berr, efc->escape_char, |
1116 | (c && c->ctl_chan != -1), | 1103 | (c && c->ctl_chan != -1), |
1117 | log_is_on_stderr()); | 1104 | log_is_on_stderr()); |
1118 | continue; | 1105 | continue; |
1119 | 1106 | ||
1120 | case '#': | 1107 | case '#': |
1121 | snprintf(string, sizeof string, "%c#\r\n", | 1108 | snprintf(string, sizeof string, "%c#\r\n", |
1122 | escape_char); | 1109 | efc->escape_char); |
1123 | buffer_append(berr, string, strlen(string)); | 1110 | buffer_append(berr, string, strlen(string)); |
1124 | s = channel_open_message(); | 1111 | s = channel_open_message(); |
1125 | buffer_append(berr, s, strlen(s)); | 1112 | buffer_append(berr, s, strlen(s)); |
@@ -1133,8 +1120,8 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1133 | continue; | 1120 | continue; |
1134 | 1121 | ||
1135 | default: | 1122 | default: |
1136 | if (ch != escape_char) { | 1123 | if (ch != efc->escape_char) { |
1137 | buffer_put_char(bin, escape_char); | 1124 | buffer_put_char(bin, efc->escape_char); |
1138 | bytes++; | 1125 | bytes++; |
1139 | } | 1126 | } |
1140 | /* Escaped characters fall through here */ | 1127 | /* Escaped characters fall through here */ |
@@ -1145,12 +1132,12 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1145 | * The previous character was not an escape char. | 1132 | * The previous character was not an escape char. |
1146 | * Check if this is an escape. | 1133 | * Check if this is an escape. |
1147 | */ | 1134 | */ |
1148 | if (last_was_cr && ch == escape_char) { | 1135 | if (last_was_cr && ch == efc->escape_char) { |
1149 | /* | 1136 | /* |
1150 | * It is. Set the flag and continue to | 1137 | * It is. Set the flag and continue to |
1151 | * next character. | 1138 | * next character. |
1152 | */ | 1139 | */ |
1153 | *escape_pendingp = 1; | 1140 | efc->escape_pending = 1; |
1154 | continue; | 1141 | continue; |
1155 | } | 1142 | } |
1156 | } | 1143 | } |
@@ -1276,21 +1263,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1276 | start_time = get_current_time(); | 1263 | start_time = get_current_time(); |
1277 | 1264 | ||
1278 | /* Initialize variables. */ | 1265 | /* Initialize variables. */ |
1279 | escape_pending1 = 0; | ||
1280 | last_was_cr = 1; | 1266 | last_was_cr = 1; |
1281 | exit_status = -1; | 1267 | exit_status = -1; |
1282 | stdin_eof = 0; | ||
1283 | buffer_high = 64 * 1024; | ||
1284 | connection_in = packet_get_connection_in(); | 1268 | connection_in = packet_get_connection_in(); |
1285 | connection_out = packet_get_connection_out(); | 1269 | connection_out = packet_get_connection_out(); |
1286 | max_fd = MAXIMUM(connection_in, connection_out); | 1270 | max_fd = MAXIMUM(connection_in, connection_out); |
1287 | 1271 | ||
1288 | quit_pending = 0; | 1272 | quit_pending = 0; |
1289 | escape_char1 = escape_char_arg; | ||
1290 | 1273 | ||
1291 | /* Initialize buffers. */ | 1274 | /* Initialize buffers. */ |
1292 | buffer_init(&stdin_buffer); | ||
1293 | buffer_init(&stdout_buffer); | ||
1294 | buffer_init(&stderr_buffer); | 1275 | buffer_init(&stderr_buffer); |
1295 | 1276 | ||
1296 | client_init_dispatch(); | 1277 | client_init_dispatch(); |
@@ -1451,16 +1432,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1451 | buffer_append(&stderr_buffer, buf, strlen(buf)); | 1432 | buffer_append(&stderr_buffer, buf, strlen(buf)); |
1452 | } | 1433 | } |
1453 | 1434 | ||
1454 | /* Output any buffered data for stdout. */ | ||
1455 | if (buffer_len(&stdout_buffer) > 0) { | ||
1456 | len = atomicio(vwrite, fileno(stdout), | ||
1457 | buffer_ptr(&stdout_buffer), buffer_len(&stdout_buffer)); | ||
1458 | if (len < 0 || (u_int)len != buffer_len(&stdout_buffer)) | ||
1459 | error("Write failed flushing stdout buffer."); | ||
1460 | else | ||
1461 | buffer_consume(&stdout_buffer, len); | ||
1462 | } | ||
1463 | |||
1464 | /* Output any buffered data for stderr. */ | 1435 | /* Output any buffered data for stderr. */ |
1465 | if (buffer_len(&stderr_buffer) > 0) { | 1436 | if (buffer_len(&stderr_buffer) > 0) { |
1466 | len = atomicio(vwrite, fileno(stderr), | 1437 | len = atomicio(vwrite, fileno(stderr), |
@@ -1473,8 +1444,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1473 | 1444 | ||
1474 | /* Clear and free any buffers. */ | 1445 | /* Clear and free any buffers. */ |
1475 | explicit_bzero(buf, sizeof(buf)); | 1446 | explicit_bzero(buf, sizeof(buf)); |
1476 | buffer_free(&stdin_buffer); | ||
1477 | buffer_free(&stdout_buffer); | ||
1478 | buffer_free(&stderr_buffer); | 1447 | buffer_free(&stderr_buffer); |
1479 | 1448 | ||
1480 | /* Report bytes transferred, and transfer rates. */ | 1449 | /* Report bytes transferred, and transfer rates. */ |
@@ -1792,9 +1761,7 @@ struct hostkeys_update_ctx { | |||
1792 | */ | 1761 | */ |
1793 | struct sshkey **keys; | 1762 | struct sshkey **keys; |
1794 | int *keys_seen; | 1763 | int *keys_seen; |
1795 | size_t nkeys; | 1764 | size_t nkeys, nnew; |
1796 | |||
1797 | size_t nnew; | ||
1798 | 1765 | ||
1799 | /* | 1766 | /* |
1800 | * Keys that are in known_hosts, but were not present in the update | 1767 | * Keys that are in known_hosts, but were not present in the update |