summaryrefslogtreecommitdiff
path: root/packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'packet.c')
-rw-r--r--packet.c145
1 files changed, 123 insertions, 22 deletions
diff --git a/packet.c b/packet.c
index 254e452d0..9887d25af 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.105 2003/04/02 09:48:07 markus Exp $");
41
42#include <sys/queue.h>
41 43
42#include "xmalloc.h" 44#include "xmalloc.h"
43#include "buffer.h" 45#include "buffer.h"
@@ -116,8 +118,14 @@ static int interactive_mode = 0;
116 118
117/* Session key information for Encryption and MAC */ 119/* Session key information for Encryption and MAC */
118Newkeys *newkeys[MODE_MAX]; 120Newkeys *newkeys[MODE_MAX];
119static u_int32_t read_seqnr = 0; 121static struct packet_state {
120static u_int32_t send_seqnr = 0; 122 u_int32_t seqnr;
123 u_int32_t packets;
124 u_int64_t blocks;
125} p_read, p_send;
126
127static u_int64_t max_blocks_in, max_blocks_out;
128static u_int32_t rekey_limit;
121 129
122/* Session key for protocol v1 */ 130/* Session key for protocol v1 */
123static u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; 131static u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
@@ -126,6 +134,13 @@ static u_int ssh1_keylen;
126/* roundup current message to extra_pad bytes */ 134/* roundup current message to extra_pad bytes */
127static u_char extra_pad = 0; 135static u_char extra_pad = 0;
128 136
137struct packet {
138 TAILQ_ENTRY(packet) next;
139 u_char type;
140 Buffer payload;
141};
142TAILQ_HEAD(, packet) outgoing;
143
129/* 144/*
130 * Sets the descriptors used for communication. Disables encryption until 145 * Sets the descriptors used for communication. Disables encryption until
131 * packet_set_encryption_key is called. 146 * packet_set_encryption_key is called.
@@ -148,6 +163,7 @@ packet_set_connection(int fd_in, int fd_out)
148 buffer_init(&output); 163 buffer_init(&output);
149 buffer_init(&outgoing_packet); 164 buffer_init(&outgoing_packet);
150 buffer_init(&incoming_packet); 165 buffer_init(&incoming_packet);
166 TAILQ_INIT(&outgoing);
151 } 167 }
152 /* Kludge: arrange the close function to be called from fatal(). */ 168 /* Kludge: arrange the close function to be called from fatal(). */
153 fatal_add_cleanup((void (*) (void *)) packet_close, NULL); 169 fatal_add_cleanup((void (*) (void *)) packet_close, NULL);
@@ -254,22 +270,26 @@ packet_get_ssh1_cipher()
254 return (cipher_get_number(receive_context.cipher)); 270 return (cipher_get_number(receive_context.cipher));
255} 271}
256 272
257 273void
258u_int32_t 274packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets)
259packet_get_seqnr(int mode)
260{ 275{
261 return (mode == MODE_IN ? read_seqnr : send_seqnr); 276 struct packet_state *state;
277
278 state = (mode == MODE_IN) ? &p_read : &p_send;
279 *seqnr = state->seqnr;
280 *blocks = state->blocks;
281 *packets = state->packets;
262} 282}
263 283
264void 284void
265packet_set_seqnr(int mode, u_int32_t seqnr) 285packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets)
266{ 286{
267 if (mode == MODE_IN) 287 struct packet_state *state;
268 read_seqnr = seqnr; 288
269 else if (mode == MODE_OUT) 289 state = (mode == MODE_IN) ? &p_read : &p_send;
270 send_seqnr = seqnr; 290 state->seqnr = seqnr;
271 else 291 state->blocks = blocks;
272 fatal("packet_set_seqnr: bad mode %d", mode); 292 state->packets = packets;
273} 293}
274 294
275/* returns 1 if connection is via ipv4 */ 295/* returns 1 if connection is via ipv4 */
@@ -562,6 +582,7 @@ set_newkeys(int mode)
562 Mac *mac; 582 Mac *mac;
563 Comp *comp; 583 Comp *comp;
564 CipherContext *cc; 584 CipherContext *cc;
585 u_int64_t *max_blocks;
565 int encrypt; 586 int encrypt;
566 587
567 debug2("set_newkeys: mode %d", mode); 588 debug2("set_newkeys: mode %d", mode);
@@ -569,9 +590,13 @@ set_newkeys(int mode)
569 if (mode == MODE_OUT) { 590 if (mode == MODE_OUT) {
570 cc = &send_context; 591 cc = &send_context;
571 encrypt = CIPHER_ENCRYPT; 592 encrypt = CIPHER_ENCRYPT;
593 p_send.packets = p_send.blocks = 0;
594 max_blocks = &max_blocks_out;
572 } else { 595 } else {
573 cc = &receive_context; 596 cc = &receive_context;
574 encrypt = CIPHER_DECRYPT; 597 encrypt = CIPHER_DECRYPT;
598 p_read.packets = p_read.blocks = 0;
599 max_blocks = &max_blocks_in;
575 } 600 }
576 if (newkeys[mode] != NULL) { 601 if (newkeys[mode] != NULL) {
577 debug("set_newkeys: rekeying"); 602 debug("set_newkeys: rekeying");
@@ -610,13 +635,16 @@ set_newkeys(int mode)
610 buffer_compress_init_recv(); 635 buffer_compress_init_recv();
611 comp->enabled = 1; 636 comp->enabled = 1;
612 } 637 }
638 *max_blocks = ((u_int64_t)1 << (enc->block_size*2));
639 if (rekey_limit)
640 *max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size);
613} 641}
614 642
615/* 643/*
616 * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) 644 * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
617 */ 645 */
618static void 646static void
619packet_send2(void) 647packet_send2_wrapped(void)
620{ 648{
621 u_char type, *cp, *macbuf = NULL; 649 u_char type, *cp, *macbuf = NULL;
622 u_char padlen, pad; 650 u_char padlen, pad;
@@ -698,10 +726,10 @@ packet_send2(void)
698 726
699 /* compute MAC over seqnr and packet(length fields, payload, padding) */ 727 /* compute MAC over seqnr and packet(length fields, payload, padding) */
700 if (mac && mac->enabled) { 728 if (mac && mac->enabled) {
701 macbuf = mac_compute(mac, send_seqnr, 729 macbuf = mac_compute(mac, p_send.seqnr,
702 buffer_ptr(&outgoing_packet), 730 buffer_ptr(&outgoing_packet),
703 buffer_len(&outgoing_packet)); 731 buffer_len(&outgoing_packet));
704 DBG(debug("done calc MAC out #%d", send_seqnr)); 732 DBG(debug("done calc MAC out #%d", p_send.seqnr));
705 } 733 }
706 /* encrypt packet and append to output buffer. */ 734 /* encrypt packet and append to output buffer. */
707 cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 735 cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
@@ -715,14 +743,64 @@ packet_send2(void)
715 buffer_dump(&output); 743 buffer_dump(&output);
716#endif 744#endif
717 /* increment sequence number for outgoing packets */ 745 /* increment sequence number for outgoing packets */
718 if (++send_seqnr == 0) 746 if (++p_send.seqnr == 0)
719 log("outgoing seqnr wraps around"); 747 log("outgoing seqnr wraps around");
748 if (++p_send.packets == 0)
749 if (!(datafellows & SSH_BUG_NOREKEY))
750 fatal("XXX too many packets with same key");
751 p_send.blocks += (packet_length + 4) / block_size;
720 buffer_clear(&outgoing_packet); 752 buffer_clear(&outgoing_packet);
721 753
722 if (type == SSH2_MSG_NEWKEYS) 754 if (type == SSH2_MSG_NEWKEYS)
723 set_newkeys(MODE_OUT); 755 set_newkeys(MODE_OUT);
724} 756}
725 757
758static void
759packet_send2(void)
760{
761 static int rekeying = 0;
762 struct packet *p;
763 u_char type, *cp;
764
765 cp = buffer_ptr(&outgoing_packet);
766 type = cp[5];
767
768 /* during rekeying we can only send key exchange messages */
769 if (rekeying) {
770 if (!((type >= SSH2_MSG_TRANSPORT_MIN) &&
771 (type <= SSH2_MSG_TRANSPORT_MAX))) {
772 debug("enqueue packet: %u", type);
773 p = xmalloc(sizeof(*p));
774 p->type = type;
775 memcpy(&p->payload, &outgoing_packet, sizeof(Buffer));
776 buffer_init(&outgoing_packet);
777 TAILQ_INSERT_TAIL(&outgoing, p, next);
778 return;
779 }
780 }
781
782 /* rekeying starts with sending KEXINIT */
783 if (type == SSH2_MSG_KEXINIT)
784 rekeying = 1;
785
786 packet_send2_wrapped();
787
788 /* after a NEWKEYS message we can send the complete queue */
789 if (type == SSH2_MSG_NEWKEYS) {
790 rekeying = 0;
791 while ((p = TAILQ_FIRST(&outgoing))) {
792 type = p->type;
793 debug("dequeue packet: %u", type);
794 buffer_free(&outgoing_packet);
795 memcpy(&outgoing_packet, &p->payload,
796 sizeof(Buffer));
797 TAILQ_REMOVE(&outgoing, p, next);
798 xfree(p);
799 packet_send2_wrapped();
800 }
801 }
802}
803
726void 804void
727packet_send(void) 805packet_send(void)
728{ 806{
@@ -966,18 +1044,22 @@ packet_read_poll2(u_int32_t *seqnr_p)
966 * increment sequence number for incoming packet 1044 * increment sequence number for incoming packet
967 */ 1045 */
968 if (mac && mac->enabled) { 1046 if (mac && mac->enabled) {
969 macbuf = mac_compute(mac, read_seqnr, 1047 macbuf = mac_compute(mac, p_read.seqnr,
970 buffer_ptr(&incoming_packet), 1048 buffer_ptr(&incoming_packet),
971 buffer_len(&incoming_packet)); 1049 buffer_len(&incoming_packet));
972 if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) 1050 if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
973 packet_disconnect("Corrupted MAC on input."); 1051 packet_disconnect("Corrupted MAC on input.");
974 DBG(debug("MAC #%d ok", read_seqnr)); 1052 DBG(debug("MAC #%d ok", p_read.seqnr));
975 buffer_consume(&input, mac->mac_len); 1053 buffer_consume(&input, mac->mac_len);
976 } 1054 }
977 if (seqnr_p != NULL) 1055 if (seqnr_p != NULL)
978 *seqnr_p = read_seqnr; 1056 *seqnr_p = p_read.seqnr;
979 if (++read_seqnr == 0) 1057 if (++p_read.seqnr == 0)
980 log("incoming seqnr wraps around"); 1058 log("incoming seqnr wraps around");
1059 if (++p_read.packets == 0)
1060 if (!(datafellows & SSH_BUG_NOREKEY))
1061 fatal("XXX too many packets with same key");
1062 p_read.blocks += (packet_length + 4) / block_size;
981 1063
982 /* get padlen */ 1064 /* get padlen */
983 cp = buffer_ptr(&incoming_packet); 1065 cp = buffer_ptr(&incoming_packet);
@@ -1416,3 +1498,22 @@ packet_send_ignore(int nbytes)
1416 rand >>= 8; 1498 rand >>= 8;
1417 } 1499 }
1418} 1500}
1501
1502#define MAX_PACKETS (1<<31)
1503int
1504packet_need_rekeying(void)
1505{
1506 if (datafellows & SSH_BUG_NOREKEY)
1507 return 0;
1508 return
1509 (p_send.packets > MAX_PACKETS) ||
1510 (p_read.packets > MAX_PACKETS) ||
1511 (max_blocks_out && (p_send.blocks > max_blocks_out)) ||
1512 (max_blocks_in && (p_read.blocks > max_blocks_in));
1513}
1514
1515void
1516packet_set_rekey_limit(u_int32_t bytes)
1517{
1518 rekey_limit = bytes;
1519}