summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clientloop.c83
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. */
154volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ 154volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
155static int escape_char1; /* Escape character. (proto1 only) */
156static int escape_pending1; /* Last character was an escape (proto1 only) */
157static int last_was_cr; /* Last character was a newline. */ 155static int last_was_cr; /* Last character was a newline. */
158static int exit_status; /* Used to store the command exit status. */ 156static int exit_status; /* Used to store the command exit status. */
159static int stdin_eof; /* EOF has been encountered on stderr. */ 157static Buffer stderr_buffer; /* Used for final exit message. */
160static Buffer stdin_buffer; /* Buffer for stdin data. */
161static Buffer stdout_buffer; /* Buffer for stdout data. */
162static Buffer stderr_buffer; /* Buffer for stderr data. */
163static u_int buffer_high; /* Soft max buffer size. */
164static int connection_in; /* Connection to server (input). */ 158static int connection_in; /* Connection to server (input). */
165static int connection_out; /* Connection to server (output). */ 159static int connection_out; /* Connection to server (output). */
166static int need_rekeying; /* Set to non-zero if rekeying is requested. */ 160static 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