Mercurial > dropbear
comparison packet.c @ 1580:7f2be495dff6 coverity
merge coverity
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sun, 04 Mar 2018 15:07:09 +0800 |
parents | 399d8eb961b5 |
children | 8f7b6f75aa58 |
comparison
equal
deleted
inserted
replaced
1545:0b991dec7ab9 | 1580:7f2be495dff6 |
---|---|
33 #include "dbrandom.h" | 33 #include "dbrandom.h" |
34 #include "service.h" | 34 #include "service.h" |
35 #include "auth.h" | 35 #include "auth.h" |
36 #include "channel.h" | 36 #include "channel.h" |
37 #include "netio.h" | 37 #include "netio.h" |
38 #include "runopts.h" | |
38 | 39 |
39 static int read_packet_init(void); | 40 static int read_packet_init(void); |
40 static void make_mac(unsigned int seqno, const struct key_context_directional * key_state, | 41 static void make_mac(unsigned int seqno, const struct key_context_directional * key_state, |
41 buffer * clear_buf, unsigned int clear_len, | 42 buffer * clear_buf, unsigned int clear_len, |
42 unsigned char *output_mac); | 43 unsigned char *output_mac); |
62 unsigned int iov_count = 50; | 63 unsigned int iov_count = 50; |
63 struct iovec iov[50]; | 64 struct iovec iov[50]; |
64 #else | 65 #else |
65 int len; | 66 int len; |
66 buffer* writebuf; | 67 buffer* writebuf; |
67 int packet_type; | |
68 #endif | 68 #endif |
69 | 69 |
70 TRACE2(("enter write_packet")) | 70 TRACE2(("enter write_packet")) |
71 dropbear_assert(!isempty(&ses.writequeue)); | 71 dropbear_assert(!isempty(&ses.writequeue)); |
72 | 72 |
74 | 74 |
75 packet_queue_to_iovec(&ses.writequeue, iov, &iov_count); | 75 packet_queue_to_iovec(&ses.writequeue, iov, &iov_count); |
76 /* This may return EAGAIN. The main loop sometimes | 76 /* This may return EAGAIN. The main loop sometimes |
77 calls write_packet() without bothering to test with select() since | 77 calls write_packet() without bothering to test with select() since |
78 it's likely to be necessary */ | 78 it's likely to be necessary */ |
79 #if DROPBEAR_FUZZ | |
80 if (fuzz.fuzzing) { | |
81 /* pretend to write one packet at a time */ | |
82 /* TODO(fuzz): randomise amount written based on the fuzz input */ | |
83 written = iov[0].iov_len; | |
84 } | |
85 else | |
86 #endif | |
87 { | |
79 written = writev(ses.sock_out, iov, iov_count); | 88 written = writev(ses.sock_out, iov, iov_count); |
80 if (written < 0) { | 89 if (written < 0) { |
81 if (errno == EINTR || errno == EAGAIN) { | 90 if (errno == EINTR || errno == EAGAIN) { |
82 TRACE2(("leave write_packet: EINTR")) | 91 TRACE2(("leave write_packet: EINTR")) |
83 return; | 92 return; |
84 } else { | 93 } else { |
85 dropbear_exit("Error writing: %s", strerror(errno)); | 94 dropbear_exit("Error writing: %s", strerror(errno)); |
86 } | 95 } |
87 } | 96 } |
97 } | |
88 | 98 |
89 packet_queue_consume(&ses.writequeue, written); | 99 packet_queue_consume(&ses.writequeue, written); |
90 ses.writequeue_len -= written; | 100 ses.writequeue_len -= written; |
91 | 101 |
92 if (written == 0) { | 102 if (written == 0) { |
93 ses.remoteclosed(); | 103 ses.remoteclosed(); |
94 } | 104 } |
95 | 105 |
96 #else /* No writev () */ | 106 #else /* No writev () */ |
107 #if DROPBEAR_FUZZ | |
108 _Static_assert(0, "No fuzzing code for no-writev writes"); | |
109 #endif | |
97 /* Get the next buffer in the queue of encrypted packets to write*/ | 110 /* Get the next buffer in the queue of encrypted packets to write*/ |
98 writebuf = (buffer*)examine(&ses.writequeue); | 111 writebuf = (buffer*)examine(&ses.writequeue); |
99 | 112 |
100 /* The last byte of the buffer is not to be transmitted, but is | 113 /* The last byte of the buffer is not to be transmitted, but is |
101 * a cleartext packet_type indicator */ | 114 * a cleartext packet_type indicator */ |
102 packet_type = writebuf->data[writebuf->len-1]; | 115 len = writebuf->len - writebuf->pos; |
103 len = writebuf->len - 1 - writebuf->pos; | |
104 TRACE2(("write_packet type %d len %d/%d", packet_type, | |
105 len, writebuf->len-1)) | |
106 dropbear_assert(len > 0); | 116 dropbear_assert(len > 0); |
107 /* Try to write as much as possible */ | 117 /* Try to write as much as possible */ |
108 written = write(ses.sock_out, buf_getptr(writebuf, len), len); | 118 written = write(ses.sock_out, buf_getptr(writebuf, len), len); |
109 | 119 |
110 if (written < 0) { | 120 if (written < 0) { |
349 mac_size = ses.keys->recv.algo_mac->hashsize; | 359 mac_size = ses.keys->recv.algo_mac->hashsize; |
350 contents_len = ses.readbuf->len - mac_size; | 360 contents_len = ses.readbuf->len - mac_size; |
351 | 361 |
352 buf_setpos(ses.readbuf, 0); | 362 buf_setpos(ses.readbuf, 0); |
353 make_mac(ses.recvseq, &ses.keys->recv, ses.readbuf, contents_len, mac_bytes); | 363 make_mac(ses.recvseq, &ses.keys->recv, ses.readbuf, contents_len, mac_bytes); |
364 | |
365 #if DROPBEAR_FUZZ | |
366 if (fuzz.fuzzing) { | |
367 /* fail 1 in 2000 times to test error path. | |
368 note that mac_bytes is all zero prior to kex, so don't test ==0 ! */ | |
369 unsigned int value = *((unsigned int*)&mac_bytes); | |
370 if (value % 2000 == 99) { | |
371 return DROPBEAR_FAILURE; | |
372 } | |
373 return DROPBEAR_SUCCESS; | |
374 } | |
375 #endif | |
354 | 376 |
355 /* compare the hash */ | 377 /* compare the hash */ |
356 buf_setpos(ses.readbuf, contents_len); | 378 buf_setpos(ses.readbuf, contents_len); |
357 if (constant_time_memcmp(mac_bytes, buf_getptr(ses.readbuf, mac_size), mac_size) != 0) { | 379 if (constant_time_memcmp(mac_bytes, buf_getptr(ses.readbuf, mac_size), mac_size) != 0) { |
358 return DROPBEAR_FAILURE; | 380 return DROPBEAR_FAILURE; |
576 buf_putbytes(writebuf, mac_bytes, mac_size); | 598 buf_putbytes(writebuf, mac_bytes, mac_size); |
577 | 599 |
578 /* Update counts */ | 600 /* Update counts */ |
579 ses.kexstate.datatrans += writebuf->len; | 601 ses.kexstate.datatrans += writebuf->len; |
580 | 602 |
581 writebuf_enqueue(writebuf, packet_type); | 603 writebuf_enqueue(writebuf); |
582 | 604 |
583 /* Update counts */ | 605 /* Update counts */ |
584 ses.transseq++; | 606 ses.transseq++; |
585 | 607 |
586 now = monotonic_now(); | 608 now = monotonic_now(); |
596 } | 618 } |
597 | 619 |
598 TRACE2(("leave encrypt_packet()")) | 620 TRACE2(("leave encrypt_packet()")) |
599 } | 621 } |
600 | 622 |
601 void writebuf_enqueue(buffer * writebuf, unsigned char packet_type) { | 623 void writebuf_enqueue(buffer * writebuf) { |
602 /* The last byte of the buffer stores the cleartext packet_type. It is not | |
603 * transmitted but is used for transmit timeout purposes */ | |
604 buf_putbyte(writebuf, packet_type); | |
605 /* enqueue the packet for sending. It will get freed after transmission. */ | 624 /* enqueue the packet for sending. It will get freed after transmission. */ |
606 buf_setpos(writebuf, 0); | 625 buf_setpos(writebuf, 0); |
607 enqueue(&ses.writequeue, (void*)writebuf); | 626 enqueue(&ses.writequeue, (void*)writebuf); |
608 ses.writequeue_len += writebuf->len-1; | 627 ses.writequeue_len += writebuf->len; |
609 } | 628 } |
610 | 629 |
611 | 630 |
612 /* Create the packet mac, and append H(seqno|clearbuf) to the output */ | 631 /* Create the packet mac, and append H(seqno|clearbuf) to the output */ |
613 /* output_mac must have ses.keys->trans.algo_mac->hashsize bytes. */ | 632 /* output_mac must have ses.keys->trans.algo_mac->hashsize bytes. */ |