summaryrefslogtreecommitdiff
path: root/packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'packet.c')
-rw-r--r--packet.c155
1 files changed, 120 insertions, 35 deletions
diff --git a/packet.c b/packet.c
index 753abebd8..8abd43eb4 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.148 2007/06/07 19:37:34 pvalchev Exp $ */ 1/* $OpenBSD: packet.c,v 1.157 2008/07/10 18:08:11 markus 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
@@ -93,8 +93,6 @@
93static int connection_in = -1; 93static int connection_in = -1;
94static int connection_out = -1; 94static int connection_out = -1;
95 95
96static int setup_timeout = -1;
97
98/* Protocol flags for the remote side. */ 96/* Protocol flags for the remote side. */
99static u_int remote_protocol_flags = 0; 97static u_int remote_protocol_flags = 0;
100 98
@@ -138,12 +136,18 @@ static int server_side = 0;
138/* Set to true if we are authenticated. */ 136/* Set to true if we are authenticated. */
139static int after_authentication = 0; 137static int after_authentication = 0;
140 138
139int keep_alive_timeouts = 0;
140
141/* Set to the maximum time that we will wait to send or receive a packet */
142static int packet_timeout_ms = -1;
143
141/* Session key information for Encryption and MAC */ 144/* Session key information for Encryption and MAC */
142Newkeys *newkeys[MODE_MAX]; 145Newkeys *newkeys[MODE_MAX];
143static struct packet_state { 146static struct packet_state {
144 u_int32_t seqnr; 147 u_int32_t seqnr;
145 u_int32_t packets; 148 u_int32_t packets;
146 u_int64_t blocks; 149 u_int64_t blocks;
150 u_int64_t bytes;
147} p_read, p_send; 151} p_read, p_send;
148 152
149static u_int64_t max_blocks_in, max_blocks_out; 153static u_int64_t max_blocks_in, max_blocks_out;
@@ -168,7 +172,7 @@ TAILQ_HEAD(, packet) outgoing;
168 * packet_set_encryption_key is called. 172 * packet_set_encryption_key is called.
169 */ 173 */
170void 174void
171packet_set_connection(int fd_in, int fd_out, int new_setup_timeout) 175packet_set_connection(int fd_in, int fd_out)
172{ 176{
173 Cipher *none = cipher_by_name("none"); 177 Cipher *none = cipher_by_name("none");
174 178
@@ -176,7 +180,6 @@ packet_set_connection(int fd_in, int fd_out, int new_setup_timeout)
176 fatal("packet_set_connection: cannot load cipher 'none'"); 180 fatal("packet_set_connection: cannot load cipher 'none'");
177 connection_in = fd_in; 181 connection_in = fd_in;
178 connection_out = fd_out; 182 connection_out = fd_out;
179 setup_timeout = new_setup_timeout;
180 cipher_init(&send_context, none, (const u_char *)"", 183 cipher_init(&send_context, none, (const u_char *)"",
181 0, NULL, 0, CIPHER_ENCRYPT); 184 0, NULL, 0, CIPHER_ENCRYPT);
182 cipher_init(&receive_context, none, (const u_char *)"", 185 cipher_init(&receive_context, none, (const u_char *)"",
@@ -189,9 +192,23 @@ packet_set_connection(int fd_in, int fd_out, int new_setup_timeout)
189 buffer_init(&outgoing_packet); 192 buffer_init(&outgoing_packet);
190 buffer_init(&incoming_packet); 193 buffer_init(&incoming_packet);
191 TAILQ_INIT(&outgoing); 194 TAILQ_INIT(&outgoing);
195 p_send.packets = p_read.packets = 0;
192 } 196 }
193} 197}
194 198
199void
200packet_set_timeout(int timeout, int count)
201{
202 if (timeout == 0 || count == 0) {
203 packet_timeout_ms = -1;
204 return;
205 }
206 if ((INT_MAX / 1000) / count < timeout)
207 packet_timeout_ms = INT_MAX;
208 else
209 packet_timeout_ms = timeout * count * 1000;
210}
211
195/* Returns 1 if remote host is connected via socket, 0 if not. */ 212/* Returns 1 if remote host is connected via socket, 0 if not. */
196 213
197int 214int
@@ -296,18 +313,25 @@ packet_get_ssh1_cipher(void)
296} 313}
297 314
298void 315void
299packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets) 316packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets,
317 u_int64_t *bytes)
300{ 318{
301 struct packet_state *state; 319 struct packet_state *state;
302 320
303 state = (mode == MODE_IN) ? &p_read : &p_send; 321 state = (mode == MODE_IN) ? &p_read : &p_send;
304 *seqnr = state->seqnr; 322 if (seqnr)
305 *blocks = state->blocks; 323 *seqnr = state->seqnr;
306 *packets = state->packets; 324 if (blocks)
325 *blocks = state->blocks;
326 if (packets)
327 *packets = state->packets;
328 if (bytes)
329 *bytes = state->bytes;
307} 330}
308 331
309void 332void
310packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets) 333packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets,
334 u_int64_t bytes)
311{ 335{
312 struct packet_state *state; 336 struct packet_state *state;
313 337
@@ -315,6 +339,7 @@ packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets)
315 state->seqnr = seqnr; 339 state->seqnr = seqnr;
316 state->blocks = blocks; 340 state->blocks = blocks;
317 state->packets = packets; 341 state->packets = packets;
342 state->bytes = bytes;
318} 343}
319 344
320/* returns 1 if connection is via ipv4 */ 345/* returns 1 if connection is via ipv4 */
@@ -593,7 +618,8 @@ packet_send1(void)
593 fprintf(stderr, "encrypted: "); 618 fprintf(stderr, "encrypted: ");
594 buffer_dump(&output); 619 buffer_dump(&output);
595#endif 620#endif
596 621 p_send.packets++;
622 p_send.bytes += len + buffer_len(&outgoing_packet);
597 buffer_clear(&outgoing_packet); 623 buffer_clear(&outgoing_packet);
598 624
599 /* 625 /*
@@ -819,6 +845,7 @@ packet_send2_wrapped(void)
819 if (!(datafellows & SSH_BUG_NOREKEY)) 845 if (!(datafellows & SSH_BUG_NOREKEY))
820 fatal("XXX too many packets with same key"); 846 fatal("XXX too many packets with same key");
821 p_send.blocks += (packet_length + 4) / block_size; 847 p_send.blocks += (packet_length + 4) / block_size;
848 p_send.bytes += packet_length + 4;
822 buffer_clear(&outgoing_packet); 849 buffer_clear(&outgoing_packet);
823 850
824 if (type == SSH2_MSG_NEWKEYS) 851 if (type == SSH2_MSG_NEWKEYS)
@@ -892,10 +919,11 @@ packet_send(void)
892int 919int
893packet_read_seqnr(u_int32_t *seqnr_p) 920packet_read_seqnr(u_int32_t *seqnr_p)
894{ 921{
895 int type, len; 922 int type, len, ret, ms_remain;
896 fd_set *setp; 923 fd_set *setp;
897 char buf[8192]; 924 char buf[8192];
898 struct timeval tv, *tvp; 925 struct timeval timeout, start, *timeoutp = NULL;
926
899 DBG(debug("packet_read()")); 927 DBG(debug("packet_read()"));
900 928
901 setp = (fd_set *)xcalloc(howmany(connection_in+1, NFDBITS), 929 setp = (fd_set *)xcalloc(howmany(connection_in+1, NFDBITS),
@@ -927,21 +955,35 @@ packet_read_seqnr(u_int32_t *seqnr_p)
927 sizeof(fd_mask)); 955 sizeof(fd_mask));
928 FD_SET(connection_in, setp); 956 FD_SET(connection_in, setp);
929 957
930 if (setup_timeout > 0) { 958 if (packet_timeout_ms > 0) {
931 tvp = &tv; 959 ms_remain = packet_timeout_ms;
932 tv.tv_sec = setup_timeout; 960 timeoutp = &timeout;
933 tv.tv_usec = 0; 961 }
934 } else
935 tvp = NULL;
936
937 /* Wait for some data to arrive. */ 962 /* Wait for some data to arrive. */
938 while (select(connection_in + 1, setp, NULL, NULL, tvp) == -1 && 963 for (;;) {
939 (errno == EAGAIN || errno == EINTR)) 964 if (packet_timeout_ms != -1) {
940 ; 965 ms_to_timeval(&timeout, ms_remain);
941 966 gettimeofday(&start, NULL);
942 if (!FD_ISSET(connection_in, setp)) 967 }
943 fatal("packet_read: Setup timeout expired, giving up"); 968 if ((ret = select(connection_in + 1, setp, NULL,
944 969 NULL, timeoutp)) >= 0)
970 break;
971 if (errno != EAGAIN && errno != EINTR &&
972 errno != EWOULDBLOCK)
973 break;
974 if (packet_timeout_ms == -1)
975 continue;
976 ms_subtract_diff(&start, &ms_remain);
977 if (ms_remain <= 0) {
978 ret = 0;
979 break;
980 }
981 }
982 if (ret == 0) {
983 logit("Connection to %.200s timed out while "
984 "waiting to read", get_remote_ipaddr());
985 cleanup_exit(255);
986 }
945 /* Read data from the socket. */ 987 /* Read data from the socket. */
946 len = read(connection_in, buf, sizeof(buf)); 988 len = read(connection_in, buf, sizeof(buf));
947 if (len == 0) { 989 if (len == 0) {
@@ -1066,6 +1108,8 @@ packet_read_poll1(void)
1066 buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 1108 buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
1067 buffer_len(&compression_buffer)); 1109 buffer_len(&compression_buffer));
1068 } 1110 }
1111 p_read.packets++;
1112 p_read.bytes += padded_len + 4;
1069 type = buffer_get_char(&incoming_packet); 1113 type = buffer_get_char(&incoming_packet);
1070 if (type < SSH_MSG_MIN || type > SSH_MSG_MAX) 1114 if (type < SSH_MSG_MIN || type > SSH_MSG_MAX)
1071 packet_disconnect("Invalid ssh1 packet type: %d", type); 1115 packet_disconnect("Invalid ssh1 packet type: %d", type);
@@ -1154,6 +1198,7 @@ packet_read_poll2(u_int32_t *seqnr_p)
1154 if (!(datafellows & SSH_BUG_NOREKEY)) 1198 if (!(datafellows & SSH_BUG_NOREKEY))
1155 fatal("XXX too many packets with same key"); 1199 fatal("XXX too many packets with same key");
1156 p_read.blocks += (packet_length + 4) / block_size; 1200 p_read.blocks += (packet_length + 4) / block_size;
1201 p_read.bytes += packet_length + 4;
1157 1202
1158 /* get padlen */ 1203 /* get padlen */
1159 cp = buffer_ptr(&incoming_packet); 1204 cp = buffer_ptr(&incoming_packet);
@@ -1206,10 +1251,13 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p)
1206 for (;;) { 1251 for (;;) {
1207 if (compat20) { 1252 if (compat20) {
1208 type = packet_read_poll2(seqnr_p); 1253 type = packet_read_poll2(seqnr_p);
1209 if (type) 1254 if (type) {
1255 keep_alive_timeouts = 0;
1210 DBG(debug("received packet type %d", type)); 1256 DBG(debug("received packet type %d", type));
1257 }
1211 switch (type) { 1258 switch (type) {
1212 case SSH2_MSG_IGNORE: 1259 case SSH2_MSG_IGNORE:
1260 debug3("Received SSH2_MSG_IGNORE");
1213 break; 1261 break;
1214 case SSH2_MSG_DEBUG: 1262 case SSH2_MSG_DEBUG:
1215 packet_get_char(); 1263 packet_get_char();
@@ -1342,6 +1390,12 @@ packet_get_string(u_int *length_ptr)
1342 return buffer_get_string(&incoming_packet, length_ptr); 1390 return buffer_get_string(&incoming_packet, length_ptr);
1343} 1391}
1344 1392
1393void *
1394packet_get_string_ptr(u_int *length_ptr)
1395{
1396 return buffer_get_string_ptr(&incoming_packet, length_ptr);
1397}
1398
1345/* 1399/*
1346 * Sends a diagnostic message from the server to the client. This message 1400 * Sends a diagnostic message from the server to the client. This message
1347 * can be sent at any time (but not while constructing another message). The 1401 * can be sent at any time (but not while constructing another message). The
@@ -1436,16 +1490,19 @@ packet_write_poll(void)
1436 1490
1437 if (len > 0) { 1491 if (len > 0) {
1438 len = write(connection_out, buffer_ptr(&output), len); 1492 len = write(connection_out, buffer_ptr(&output), len);
1439 if (len <= 0) { 1493 if (len == -1) {
1440 if (errno == EAGAIN) 1494 if (errno == EINTR || errno == EAGAIN ||
1495 errno == EWOULDBLOCK)
1441 return; 1496 return;
1442 else 1497 fatal("Write failed: %.100s", strerror(errno));
1443 fatal("Write failed: %.100s", strerror(errno));
1444 } 1498 }
1499 if (len == 0)
1500 fatal("Write connection closed");
1445 buffer_consume(&output, len); 1501 buffer_consume(&output, len);
1446 } 1502 }
1447} 1503}
1448 1504
1505
1449/* 1506/*
1450 * Calls packet_write_poll repeatedly until all pending output data has been 1507 * Calls packet_write_poll repeatedly until all pending output data has been
1451 * written. 1508 * written.
@@ -1455,6 +1512,8 @@ void
1455packet_write_wait(void) 1512packet_write_wait(void)
1456{ 1513{
1457 fd_set *setp; 1514 fd_set *setp;
1515 int ret, ms_remain;
1516 struct timeval start, timeout, *timeoutp = NULL;
1458 1517
1459 setp = (fd_set *)xcalloc(howmany(connection_out + 1, NFDBITS), 1518 setp = (fd_set *)xcalloc(howmany(connection_out + 1, NFDBITS),
1460 sizeof(fd_mask)); 1519 sizeof(fd_mask));
@@ -1463,9 +1522,35 @@ packet_write_wait(void)
1463 memset(setp, 0, howmany(connection_out + 1, NFDBITS) * 1522 memset(setp, 0, howmany(connection_out + 1, NFDBITS) *
1464 sizeof(fd_mask)); 1523 sizeof(fd_mask));
1465 FD_SET(connection_out, setp); 1524 FD_SET(connection_out, setp);
1466 while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 && 1525
1467 (errno == EAGAIN || errno == EINTR)) 1526 if (packet_timeout_ms > 0) {
1468 ; 1527 ms_remain = packet_timeout_ms;
1528 timeoutp = &timeout;
1529 }
1530 for (;;) {
1531 if (packet_timeout_ms != -1) {
1532 ms_to_timeval(&timeout, ms_remain);
1533 gettimeofday(&start, NULL);
1534 }
1535 if ((ret = select(connection_out + 1, NULL, setp,
1536 NULL, timeoutp)) >= 0)
1537 break;
1538 if (errno != EAGAIN && errno != EINTR &&
1539 errno != EWOULDBLOCK)
1540 break;
1541 if (packet_timeout_ms == -1)
1542 continue;
1543 ms_subtract_diff(&start, &ms_remain);
1544 if (ms_remain <= 0) {
1545 ret = 0;
1546 break;
1547 }
1548 }
1549 if (ret == 0) {
1550 logit("Connection to %.200s timed out while "
1551 "waiting to write", get_remote_ipaddr());
1552 cleanup_exit(255);
1553 }
1469 packet_write_poll(); 1554 packet_write_poll();
1470 } 1555 }
1471 xfree(setp); 1556 xfree(setp);