Mercurial > dropbear
comparison packet.c @ 743:09c5eb71ec96 kexguess
merge from head roundtrip changes
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 01 Apr 2013 00:13:41 +0800 |
parents | 9a5438271556 |
children | 24172f555f9c |
comparison
equal
deleted
inserted
replaced
742:cd201dc2da9a | 743:09c5eb71ec96 |
---|---|
53 | 53 |
54 int len, written; | 54 int len, written; |
55 buffer * writebuf = NULL; | 55 buffer * writebuf = NULL; |
56 time_t now; | 56 time_t now; |
57 unsigned packet_type; | 57 unsigned packet_type; |
58 | 58 int all_ignore = 1; |
59 TRACE(("enter write_packet")) | 59 #ifdef HAVE_WRITEV |
60 struct iovec *iov = NULL; | |
61 int i; | |
62 struct Link *l; | |
63 #endif | |
64 | |
65 TRACE2(("enter write_packet")) | |
60 dropbear_assert(!isempty(&ses.writequeue)); | 66 dropbear_assert(!isempty(&ses.writequeue)); |
61 | 67 |
68 #ifdef HAVE_WRITEV | |
69 iov = m_malloc(sizeof(*iov) * ses.writequeue.count); | |
70 for (l = ses.writequeue.head, i = 0; l; l = l->link, i++) | |
71 { | |
72 writebuf = (buffer*)l->item; | |
73 packet_type = writebuf->data[writebuf->len-1]; | |
74 len = writebuf->len - 1 - writebuf->pos; | |
75 dropbear_assert(len > 0); | |
76 all_ignore &= (packet_type == SSH_MSG_IGNORE); | |
77 iov[i].iov_base = buf_getptr(writebuf, len); | |
78 iov[i].iov_len = len; | |
79 } | |
80 written = writev(ses.sock_out, iov, ses.writequeue.count); | |
81 if (written < 0) { | |
82 if (errno == EINTR) { | |
83 m_free(iov); | |
84 TRACE2(("leave writepacket: EINTR")) | |
85 return; | |
86 } else { | |
87 dropbear_exit("Error writing"); | |
88 } | |
89 } | |
90 | |
91 if (written == 0) { | |
92 ses.remoteclosed(); | |
93 } | |
94 | |
95 while (written > 0) { | |
96 writebuf = (buffer*)examine(&ses.writequeue); | |
97 len = writebuf->len - 1 - writebuf->pos; | |
98 if (len > written) { | |
99 // partial buffer write | |
100 buf_incrpos(writebuf, written); | |
101 written = 0; | |
102 } else { | |
103 written -= len; | |
104 dequeue(&ses.writequeue); | |
105 buf_free(writebuf); | |
106 } | |
107 } | |
108 | |
109 m_free(iov); | |
110 | |
111 #else | |
62 /* Get the next buffer in the queue of encrypted packets to write*/ | 112 /* Get the next buffer in the queue of encrypted packets to write*/ |
63 writebuf = (buffer*)examine(&ses.writequeue); | 113 writebuf = (buffer*)examine(&ses.writequeue); |
64 | 114 |
65 /* The last byte of the buffer is not to be transmitted, but is | 115 /* The last byte of the buffer is not to be transmitted, but is |
66 * a cleartext packet_type indicator */ | 116 * a cleartext packet_type indicator */ |
70 /* Try to write as much as possible */ | 120 /* Try to write as much as possible */ |
71 written = write(ses.sock_out, buf_getptr(writebuf, len), len); | 121 written = write(ses.sock_out, buf_getptr(writebuf, len), len); |
72 | 122 |
73 if (written < 0) { | 123 if (written < 0) { |
74 if (errno == EINTR) { | 124 if (errno == EINTR) { |
75 TRACE(("leave writepacket: EINTR")) | 125 TRACE2(("leave writepacket: EINTR")) |
76 return; | 126 return; |
77 } else { | 127 } else { |
78 dropbear_exit("Error writing"); | 128 dropbear_exit("Error writing"); |
79 } | 129 } |
80 } | 130 } |
81 | 131 all_ignore = (packet_type == SSH_MSG_IGNORE); |
82 now = time(NULL); | |
83 ses.last_trx_packet_time = now; | |
84 | |
85 if (packet_type != SSH_MSG_IGNORE) { | |
86 ses.last_packet_time = now; | |
87 } | |
88 | 132 |
89 if (written == 0) { | 133 if (written == 0) { |
90 ses.remoteclosed(); | 134 ses.remoteclosed(); |
91 } | 135 } |
92 | 136 |
98 } else { | 142 } else { |
99 /* More packet left to write, leave it in the queue for later */ | 143 /* More packet left to write, leave it in the queue for later */ |
100 buf_incrpos(writebuf, written); | 144 buf_incrpos(writebuf, written); |
101 } | 145 } |
102 | 146 |
103 TRACE(("leave write_packet")) | 147 #endif |
148 now = time(NULL); | |
149 ses.last_trx_packet_time = now; | |
150 | |
151 if (!all_ignore) { | |
152 ses.last_packet_time = now; | |
153 } | |
154 | |
155 TRACE2(("leave write_packet")) | |
104 } | 156 } |
105 | 157 |
106 /* Non-blocking function reading available portion of a packet into the | 158 /* Non-blocking function reading available portion of a packet into the |
107 * ses's buffer, decrypting the length if encrypted, decrypting the | 159 * ses's buffer, decrypting the length if encrypted, decrypting the |
108 * full portion if possible */ | 160 * full portion if possible */ |
110 | 162 |
111 int len; | 163 int len; |
112 unsigned int maxlen; | 164 unsigned int maxlen; |
113 unsigned char blocksize; | 165 unsigned char blocksize; |
114 | 166 |
115 TRACE(("enter read_packet")) | 167 TRACE2(("enter read_packet")) |
116 blocksize = ses.keys->recv.algo_crypt->blocksize; | 168 blocksize = ses.keys->recv.algo_crypt->blocksize; |
117 | 169 |
118 if (ses.readbuf == NULL || ses.readbuf->len < blocksize) { | 170 if (ses.readbuf == NULL || ses.readbuf->len < blocksize) { |
119 int ret; | 171 int ret; |
120 /* In the first blocksize of a packet */ | 172 /* In the first blocksize of a packet */ |
123 * find the length of the whole packet */ | 175 * find the length of the whole packet */ |
124 ret = read_packet_init(); | 176 ret = read_packet_init(); |
125 | 177 |
126 if (ret == DROPBEAR_FAILURE) { | 178 if (ret == DROPBEAR_FAILURE) { |
127 /* didn't read enough to determine the length */ | 179 /* didn't read enough to determine the length */ |
128 TRACE(("leave read_packet: packetinit done")) | 180 TRACE2(("leave read_packet: packetinit done")) |
129 return; | 181 return; |
130 } | 182 } |
131 } | 183 } |
132 | 184 |
133 /* Attempt to read the remainder of the packet, note that there | 185 /* Attempt to read the remainder of the packet, note that there |
145 ses.remoteclosed(); | 197 ses.remoteclosed(); |
146 } | 198 } |
147 | 199 |
148 if (len < 0) { | 200 if (len < 0) { |
149 if (errno == EINTR || errno == EAGAIN) { | 201 if (errno == EINTR || errno == EAGAIN) { |
150 TRACE(("leave read_packet: EINTR or EAGAIN")) | 202 TRACE2(("leave read_packet: EINTR or EAGAIN")) |
151 return; | 203 return; |
152 } else { | 204 } else { |
153 dropbear_exit("Error reading: %s", strerror(errno)); | 205 dropbear_exit("Error reading: %s", strerror(errno)); |
154 } | 206 } |
155 } | 207 } |
161 /* The whole packet has been read */ | 213 /* The whole packet has been read */ |
162 decrypt_packet(); | 214 decrypt_packet(); |
163 /* The main select() loop process_packet() to | 215 /* The main select() loop process_packet() to |
164 * handle the packet contents... */ | 216 * handle the packet contents... */ |
165 } | 217 } |
166 TRACE(("leave read_packet")) | 218 TRACE2(("leave read_packet")) |
167 } | 219 } |
168 | 220 |
169 /* Function used to read the initial portion of a packet, and determine the | 221 /* Function used to read the initial portion of a packet, and determine the |
170 * length. Only called during the first BLOCKSIZE of a packet. */ | 222 * length. Only called during the first BLOCKSIZE of a packet. */ |
171 /* Returns DROPBEAR_SUCCESS if the length is determined, | 223 /* Returns DROPBEAR_SUCCESS if the length is determined, |
195 if (slen == 0) { | 247 if (slen == 0) { |
196 ses.remoteclosed(); | 248 ses.remoteclosed(); |
197 } | 249 } |
198 if (slen < 0) { | 250 if (slen < 0) { |
199 if (errno == EINTR) { | 251 if (errno == EINTR) { |
200 TRACE(("leave read_packet_init: EINTR")) | 252 TRACE2(("leave read_packet_init: EINTR")) |
201 return DROPBEAR_FAILURE; | 253 return DROPBEAR_FAILURE; |
202 } | 254 } |
203 dropbear_exit("Error reading: %s", strerror(errno)); | 255 dropbear_exit("Error reading: %s", strerror(errno)); |
204 } | 256 } |
205 | 257 |
219 &ses.keys->recv.cipher_state) != CRYPT_OK) { | 271 &ses.keys->recv.cipher_state) != CRYPT_OK) { |
220 dropbear_exit("Error decrypting"); | 272 dropbear_exit("Error decrypting"); |
221 } | 273 } |
222 len = buf_getint(ses.readbuf) + 4 + macsize; | 274 len = buf_getint(ses.readbuf) + 4 + macsize; |
223 | 275 |
224 TRACE(("packet size is %d, block %d mac %d", len, blocksize, macsize)) | 276 TRACE2(("packet size is %d, block %d mac %d", len, blocksize, macsize)) |
225 | 277 |
226 | 278 |
227 /* check packet length */ | 279 /* check packet length */ |
228 if ((len > RECV_MAX_PACKET_LEN) || | 280 if ((len > RECV_MAX_PACKET_LEN) || |
229 (len < MIN_PACKET_LEN + macsize) || | 281 (len < MIN_PACKET_LEN + macsize) || |
245 unsigned char blocksize; | 297 unsigned char blocksize; |
246 unsigned char macsize; | 298 unsigned char macsize; |
247 unsigned int padlen; | 299 unsigned int padlen; |
248 unsigned int len; | 300 unsigned int len; |
249 | 301 |
250 TRACE(("enter decrypt_packet")) | 302 TRACE2(("enter decrypt_packet")) |
251 blocksize = ses.keys->recv.algo_crypt->blocksize; | 303 blocksize = ses.keys->recv.algo_crypt->blocksize; |
252 macsize = ses.keys->recv.algo_mac->hashsize; | 304 macsize = ses.keys->recv.algo_mac->hashsize; |
253 | 305 |
254 ses.kexstate.datarecv += ses.readbuf->len; | 306 ses.kexstate.datarecv += ses.readbuf->len; |
255 | 307 |
302 ses.readbuf = NULL; | 354 ses.readbuf = NULL; |
303 buf_setpos(ses.payload, 0); | 355 buf_setpos(ses.payload, 0); |
304 | 356 |
305 ses.recvseq++; | 357 ses.recvseq++; |
306 | 358 |
307 TRACE(("leave decrypt_packet")) | 359 TRACE2(("leave decrypt_packet")) |
308 } | 360 } |
309 | 361 |
310 /* Checks the mac at the end of a decrypted readbuf. | 362 /* Checks the mac at the end of a decrypted readbuf. |
311 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ | 363 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ |
312 static int checkmac() { | 364 static int checkmac() { |
401 ses.reply_queue_tail->next = new_item; | 453 ses.reply_queue_tail->next = new_item; |
402 } else { | 454 } else { |
403 ses.reply_queue_head = new_item; | 455 ses.reply_queue_head = new_item; |
404 } | 456 } |
405 ses.reply_queue_tail = new_item; | 457 ses.reply_queue_tail = new_item; |
406 TRACE(("leave enqueue_reply_packet")) | 458 TRACE2(("leave enqueue_reply_packet")) |
407 } | 459 } |
408 | 460 |
409 void maybe_flush_reply_queue() { | 461 void maybe_flush_reply_queue() { |
410 struct packetlist *tmp_item = NULL, *curr_item = NULL; | 462 struct packetlist *tmp_item = NULL, *curr_item = NULL; |
411 if (!ses.dataallowed) | 463 if (!ses.dataallowed) |
438 encrypted in-place. */ | 490 encrypted in-place. */ |
439 unsigned char packet_type; | 491 unsigned char packet_type; |
440 unsigned int len, encrypt_buf_size; | 492 unsigned int len, encrypt_buf_size; |
441 unsigned char mac_bytes[MAX_MAC_LEN]; | 493 unsigned char mac_bytes[MAX_MAC_LEN]; |
442 | 494 |
443 TRACE(("enter encrypt_packet()")) | 495 TRACE2(("enter encrypt_packet()")) |
444 | 496 |
445 buf_setpos(ses.writepayload, 0); | 497 buf_setpos(ses.writepayload, 0); |
446 packet_type = buf_getbyte(ses.writepayload); | 498 packet_type = buf_getbyte(ses.writepayload); |
447 buf_setpos(ses.writepayload, 0); | 499 buf_setpos(ses.writepayload, 0); |
448 | 500 |
449 TRACE(("encrypt_packet type is %d", packet_type)) | 501 TRACE2(("encrypt_packet type is %d", packet_type)) |
450 | 502 |
451 if ((!ses.dataallowed && !packet_is_okay_kex(packet_type)) | 503 if ((!ses.dataallowed && !packet_is_okay_kex(packet_type)) |
452 || ses.kexstate.sentnewkeys) { | 504 || ses.kexstate.sentnewkeys) { |
453 /* During key exchange only particular packets are allowed. | 505 /* During key exchange only particular packets are allowed. |
454 Since this packet_type isn't OK we just enqueue it to send | 506 Since this packet_type isn't OK we just enqueue it to send |
557 | 609 |
558 /* Update counts */ | 610 /* Update counts */ |
559 ses.kexstate.datatrans += writebuf->len; | 611 ses.kexstate.datatrans += writebuf->len; |
560 ses.transseq++; | 612 ses.transseq++; |
561 | 613 |
562 TRACE(("leave encrypt_packet()")) | 614 TRACE2(("leave encrypt_packet()")) |
563 } | 615 } |
564 | 616 |
565 | 617 |
566 /* Create the packet mac, and append H(seqno|clearbuf) to the output */ | 618 /* Create the packet mac, and append H(seqno|clearbuf) to the output */ |
567 /* output_mac must have ses.keys->trans.algo_mac->hashsize bytes. */ | 619 /* output_mac must have ses.keys->trans.algo_mac->hashsize bytes. */ |
570 unsigned char *output_mac) { | 622 unsigned char *output_mac) { |
571 unsigned char seqbuf[4]; | 623 unsigned char seqbuf[4]; |
572 unsigned long bufsize; | 624 unsigned long bufsize; |
573 hmac_state hmac; | 625 hmac_state hmac; |
574 | 626 |
575 TRACE(("enter writemac")) | |
576 | |
577 if (key_state->algo_mac->hashsize > 0) { | 627 if (key_state->algo_mac->hashsize > 0) { |
578 /* calculate the mac */ | 628 /* calculate the mac */ |
579 if (hmac_init(&hmac, | 629 if (hmac_init(&hmac, |
580 key_state->hash_index, | 630 key_state->hash_index, |
581 key_state->mackey, | 631 key_state->mackey, |
600 bufsize = MAX_MAC_LEN; | 650 bufsize = MAX_MAC_LEN; |
601 if (hmac_done(&hmac, output_mac, &bufsize) != CRYPT_OK) { | 651 if (hmac_done(&hmac, output_mac, &bufsize) != CRYPT_OK) { |
602 dropbear_exit("HMAC error"); | 652 dropbear_exit("HMAC error"); |
603 } | 653 } |
604 } | 654 } |
605 TRACE(("leave writemac")) | 655 TRACE2(("leave writemac")) |
606 } | 656 } |
607 | 657 |
608 #ifndef DISABLE_ZLIB | 658 #ifndef DISABLE_ZLIB |
609 /* compresses len bytes from src, outputting to dest (starting from the | 659 /* compresses len bytes from src, outputting to dest (starting from the |
610 * respective current positions. */ | 660 * respective current positions. */ |
611 static void buf_compress(buffer * dest, buffer * src, unsigned int len) { | 661 static void buf_compress(buffer * dest, buffer * src, unsigned int len) { |
612 | 662 |
613 unsigned int endpos = src->pos + len; | 663 unsigned int endpos = src->pos + len; |
614 int result; | 664 int result; |
615 | 665 |
616 TRACE(("enter buf_compress")) | 666 TRACE2(("enter buf_compress")) |
617 | 667 |
618 while (1) { | 668 while (1) { |
619 | 669 |
620 ses.keys->trans.zstream->avail_in = endpos - src->pos; | 670 ses.keys->trans.zstream->avail_in = endpos - src->pos; |
621 ses.keys->trans.zstream->next_in = | 671 ses.keys->trans.zstream->next_in = |
645 * unusual circumstances where the data grows in size after deflate(), | 695 * unusual circumstances where the data grows in size after deflate(), |
646 * but it is possible */ | 696 * but it is possible */ |
647 buf_resize(dest, dest->size + ZLIB_COMPRESS_INCR); | 697 buf_resize(dest, dest->size + ZLIB_COMPRESS_INCR); |
648 | 698 |
649 } | 699 } |
650 TRACE(("leave buf_compress")) | 700 TRACE2(("leave buf_compress")) |
651 } | 701 } |
652 #endif | 702 #endif |