summaryrefslogtreecommitdiff
path: root/packet.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2003-09-23 18:08:35 +0000
committerColin Watson <cjwatson@debian.org>2003-09-23 18:08:35 +0000
commitd59fd3e421aa81b8e5e118f3f806081df2aca879 (patch)
tree356a4e607edc979c625bb33db63c656d771478bd /packet.c
parent7505658c58e96b8d270f1928a0e1fa7f3e0c266b (diff)
parent45431c9b4677608680cd071768cbf156b316a7e8 (diff)
Merge 3.7.1p2 to the trunk. I have absolutely no idea yet whether this will
work.
Diffstat (limited to 'packet.c')
-rw-r--r--packet.c181
1 files changed, 147 insertions, 34 deletions
diff --git a/packet.c b/packet.c
index dae1226a6..fd436d56f 100644
--- a/packet.c
+++ b/packet.c
@@ -37,7 +37,9 @@
37 */ 37 */
38 38
39#include "includes.h" 39#include "includes.h"
40RCSID("$OpenBSD: packet.c,v 1.104 2003/04/01 10:22:21 markus Exp $"); 40RCSID("$OpenBSD: packet.c,v 1.110 2003/09/19 09:02:02 markus Exp $");
41
42#include "openbsd-compat/sys-queue.h"
41 43
42#include "xmalloc.h" 44#include "xmalloc.h"
43#include "buffer.h" 45#include "buffer.h"
@@ -108,7 +110,7 @@ static int compression_buffer_ready = 0;
108static int packet_compression = 0; 110static int packet_compression = 0;
109 111
110/* default maximum packet size */ 112/* default maximum packet size */
111int max_packet_size = 32768; 113u_int max_packet_size = 32768;
112 114
113/* Flag indicating whether this module has been initialized. */ 115/* Flag indicating whether this module has been initialized. */
114static int initialized = 0; 116static int initialized = 0;
@@ -118,8 +120,14 @@ static int interactive_mode = 0;
118 120
119/* Session key information for Encryption and MAC */ 121/* Session key information for Encryption and MAC */
120Newkeys *newkeys[MODE_MAX]; 122Newkeys *newkeys[MODE_MAX];
121static u_int32_t read_seqnr = 0; 123static struct packet_state {
122static u_int32_t send_seqnr = 0; 124 u_int32_t seqnr;
125 u_int32_t packets;
126 u_int64_t blocks;
127} p_read, p_send;
128
129static u_int64_t max_blocks_in, max_blocks_out;
130static u_int32_t rekey_limit;
123 131
124/* Session key for protocol v1 */ 132/* Session key for protocol v1 */
125static u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; 133static u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
@@ -128,6 +136,13 @@ static u_int ssh1_keylen;
128/* roundup current message to extra_pad bytes */ 136/* roundup current message to extra_pad bytes */
129static u_char extra_pad = 0; 137static u_char extra_pad = 0;
130 138
139struct packet {
140 TAILQ_ENTRY(packet) next;
141 u_char type;
142 Buffer payload;
143};
144TAILQ_HEAD(, packet) outgoing;
145
131/* 146/*
132 * Sets the descriptors used for communication. Disables encryption until 147 * Sets the descriptors used for communication. Disables encryption until
133 * packet_set_encryption_key is called. 148 * packet_set_encryption_key is called.
@@ -151,6 +166,7 @@ packet_set_connection(int fd_in, int fd_out, int new_setup_timeout)
151 buffer_init(&output); 166 buffer_init(&output);
152 buffer_init(&outgoing_packet); 167 buffer_init(&outgoing_packet);
153 buffer_init(&incoming_packet); 168 buffer_init(&incoming_packet);
169 TAILQ_INIT(&outgoing);
154 } 170 }
155 /* Kludge: arrange the close function to be called from fatal(). */ 171 /* Kludge: arrange the close function to be called from fatal(). */
156 fatal_add_cleanup((void (*) (void *)) packet_close, NULL); 172 fatal_add_cleanup((void (*) (void *)) packet_close, NULL);
@@ -252,27 +268,31 @@ packet_set_iv(int mode, u_char *dat)
252 cipher_set_keyiv(cc, dat); 268 cipher_set_keyiv(cc, dat);
253} 269}
254int 270int
255packet_get_ssh1_cipher() 271packet_get_ssh1_cipher(void)
256{ 272{
257 return (cipher_get_number(receive_context.cipher)); 273 return (cipher_get_number(receive_context.cipher));
258} 274}
259 275
260 276void
261u_int32_t 277packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets)
262packet_get_seqnr(int mode)
263{ 278{
264 return (mode == MODE_IN ? read_seqnr : send_seqnr); 279 struct packet_state *state;
280
281 state = (mode == MODE_IN) ? &p_read : &p_send;
282 *seqnr = state->seqnr;
283 *blocks = state->blocks;
284 *packets = state->packets;
265} 285}
266 286
267void 287void
268packet_set_seqnr(int mode, u_int32_t seqnr) 288packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets)
269{ 289{
270 if (mode == MODE_IN) 290 struct packet_state *state;
271 read_seqnr = seqnr; 291
272 else if (mode == MODE_OUT) 292 state = (mode == MODE_IN) ? &p_read : &p_send;
273 send_seqnr = seqnr; 293 state->seqnr = seqnr;
274 else 294 state->blocks = blocks;
275 fatal("packet_set_seqnr: bad mode %d", mode); 295 state->packets = packets;
276} 296}
277 297
278/* returns 1 if connection is via ipv4 */ 298/* returns 1 if connection is via ipv4 */
@@ -565,6 +585,7 @@ set_newkeys(int mode)
565 Mac *mac; 585 Mac *mac;
566 Comp *comp; 586 Comp *comp;
567 CipherContext *cc; 587 CipherContext *cc;
588 u_int64_t *max_blocks;
568 int encrypt; 589 int encrypt;
569 590
570 debug2("set_newkeys: mode %d", mode); 591 debug2("set_newkeys: mode %d", mode);
@@ -572,9 +593,13 @@ set_newkeys(int mode)
572 if (mode == MODE_OUT) { 593 if (mode == MODE_OUT) {
573 cc = &send_context; 594 cc = &send_context;
574 encrypt = CIPHER_ENCRYPT; 595 encrypt = CIPHER_ENCRYPT;
596 p_send.packets = p_send.blocks = 0;
597 max_blocks = &max_blocks_out;
575 } else { 598 } else {
576 cc = &receive_context; 599 cc = &receive_context;
577 encrypt = CIPHER_DECRYPT; 600 encrypt = CIPHER_DECRYPT;
601 p_read.packets = p_read.blocks = 0;
602 max_blocks = &max_blocks_in;
578 } 603 }
579 if (newkeys[mode] != NULL) { 604 if (newkeys[mode] != NULL) {
580 debug("set_newkeys: rekeying"); 605 debug("set_newkeys: rekeying");
@@ -613,13 +638,23 @@ set_newkeys(int mode)
613 buffer_compress_init_recv(); 638 buffer_compress_init_recv();
614 comp->enabled = 1; 639 comp->enabled = 1;
615 } 640 }
641 /*
642 * The 2^(blocksize*2) limit is too expensive for 3DES,
643 * blowfish, etc, so enforce a 1GB limit for small blocksizes.
644 */
645 if (enc->block_size >= 16)
646 *max_blocks = (u_int64_t)1 << (enc->block_size*2);
647 else
648 *max_blocks = ((u_int64_t)1 << 30) / enc->block_size;
649 if (rekey_limit)
650 *max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size);
616} 651}
617 652
618/* 653/*
619 * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) 654 * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
620 */ 655 */
621static void 656static void
622packet_send2(void) 657packet_send2_wrapped(void)
623{ 658{
624 u_char type, *cp, *macbuf = NULL; 659 u_char type, *cp, *macbuf = NULL;
625 u_char padlen, pad; 660 u_char padlen, pad;
@@ -701,10 +736,10 @@ packet_send2(void)
701 736
702 /* compute MAC over seqnr and packet(length fields, payload, padding) */ 737 /* compute MAC over seqnr and packet(length fields, payload, padding) */
703 if (mac && mac->enabled) { 738 if (mac && mac->enabled) {
704 macbuf = mac_compute(mac, send_seqnr, 739 macbuf = mac_compute(mac, p_send.seqnr,
705 buffer_ptr(&outgoing_packet), 740 buffer_ptr(&outgoing_packet),
706 buffer_len(&outgoing_packet)); 741 buffer_len(&outgoing_packet));
707 DBG(debug("done calc MAC out #%d", send_seqnr)); 742 DBG(debug("done calc MAC out #%d", p_send.seqnr));
708 } 743 }
709 /* encrypt packet and append to output buffer. */ 744 /* encrypt packet and append to output buffer. */
710 cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 745 cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
@@ -718,14 +753,64 @@ packet_send2(void)
718 buffer_dump(&output); 753 buffer_dump(&output);
719#endif 754#endif
720 /* increment sequence number for outgoing packets */ 755 /* increment sequence number for outgoing packets */
721 if (++send_seqnr == 0) 756 if (++p_send.seqnr == 0)
722 log("outgoing seqnr wraps around"); 757 logit("outgoing seqnr wraps around");
758 if (++p_send.packets == 0)
759 if (!(datafellows & SSH_BUG_NOREKEY))
760 fatal("XXX too many packets with same key");
761 p_send.blocks += (packet_length + 4) / block_size;
723 buffer_clear(&outgoing_packet); 762 buffer_clear(&outgoing_packet);
724 763
725 if (type == SSH2_MSG_NEWKEYS) 764 if (type == SSH2_MSG_NEWKEYS)
726 set_newkeys(MODE_OUT); 765 set_newkeys(MODE_OUT);
727} 766}
728 767
768static void
769packet_send2(void)
770{
771 static int rekeying = 0;
772 struct packet *p;
773 u_char type, *cp;
774
775 cp = buffer_ptr(&outgoing_packet);
776 type = cp[5];
777
778 /* during rekeying we can only send key exchange messages */
779 if (rekeying) {
780 if (!((type >= SSH2_MSG_TRANSPORT_MIN) &&
781 (type <= SSH2_MSG_TRANSPORT_MAX))) {
782 debug("enqueue packet: %u", type);
783 p = xmalloc(sizeof(*p));
784 p->type = type;
785 memcpy(&p->payload, &outgoing_packet, sizeof(Buffer));
786 buffer_init(&outgoing_packet);
787 TAILQ_INSERT_TAIL(&outgoing, p, next);
788 return;
789 }
790 }
791
792 /* rekeying starts with sending KEXINIT */
793 if (type == SSH2_MSG_KEXINIT)
794 rekeying = 1;
795
796 packet_send2_wrapped();
797
798 /* after a NEWKEYS message we can send the complete queue */
799 if (type == SSH2_MSG_NEWKEYS) {
800 rekeying = 0;
801 while ((p = TAILQ_FIRST(&outgoing))) {
802 type = p->type;
803 debug("dequeue packet: %u", type);
804 buffer_free(&outgoing_packet);
805 memcpy(&outgoing_packet, &p->payload,
806 sizeof(Buffer));
807 TAILQ_REMOVE(&outgoing, p, next);
808 xfree(p);
809 packet_send2_wrapped();
810 }
811 }
812}
813
729void 814void
730packet_send(void) 815packet_send(void)
731{ 816{
@@ -798,7 +883,7 @@ packet_read_seqnr(u_int32_t *seqnr_p)
798 /* Read data from the socket. */ 883 /* Read data from the socket. */
799 len = read(connection_in, buf, sizeof(buf)); 884 len = read(connection_in, buf, sizeof(buf));
800 if (len == 0) { 885 if (len == 0) {
801 log("Connection closed by %.200s", get_remote_ipaddr()); 886 logit("Connection closed by %.200s", get_remote_ipaddr());
802 fatal_cleanup(); 887 fatal_cleanup();
803 } 888 }
804 if (len < 0) 889 if (len < 0)
@@ -949,7 +1034,9 @@ packet_read_poll2(u_int32_t *seqnr_p)
949 cp = buffer_ptr(&incoming_packet); 1034 cp = buffer_ptr(&incoming_packet);
950 packet_length = GET_32BIT(cp); 1035 packet_length = GET_32BIT(cp);
951 if (packet_length < 1 + 4 || packet_length > 256 * 1024) { 1036 if (packet_length < 1 + 4 || packet_length > 256 * 1024) {
1037#ifdef PACKET_DEBUG
952 buffer_dump(&incoming_packet); 1038 buffer_dump(&incoming_packet);
1039#endif
953 packet_disconnect("Bad packet length %u.", packet_length); 1040 packet_disconnect("Bad packet length %u.", packet_length);
954 } 1041 }
955 DBG(debug("input: packet len %u", packet_length+4)); 1042 DBG(debug("input: packet len %u", packet_length+4));
@@ -980,18 +1067,22 @@ packet_read_poll2(u_int32_t *seqnr_p)
980 * increment sequence number for incoming packet 1067 * increment sequence number for incoming packet
981 */ 1068 */
982 if (mac && mac->enabled) { 1069 if (mac && mac->enabled) {
983 macbuf = mac_compute(mac, read_seqnr, 1070 macbuf = mac_compute(mac, p_read.seqnr,
984 buffer_ptr(&incoming_packet), 1071 buffer_ptr(&incoming_packet),
985 buffer_len(&incoming_packet)); 1072 buffer_len(&incoming_packet));
986 if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) 1073 if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
987 packet_disconnect("Corrupted MAC on input."); 1074 packet_disconnect("Corrupted MAC on input.");
988 DBG(debug("MAC #%d ok", read_seqnr)); 1075 DBG(debug("MAC #%d ok", p_read.seqnr));
989 buffer_consume(&input, mac->mac_len); 1076 buffer_consume(&input, mac->mac_len);
990 } 1077 }
991 if (seqnr_p != NULL) 1078 if (seqnr_p != NULL)
992 *seqnr_p = read_seqnr; 1079 *seqnr_p = p_read.seqnr;
993 if (++read_seqnr == 0) 1080 if (++p_read.seqnr == 0)
994 log("incoming seqnr wraps around"); 1081 logit("incoming seqnr wraps around");
1082 if (++p_read.packets == 0)
1083 if (!(datafellows & SSH_BUG_NOREKEY))
1084 fatal("XXX too many packets with same key");
1085 p_read.blocks += (packet_length + 4) / block_size;
995 1086
996 /* get padlen */ 1087 /* get padlen */
997 cp = buffer_ptr(&incoming_packet); 1088 cp = buffer_ptr(&incoming_packet);
@@ -1056,7 +1147,7 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p)
1056 case SSH2_MSG_DISCONNECT: 1147 case SSH2_MSG_DISCONNECT:
1057 reason = packet_get_int(); 1148 reason = packet_get_int();
1058 msg = packet_get_string(NULL); 1149 msg = packet_get_string(NULL);
1059 log("Received disconnect from %s: %u: %.400s", 1150 logit("Received disconnect from %s: %u: %.400s",
1060 get_remote_ipaddr(), reason, msg); 1151 get_remote_ipaddr(), reason, msg);
1061 xfree(msg); 1152 xfree(msg);
1062 fatal_cleanup(); 1153 fatal_cleanup();
@@ -1082,7 +1173,7 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p)
1082 break; 1173 break;
1083 case SSH_MSG_DISCONNECT: 1174 case SSH_MSG_DISCONNECT:
1084 msg = packet_get_string(NULL); 1175 msg = packet_get_string(NULL);
1085 log("Received disconnect from %s: %.400s", 1176 logit("Received disconnect from %s: %.400s",
1086 get_remote_ipaddr(), msg); 1177 get_remote_ipaddr(), msg);
1087 fatal_cleanup(); 1178 fatal_cleanup();
1088 xfree(msg); 1179 xfree(msg);
@@ -1241,7 +1332,7 @@ packet_disconnect(const char *fmt,...)
1241 va_end(args); 1332 va_end(args);
1242 1333
1243 /* Display the error locally */ 1334 /* Display the error locally */
1244 log("Disconnecting: %.100s", buf); 1335 logit("Disconnecting: %.100s", buf);
1245 1336
1246 /* Send the disconnect message to the other side, and wait for it to get sent. */ 1337 /* Send the disconnect message to the other side, and wait for it to get sent. */
1247 if (compat20) { 1338 if (compat20) {
@@ -1328,6 +1419,8 @@ packet_not_very_much_data_to_write(void)
1328 return buffer_len(&output) < 128 * 1024; 1419 return buffer_len(&output) < 128 * 1024;
1329} 1420}
1330 1421
1422
1423#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
1331static void 1424static void
1332packet_set_tos(int interactive) 1425packet_set_tos(int interactive)
1333{ 1426{
@@ -1341,6 +1434,7 @@ packet_set_tos(int interactive)
1341 error("setsockopt IP_TOS %d: %.100s:", 1434 error("setsockopt IP_TOS %d: %.100s:",
1342 tos, strerror(errno)); 1435 tos, strerror(errno));
1343} 1436}
1437#endif
1344 1438
1345/* Informs that the current session is interactive. Sets IP flags for that. */ 1439/* Informs that the current session is interactive. Sets IP flags for that. */
1346 1440
@@ -1375,18 +1469,18 @@ packet_is_interactive(void)
1375 return interactive_mode; 1469 return interactive_mode;
1376} 1470}
1377 1471
1378int 1472u_int
1379packet_set_maxsize(int s) 1473packet_set_maxsize(u_int s)
1380{ 1474{
1381 static int called = 0; 1475 static int called = 0;
1382 1476
1383 if (called) { 1477 if (called) {
1384 log("packet_set_maxsize: called twice: old %d new %d", 1478 logit("packet_set_maxsize: called twice: old %d new %d",
1385 max_packet_size, s); 1479 max_packet_size, s);
1386 return -1; 1480 return -1;
1387 } 1481 }
1388 if (s < 4 * 1024 || s > 1024 * 1024) { 1482 if (s < 4 * 1024 || s > 1024 * 1024) {
1389 log("packet_set_maxsize: bad size %d", s); 1483 logit("packet_set_maxsize: bad size %d", s);
1390 return -1; 1484 return -1;
1391 } 1485 }
1392 called = 1; 1486 called = 1;
@@ -1428,3 +1522,22 @@ packet_send_ignore(int nbytes)
1428 rand >>= 8; 1522 rand >>= 8;
1429 } 1523 }
1430} 1524}
1525
1526#define MAX_PACKETS (1<<31)
1527int
1528packet_need_rekeying(void)
1529{
1530 if (datafellows & SSH_BUG_NOREKEY)
1531 return 0;
1532 return
1533 (p_send.packets > MAX_PACKETS) ||
1534 (p_read.packets > MAX_PACKETS) ||
1535 (max_blocks_out && (p_send.blocks > max_blocks_out)) ||
1536 (max_blocks_in && (p_read.blocks > max_blocks_in));
1537}
1538
1539void
1540packet_set_rekey_limit(u_int32_t bytes)
1541{
1542 rekey_limit = bytes;
1543}