diff options
author | Colin Watson <cjwatson@debian.org> | 2009-12-29 21:42:53 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2009-12-29 21:42:53 +0000 |
commit | 87552344215a38d3a2b0d4d63dc151e05978bbe1 (patch) | |
tree | 9f4b96055e6ccaa915e8d59d9f2805e9e119371d /packet.c | |
parent | a25ec0b132c44c9e341e08464ff830de06b81126 (diff) | |
parent | ef94e5613d37bcbf880f21ee6094e4b1c7683a4c (diff) |
import openssh-5.1p1-gsskex-cjwatson-20080722.patch
Diffstat (limited to 'packet.c')
-rw-r--r-- | packet.c | 139 |
1 files changed, 119 insertions, 20 deletions
@@ -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 |
@@ -136,12 +136,18 @@ static int server_side = 0; | |||
136 | /* Set to true if we are authenticated. */ | 136 | /* Set to true if we are authenticated. */ |
137 | static int after_authentication = 0; | 137 | static int after_authentication = 0; |
138 | 138 | ||
139 | int keep_alive_timeouts = 0; | ||
140 | |||
141 | /* Set to the maximum time that we will wait to send or receive a packet */ | ||
142 | static int packet_timeout_ms = -1; | ||
143 | |||
139 | /* Session key information for Encryption and MAC */ | 144 | /* Session key information for Encryption and MAC */ |
140 | Newkeys *newkeys[MODE_MAX]; | 145 | Newkeys *newkeys[MODE_MAX]; |
141 | static struct packet_state { | 146 | static struct packet_state { |
142 | u_int32_t seqnr; | 147 | u_int32_t seqnr; |
143 | u_int32_t packets; | 148 | u_int32_t packets; |
144 | u_int64_t blocks; | 149 | u_int64_t blocks; |
150 | u_int64_t bytes; | ||
145 | } p_read, p_send; | 151 | } p_read, p_send; |
146 | 152 | ||
147 | static u_int64_t max_blocks_in, max_blocks_out; | 153 | static u_int64_t max_blocks_in, max_blocks_out; |
@@ -186,7 +192,21 @@ packet_set_connection(int fd_in, int fd_out) | |||
186 | buffer_init(&outgoing_packet); | 192 | buffer_init(&outgoing_packet); |
187 | buffer_init(&incoming_packet); | 193 | buffer_init(&incoming_packet); |
188 | TAILQ_INIT(&outgoing); | 194 | TAILQ_INIT(&outgoing); |
195 | p_send.packets = p_read.packets = 0; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | void | ||
200 | packet_set_timeout(int timeout, int count) | ||
201 | { | ||
202 | if (timeout == 0 || count == 0) { | ||
203 | packet_timeout_ms = -1; | ||
204 | return; | ||
189 | } | 205 | } |
206 | if ((INT_MAX / 1000) / count < timeout) | ||
207 | packet_timeout_ms = INT_MAX; | ||
208 | else | ||
209 | packet_timeout_ms = timeout * count * 1000; | ||
190 | } | 210 | } |
191 | 211 | ||
192 | /* 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. */ |
@@ -293,18 +313,25 @@ packet_get_ssh1_cipher(void) | |||
293 | } | 313 | } |
294 | 314 | ||
295 | void | 315 | void |
296 | packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets) | 316 | packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets, |
317 | u_int64_t *bytes) | ||
297 | { | 318 | { |
298 | struct packet_state *state; | 319 | struct packet_state *state; |
299 | 320 | ||
300 | state = (mode == MODE_IN) ? &p_read : &p_send; | 321 | state = (mode == MODE_IN) ? &p_read : &p_send; |
301 | *seqnr = state->seqnr; | 322 | if (seqnr) |
302 | *blocks = state->blocks; | 323 | *seqnr = state->seqnr; |
303 | *packets = state->packets; | 324 | if (blocks) |
325 | *blocks = state->blocks; | ||
326 | if (packets) | ||
327 | *packets = state->packets; | ||
328 | if (bytes) | ||
329 | *bytes = state->bytes; | ||
304 | } | 330 | } |
305 | 331 | ||
306 | void | 332 | void |
307 | packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets) | 333 | packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets, |
334 | u_int64_t bytes) | ||
308 | { | 335 | { |
309 | struct packet_state *state; | 336 | struct packet_state *state; |
310 | 337 | ||
@@ -312,6 +339,7 @@ packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets) | |||
312 | state->seqnr = seqnr; | 339 | state->seqnr = seqnr; |
313 | state->blocks = blocks; | 340 | state->blocks = blocks; |
314 | state->packets = packets; | 341 | state->packets = packets; |
342 | state->bytes = bytes; | ||
315 | } | 343 | } |
316 | 344 | ||
317 | /* returns 1 if connection is via ipv4 */ | 345 | /* returns 1 if connection is via ipv4 */ |
@@ -590,7 +618,8 @@ packet_send1(void) | |||
590 | fprintf(stderr, "encrypted: "); | 618 | fprintf(stderr, "encrypted: "); |
591 | buffer_dump(&output); | 619 | buffer_dump(&output); |
592 | #endif | 620 | #endif |
593 | 621 | p_send.packets++; | |
622 | p_send.bytes += len + buffer_len(&outgoing_packet); | ||
594 | buffer_clear(&outgoing_packet); | 623 | buffer_clear(&outgoing_packet); |
595 | 624 | ||
596 | /* | 625 | /* |
@@ -816,6 +845,7 @@ packet_send2_wrapped(void) | |||
816 | if (!(datafellows & SSH_BUG_NOREKEY)) | 845 | if (!(datafellows & SSH_BUG_NOREKEY)) |
817 | fatal("XXX too many packets with same key"); | 846 | fatal("XXX too many packets with same key"); |
818 | p_send.blocks += (packet_length + 4) / block_size; | 847 | p_send.blocks += (packet_length + 4) / block_size; |
848 | p_send.bytes += packet_length + 4; | ||
819 | buffer_clear(&outgoing_packet); | 849 | buffer_clear(&outgoing_packet); |
820 | 850 | ||
821 | if (type == SSH2_MSG_NEWKEYS) | 851 | if (type == SSH2_MSG_NEWKEYS) |
@@ -889,9 +919,11 @@ packet_send(void) | |||
889 | int | 919 | int |
890 | packet_read_seqnr(u_int32_t *seqnr_p) | 920 | packet_read_seqnr(u_int32_t *seqnr_p) |
891 | { | 921 | { |
892 | int type, len; | 922 | int type, len, ret, ms_remain; |
893 | fd_set *setp; | 923 | fd_set *setp; |
894 | char buf[8192]; | 924 | char buf[8192]; |
925 | struct timeval timeout, start, *timeoutp = NULL; | ||
926 | |||
895 | DBG(debug("packet_read()")); | 927 | DBG(debug("packet_read()")); |
896 | 928 | ||
897 | setp = (fd_set *)xcalloc(howmany(connection_in+1, NFDBITS), | 929 | setp = (fd_set *)xcalloc(howmany(connection_in+1, NFDBITS), |
@@ -923,11 +955,35 @@ packet_read_seqnr(u_int32_t *seqnr_p) | |||
923 | sizeof(fd_mask)); | 955 | sizeof(fd_mask)); |
924 | FD_SET(connection_in, setp); | 956 | FD_SET(connection_in, setp); |
925 | 957 | ||
958 | if (packet_timeout_ms > 0) { | ||
959 | ms_remain = packet_timeout_ms; | ||
960 | timeoutp = &timeout; | ||
961 | } | ||
926 | /* Wait for some data to arrive. */ | 962 | /* Wait for some data to arrive. */ |
927 | while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 && | 963 | for (;;) { |
928 | (errno == EAGAIN || errno == EINTR)) | 964 | if (packet_timeout_ms != -1) { |
929 | ; | 965 | ms_to_timeval(&timeout, ms_remain); |
930 | 966 | gettimeofday(&start, NULL); | |
967 | } | ||
968 | if ((ret = select(connection_in + 1, setp, NULL, | ||
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 | } | ||
931 | /* Read data from the socket. */ | 987 | /* Read data from the socket. */ |
932 | len = read(connection_in, buf, sizeof(buf)); | 988 | len = read(connection_in, buf, sizeof(buf)); |
933 | if (len == 0) { | 989 | if (len == 0) { |
@@ -1052,6 +1108,8 @@ packet_read_poll1(void) | |||
1052 | buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), | 1108 | buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), |
1053 | buffer_len(&compression_buffer)); | 1109 | buffer_len(&compression_buffer)); |
1054 | } | 1110 | } |
1111 | p_read.packets++; | ||
1112 | p_read.bytes += padded_len + 4; | ||
1055 | type = buffer_get_char(&incoming_packet); | 1113 | type = buffer_get_char(&incoming_packet); |
1056 | if (type < SSH_MSG_MIN || type > SSH_MSG_MAX) | 1114 | if (type < SSH_MSG_MIN || type > SSH_MSG_MAX) |
1057 | packet_disconnect("Invalid ssh1 packet type: %d", type); | 1115 | packet_disconnect("Invalid ssh1 packet type: %d", type); |
@@ -1140,6 +1198,7 @@ packet_read_poll2(u_int32_t *seqnr_p) | |||
1140 | if (!(datafellows & SSH_BUG_NOREKEY)) | 1198 | if (!(datafellows & SSH_BUG_NOREKEY)) |
1141 | fatal("XXX too many packets with same key"); | 1199 | fatal("XXX too many packets with same key"); |
1142 | p_read.blocks += (packet_length + 4) / block_size; | 1200 | p_read.blocks += (packet_length + 4) / block_size; |
1201 | p_read.bytes += packet_length + 4; | ||
1143 | 1202 | ||
1144 | /* get padlen */ | 1203 | /* get padlen */ |
1145 | cp = buffer_ptr(&incoming_packet); | 1204 | cp = buffer_ptr(&incoming_packet); |
@@ -1192,10 +1251,13 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p) | |||
1192 | for (;;) { | 1251 | for (;;) { |
1193 | if (compat20) { | 1252 | if (compat20) { |
1194 | type = packet_read_poll2(seqnr_p); | 1253 | type = packet_read_poll2(seqnr_p); |
1195 | if (type) | 1254 | if (type) { |
1255 | keep_alive_timeouts = 0; | ||
1196 | DBG(debug("received packet type %d", type)); | 1256 | DBG(debug("received packet type %d", type)); |
1257 | } | ||
1197 | switch (type) { | 1258 | switch (type) { |
1198 | case SSH2_MSG_IGNORE: | 1259 | case SSH2_MSG_IGNORE: |
1260 | debug3("Received SSH2_MSG_IGNORE"); | ||
1199 | break; | 1261 | break; |
1200 | case SSH2_MSG_DEBUG: | 1262 | case SSH2_MSG_DEBUG: |
1201 | packet_get_char(); | 1263 | packet_get_char(); |
@@ -1328,6 +1390,12 @@ packet_get_string(u_int *length_ptr) | |||
1328 | return buffer_get_string(&incoming_packet, length_ptr); | 1390 | return buffer_get_string(&incoming_packet, length_ptr); |
1329 | } | 1391 | } |
1330 | 1392 | ||
1393 | void * | ||
1394 | packet_get_string_ptr(u_int *length_ptr) | ||
1395 | { | ||
1396 | return buffer_get_string_ptr(&incoming_packet, length_ptr); | ||
1397 | } | ||
1398 | |||
1331 | /* | 1399 | /* |
1332 | * 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 |
1333 | * 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 |
@@ -1422,16 +1490,19 @@ packet_write_poll(void) | |||
1422 | 1490 | ||
1423 | if (len > 0) { | 1491 | if (len > 0) { |
1424 | len = write(connection_out, buffer_ptr(&output), len); | 1492 | len = write(connection_out, buffer_ptr(&output), len); |
1425 | if (len <= 0) { | 1493 | if (len == -1) { |
1426 | if (errno == EAGAIN) | 1494 | if (errno == EINTR || errno == EAGAIN || |
1495 | errno == EWOULDBLOCK) | ||
1427 | return; | 1496 | return; |
1428 | else | 1497 | fatal("Write failed: %.100s", strerror(errno)); |
1429 | fatal("Write failed: %.100s", strerror(errno)); | ||
1430 | } | 1498 | } |
1499 | if (len == 0) | ||
1500 | fatal("Write connection closed"); | ||
1431 | buffer_consume(&output, len); | 1501 | buffer_consume(&output, len); |
1432 | } | 1502 | } |
1433 | } | 1503 | } |
1434 | 1504 | ||
1505 | |||
1435 | /* | 1506 | /* |
1436 | * 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 |
1437 | * written. | 1508 | * written. |
@@ -1441,6 +1512,8 @@ void | |||
1441 | packet_write_wait(void) | 1512 | packet_write_wait(void) |
1442 | { | 1513 | { |
1443 | fd_set *setp; | 1514 | fd_set *setp; |
1515 | int ret, ms_remain; | ||
1516 | struct timeval start, timeout, *timeoutp = NULL; | ||
1444 | 1517 | ||
1445 | setp = (fd_set *)xcalloc(howmany(connection_out + 1, NFDBITS), | 1518 | setp = (fd_set *)xcalloc(howmany(connection_out + 1, NFDBITS), |
1446 | sizeof(fd_mask)); | 1519 | sizeof(fd_mask)); |
@@ -1449,9 +1522,35 @@ packet_write_wait(void) | |||
1449 | memset(setp, 0, howmany(connection_out + 1, NFDBITS) * | 1522 | memset(setp, 0, howmany(connection_out + 1, NFDBITS) * |
1450 | sizeof(fd_mask)); | 1523 | sizeof(fd_mask)); |
1451 | FD_SET(connection_out, setp); | 1524 | FD_SET(connection_out, setp); |
1452 | while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 && | 1525 | |
1453 | (errno == EAGAIN || errno == EINTR)) | 1526 | if (packet_timeout_ms > 0) { |
1454 | ; | 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 | } | ||
1455 | packet_write_poll(); | 1554 | packet_write_poll(); |
1456 | } | 1555 | } |
1457 | xfree(setp); | 1556 | xfree(setp); |