diff options
author | Colin Watson <cjwatson@debian.org> | 2013-09-14 23:42:11 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2013-09-14 23:42:11 +0100 |
commit | 327155e6824b3ee13837bdde04e4eb47e147ff46 (patch) | |
tree | 8f8743122403c7a2e6ed919156711fb1520c657f /packet.c | |
parent | 0334ce32304e9ba2a10ee5ca49ca6e8ff3ba6cf4 (diff) | |
parent | 74e339b8f8936bc0d985e053a076d0c9b5e9ea51 (diff) |
* New upstream release (http://www.openssh.com/txt/release-6.3).
- sftp(1): add support for resuming partial downloads using the "reget"
command and on the sftp commandline or on the "get" commandline using
the "-a" (append) option (closes: #158590).
- ssh(1): add an "IgnoreUnknown" configuration option to selectively
suppress errors arising from unknown configuration directives (closes:
#436052).
- sftp(1): update progressmeter when data is acknowledged, not when it's
sent (partially addresses #708372).
- ssh(1): do not fatally exit when attempting to cleanup multiplexing-
created channels that are incompletely opened (closes: #651357).
Diffstat (limited to 'packet.c')
-rw-r--r-- | packet.c | 74 |
1 files changed, 51 insertions, 23 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.c,v 1.182 2013/04/11 02:27:50 djm Exp $ */ | 1 | /* $OpenBSD: packet.c,v 1.188 2013/07/12 00:19:58 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 |
@@ -58,6 +58,7 @@ | |||
58 | #include <string.h> | 58 | #include <string.h> |
59 | #include <unistd.h> | 59 | #include <unistd.h> |
60 | #include <signal.h> | 60 | #include <signal.h> |
61 | #include <time.h> | ||
61 | 62 | ||
62 | #include "xmalloc.h" | 63 | #include "xmalloc.h" |
63 | #include "buffer.h" | 64 | #include "buffer.h" |
@@ -165,9 +166,14 @@ struct session_state { | |||
165 | Newkeys *newkeys[MODE_MAX]; | 166 | Newkeys *newkeys[MODE_MAX]; |
166 | struct packet_state p_read, p_send; | 167 | struct packet_state p_read, p_send; |
167 | 168 | ||
169 | /* Volume-based rekeying */ | ||
168 | u_int64_t max_blocks_in, max_blocks_out; | 170 | u_int64_t max_blocks_in, max_blocks_out; |
169 | u_int32_t rekey_limit; | 171 | u_int32_t rekey_limit; |
170 | 172 | ||
173 | /* Time-based rekeying */ | ||
174 | time_t rekey_interval; /* how often in seconds */ | ||
175 | time_t rekey_time; /* time of last rekeying */ | ||
176 | |||
171 | /* Session key for protocol v1 */ | 177 | /* Session key for protocol v1 */ |
172 | u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; | 178 | u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; |
173 | u_int ssh1_keylen; | 179 | u_int ssh1_keylen; |
@@ -215,7 +221,7 @@ alloc_session_state(void) | |||
215 | void | 221 | void |
216 | packet_set_connection(int fd_in, int fd_out) | 222 | packet_set_connection(int fd_in, int fd_out) |
217 | { | 223 | { |
218 | Cipher *none = cipher_by_name("none"); | 224 | const Cipher *none = cipher_by_name("none"); |
219 | 225 | ||
220 | if (none == NULL) | 226 | if (none == NULL) |
221 | fatal("packet_set_connection: cannot load cipher 'none'"); | 227 | fatal("packet_set_connection: cannot load cipher 'none'"); |
@@ -545,7 +551,7 @@ packet_start_compression(int level) | |||
545 | void | 551 | void |
546 | packet_set_encryption_key(const u_char *key, u_int keylen, int number) | 552 | packet_set_encryption_key(const u_char *key, u_int keylen, int number) |
547 | { | 553 | { |
548 | Cipher *cipher = cipher_by_number(number); | 554 | const Cipher *cipher = cipher_by_number(number); |
549 | 555 | ||
550 | if (cipher == NULL) | 556 | if (cipher == NULL) |
551 | fatal("packet_set_encryption_key: unknown cipher number %d", number); | 557 | fatal("packet_set_encryption_key: unknown cipher number %d", number); |
@@ -760,13 +766,13 @@ set_newkeys(int mode) | |||
760 | memset(enc->iv, 0, enc->iv_len); | 766 | memset(enc->iv, 0, enc->iv_len); |
761 | memset(enc->key, 0, enc->key_len); | 767 | memset(enc->key, 0, enc->key_len); |
762 | memset(mac->key, 0, mac->key_len); | 768 | memset(mac->key, 0, mac->key_len); |
763 | xfree(enc->name); | 769 | free(enc->name); |
764 | xfree(enc->iv); | 770 | free(enc->iv); |
765 | xfree(enc->key); | 771 | free(enc->key); |
766 | xfree(mac->name); | 772 | free(mac->name); |
767 | xfree(mac->key); | 773 | free(mac->key); |
768 | xfree(comp->name); | 774 | free(comp->name); |
769 | xfree(active_state->newkeys[mode]); | 775 | free(active_state->newkeys[mode]); |
770 | } | 776 | } |
771 | active_state->newkeys[mode] = kex_get_newkeys(mode); | 777 | active_state->newkeys[mode] = kex_get_newkeys(mode); |
772 | if (active_state->newkeys[mode] == NULL) | 778 | if (active_state->newkeys[mode] == NULL) |
@@ -1009,6 +1015,7 @@ packet_send2(void) | |||
1009 | /* after a NEWKEYS message we can send the complete queue */ | 1015 | /* after a NEWKEYS message we can send the complete queue */ |
1010 | if (type == SSH2_MSG_NEWKEYS) { | 1016 | if (type == SSH2_MSG_NEWKEYS) { |
1011 | active_state->rekeying = 0; | 1017 | active_state->rekeying = 0; |
1018 | active_state->rekey_time = monotime(); | ||
1012 | while ((p = TAILQ_FIRST(&active_state->outgoing))) { | 1019 | while ((p = TAILQ_FIRST(&active_state->outgoing))) { |
1013 | type = p->type; | 1020 | type = p->type; |
1014 | debug("dequeue packet: %u", type); | 1021 | debug("dequeue packet: %u", type); |
@@ -1016,7 +1023,7 @@ packet_send2(void) | |||
1016 | memcpy(&active_state->outgoing_packet, &p->payload, | 1023 | memcpy(&active_state->outgoing_packet, &p->payload, |
1017 | sizeof(Buffer)); | 1024 | sizeof(Buffer)); |
1018 | TAILQ_REMOVE(&active_state->outgoing, p, next); | 1025 | TAILQ_REMOVE(&active_state->outgoing, p, next); |
1019 | xfree(p); | 1026 | free(p); |
1020 | packet_send2_wrapped(); | 1027 | packet_send2_wrapped(); |
1021 | } | 1028 | } |
1022 | } | 1029 | } |
@@ -1041,7 +1048,7 @@ packet_send(void) | |||
1041 | int | 1048 | int |
1042 | packet_read_seqnr(u_int32_t *seqnr_p) | 1049 | packet_read_seqnr(u_int32_t *seqnr_p) |
1043 | { | 1050 | { |
1044 | int type, len, ret, ms_remain, cont; | 1051 | int type, len, ret, cont, ms_remain = 0; |
1045 | fd_set *setp; | 1052 | fd_set *setp; |
1046 | char buf[8192]; | 1053 | char buf[8192]; |
1047 | struct timeval timeout, start, *timeoutp = NULL; | 1054 | struct timeval timeout, start, *timeoutp = NULL; |
@@ -1066,7 +1073,7 @@ packet_read_seqnr(u_int32_t *seqnr_p) | |||
1066 | packet_check_eom(); | 1073 | packet_check_eom(); |
1067 | /* If we got a packet, return it. */ | 1074 | /* If we got a packet, return it. */ |
1068 | if (type != SSH_MSG_NONE) { | 1075 | if (type != SSH_MSG_NONE) { |
1069 | xfree(setp); | 1076 | free(setp); |
1070 | return type; | 1077 | return type; |
1071 | } | 1078 | } |
1072 | /* | 1079 | /* |
@@ -1453,9 +1460,9 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p) | |||
1453 | packet_get_char(); | 1460 | packet_get_char(); |
1454 | msg = packet_get_string(NULL); | 1461 | msg = packet_get_string(NULL); |
1455 | debug("Remote: %.900s", msg); | 1462 | debug("Remote: %.900s", msg); |
1456 | xfree(msg); | 1463 | free(msg); |
1457 | msg = packet_get_string(NULL); | 1464 | msg = packet_get_string(NULL); |
1458 | xfree(msg); | 1465 | free(msg); |
1459 | break; | 1466 | break; |
1460 | case SSH2_MSG_DISCONNECT: | 1467 | case SSH2_MSG_DISCONNECT: |
1461 | reason = packet_get_int(); | 1468 | reason = packet_get_int(); |
@@ -1466,7 +1473,7 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p) | |||
1466 | SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, | 1473 | SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, |
1467 | "Received disconnect from %s: %u: %.400s", | 1474 | "Received disconnect from %s: %u: %.400s", |
1468 | get_remote_ipaddr(), reason, msg); | 1475 | get_remote_ipaddr(), reason, msg); |
1469 | xfree(msg); | 1476 | free(msg); |
1470 | cleanup_exit(255); | 1477 | cleanup_exit(255); |
1471 | break; | 1478 | break; |
1472 | case SSH2_MSG_UNIMPLEMENTED: | 1479 | case SSH2_MSG_UNIMPLEMENTED: |
@@ -1480,12 +1487,14 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p) | |||
1480 | } else { | 1487 | } else { |
1481 | type = packet_read_poll1(); | 1488 | type = packet_read_poll1(); |
1482 | switch (type) { | 1489 | switch (type) { |
1490 | case SSH_MSG_NONE: | ||
1491 | return SSH_MSG_NONE; | ||
1483 | case SSH_MSG_IGNORE: | 1492 | case SSH_MSG_IGNORE: |
1484 | break; | 1493 | break; |
1485 | case SSH_MSG_DEBUG: | 1494 | case SSH_MSG_DEBUG: |
1486 | msg = packet_get_string(NULL); | 1495 | msg = packet_get_string(NULL); |
1487 | debug("Remote: %.900s", msg); | 1496 | debug("Remote: %.900s", msg); |
1488 | xfree(msg); | 1497 | free(msg); |
1489 | break; | 1498 | break; |
1490 | case SSH_MSG_DISCONNECT: | 1499 | case SSH_MSG_DISCONNECT: |
1491 | msg = packet_get_string(NULL); | 1500 | msg = packet_get_string(NULL); |
@@ -1494,8 +1503,7 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p) | |||
1494 | cleanup_exit(255); | 1503 | cleanup_exit(255); |
1495 | break; | 1504 | break; |
1496 | default: | 1505 | default: |
1497 | if (type) | 1506 | DBG(debug("received packet type %d", type)); |
1498 | DBG(debug("received packet type %d", type)); | ||
1499 | return type; | 1507 | return type; |
1500 | } | 1508 | } |
1501 | } | 1509 | } |
@@ -1732,7 +1740,7 @@ void | |||
1732 | packet_write_wait(void) | 1740 | packet_write_wait(void) |
1733 | { | 1741 | { |
1734 | fd_set *setp; | 1742 | fd_set *setp; |
1735 | int ret, ms_remain; | 1743 | int ret, ms_remain = 0; |
1736 | struct timeval start, timeout, *timeoutp = NULL; | 1744 | struct timeval start, timeout, *timeoutp = NULL; |
1737 | 1745 | ||
1738 | setp = (fd_set *)xcalloc(howmany(active_state->connection_out + 1, | 1746 | setp = (fd_set *)xcalloc(howmany(active_state->connection_out + 1, |
@@ -1773,7 +1781,7 @@ packet_write_wait(void) | |||
1773 | } | 1781 | } |
1774 | packet_write_poll(); | 1782 | packet_write_poll(); |
1775 | } | 1783 | } |
1776 | xfree(setp); | 1784 | free(setp); |
1777 | } | 1785 | } |
1778 | 1786 | ||
1779 | /* Returns true if there is buffered data to write to the connection. */ | 1787 | /* Returns true if there is buffered data to write to the connection. */ |
@@ -1933,13 +1941,33 @@ packet_need_rekeying(void) | |||
1933 | (active_state->max_blocks_out && | 1941 | (active_state->max_blocks_out && |
1934 | (active_state->p_send.blocks > active_state->max_blocks_out)) || | 1942 | (active_state->p_send.blocks > active_state->max_blocks_out)) || |
1935 | (active_state->max_blocks_in && | 1943 | (active_state->max_blocks_in && |
1936 | (active_state->p_read.blocks > active_state->max_blocks_in)); | 1944 | (active_state->p_read.blocks > active_state->max_blocks_in)) || |
1945 | (active_state->rekey_interval != 0 && active_state->rekey_time + | ||
1946 | active_state->rekey_interval <= monotime()); | ||
1937 | } | 1947 | } |
1938 | 1948 | ||
1939 | void | 1949 | void |
1940 | packet_set_rekey_limit(u_int32_t bytes) | 1950 | packet_set_rekey_limits(u_int32_t bytes, time_t seconds) |
1941 | { | 1951 | { |
1952 | debug3("rekey after %lld bytes, %d seconds", (long long)bytes, | ||
1953 | (int)seconds); | ||
1942 | active_state->rekey_limit = bytes; | 1954 | active_state->rekey_limit = bytes; |
1955 | active_state->rekey_interval = seconds; | ||
1956 | /* | ||
1957 | * We set the time here so that in post-auth privsep slave we count | ||
1958 | * from the completion of the authentication. | ||
1959 | */ | ||
1960 | active_state->rekey_time = monotime(); | ||
1961 | } | ||
1962 | |||
1963 | time_t | ||
1964 | packet_get_rekey_timeout(void) | ||
1965 | { | ||
1966 | time_t seconds; | ||
1967 | |||
1968 | seconds = active_state->rekey_time + active_state->rekey_interval - | ||
1969 | monotime(); | ||
1970 | return (seconds <= 0 ? 1 : seconds); | ||
1943 | } | 1971 | } |
1944 | 1972 | ||
1945 | void | 1973 | void |