Mercurial > dropbear
comparison packet.c @ 773:a9f2a6ae4eb5
merge
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sun, 14 Apr 2013 22:49:19 +0800 |
parents | d63ef1e211ea |
children | 0bf76f54de6f |
comparison
equal
deleted
inserted
replaced
772:7fc0aeada79c | 773:a9f2a6ae4eb5 |
---|---|
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 TRACE2(("write_packet writev #%d type %d len %d/%d", i, packet_type, | |
78 len, writebuf->len-1)) | |
79 iov[i].iov_base = buf_getptr(writebuf, len); | |
80 iov[i].iov_len = len; | |
81 } | |
82 written = writev(ses.sock_out, iov, ses.writequeue.count); | |
83 if (written < 0) { | |
84 if (errno == EINTR) { | |
85 m_free(iov); | |
86 TRACE2(("leave writepacket: EINTR")) | |
87 return; | |
88 } else { | |
89 dropbear_exit("Error writing"); | |
90 } | |
91 } | |
92 | |
93 if (written == 0) { | |
94 ses.remoteclosed(); | |
95 } | |
96 | |
97 while (written > 0) { | |
98 writebuf = (buffer*)examine(&ses.writequeue); | |
99 len = writebuf->len - 1 - writebuf->pos; | |
100 if (len > written) { | |
101 // partial buffer write | |
102 buf_incrpos(writebuf, written); | |
103 written = 0; | |
104 } else { | |
105 written -= len; | |
106 dequeue(&ses.writequeue); | |
107 buf_free(writebuf); | |
108 } | |
109 } | |
110 | |
111 m_free(iov); | |
112 | |
113 #else | |
62 /* Get the next buffer in the queue of encrypted packets to write*/ | 114 /* Get the next buffer in the queue of encrypted packets to write*/ |
63 writebuf = (buffer*)examine(&ses.writequeue); | 115 writebuf = (buffer*)examine(&ses.writequeue); |
64 | 116 |
65 /* The last byte of the buffer is not to be transmitted, but is | 117 /* The last byte of the buffer is not to be transmitted, but is |
66 * a cleartext packet_type indicator */ | 118 * a cleartext packet_type indicator */ |
70 /* Try to write as much as possible */ | 122 /* Try to write as much as possible */ |
71 written = write(ses.sock_out, buf_getptr(writebuf, len), len); | 123 written = write(ses.sock_out, buf_getptr(writebuf, len), len); |
72 | 124 |
73 if (written < 0) { | 125 if (written < 0) { |
74 if (errno == EINTR) { | 126 if (errno == EINTR) { |
75 TRACE(("leave writepacket: EINTR")) | 127 TRACE2(("leave writepacket: EINTR")) |
76 return; | 128 return; |
77 } else { | 129 } else { |
78 dropbear_exit("Error writing"); | 130 dropbear_exit("Error writing"); |
79 } | 131 } |
80 } | 132 } |
81 | 133 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 | 134 |
89 if (written == 0) { | 135 if (written == 0) { |
90 ses.remoteclosed(); | 136 ses.remoteclosed(); |
91 } | 137 } |
92 | 138 |
98 } else { | 144 } else { |
99 /* More packet left to write, leave it in the queue for later */ | 145 /* More packet left to write, leave it in the queue for later */ |
100 buf_incrpos(writebuf, written); | 146 buf_incrpos(writebuf, written); |
101 } | 147 } |
102 | 148 |
103 TRACE(("leave write_packet")) | 149 #endif |
150 now = time(NULL); | |
151 ses.last_trx_packet_time = now; | |
152 | |
153 if (!all_ignore) { | |
154 ses.last_packet_time = now; | |
155 } | |
156 | |
157 TRACE2(("leave write_packet")) | |
104 } | 158 } |
105 | 159 |
106 /* Non-blocking function reading available portion of a packet into the | 160 /* Non-blocking function reading available portion of a packet into the |
107 * ses's buffer, decrypting the length if encrypted, decrypting the | 161 * ses's buffer, decrypting the length if encrypted, decrypting the |
108 * full portion if possible */ | 162 * full portion if possible */ |
110 | 164 |
111 int len; | 165 int len; |
112 unsigned int maxlen; | 166 unsigned int maxlen; |
113 unsigned char blocksize; | 167 unsigned char blocksize; |
114 | 168 |
115 TRACE(("enter read_packet")) | 169 TRACE2(("enter read_packet")) |
116 blocksize = ses.keys->recv.algo_crypt->blocksize; | 170 blocksize = ses.keys->recv.algo_crypt->blocksize; |
117 | 171 |
118 if (ses.readbuf == NULL || ses.readbuf->len < blocksize) { | 172 if (ses.readbuf == NULL || ses.readbuf->len < blocksize) { |
119 int ret; | 173 int ret; |
120 /* In the first blocksize of a packet */ | 174 /* In the first blocksize of a packet */ |
123 * find the length of the whole packet */ | 177 * find the length of the whole packet */ |
124 ret = read_packet_init(); | 178 ret = read_packet_init(); |
125 | 179 |
126 if (ret == DROPBEAR_FAILURE) { | 180 if (ret == DROPBEAR_FAILURE) { |
127 /* didn't read enough to determine the length */ | 181 /* didn't read enough to determine the length */ |
128 TRACE(("leave read_packet: packetinit done")) | 182 TRACE2(("leave read_packet: packetinit done")) |
129 return; | 183 return; |
130 } | 184 } |
131 } | 185 } |
132 | 186 |
133 /* Attempt to read the remainder of the packet, note that there | 187 /* Attempt to read the remainder of the packet, note that there |
145 ses.remoteclosed(); | 199 ses.remoteclosed(); |
146 } | 200 } |
147 | 201 |
148 if (len < 0) { | 202 if (len < 0) { |
149 if (errno == EINTR || errno == EAGAIN) { | 203 if (errno == EINTR || errno == EAGAIN) { |
150 TRACE(("leave read_packet: EINTR or EAGAIN")) | 204 TRACE2(("leave read_packet: EINTR or EAGAIN")) |
151 return; | 205 return; |
152 } else { | 206 } else { |
153 dropbear_exit("Error reading: %s", strerror(errno)); | 207 dropbear_exit("Error reading: %s", strerror(errno)); |
154 } | 208 } |
155 } | 209 } |
161 /* The whole packet has been read */ | 215 /* The whole packet has been read */ |
162 decrypt_packet(); | 216 decrypt_packet(); |
163 /* The main select() loop process_packet() to | 217 /* The main select() loop process_packet() to |
164 * handle the packet contents... */ | 218 * handle the packet contents... */ |
165 } | 219 } |
166 TRACE(("leave read_packet")) | 220 TRACE2(("leave read_packet")) |
167 } | 221 } |
168 | 222 |
169 /* Function used to read the initial portion of a packet, and determine the | 223 /* Function used to read the initial portion of a packet, and determine the |
170 * length. Only called during the first BLOCKSIZE of a packet. */ | 224 * length. Only called during the first BLOCKSIZE of a packet. */ |
171 /* Returns DROPBEAR_SUCCESS if the length is determined, | 225 /* Returns DROPBEAR_SUCCESS if the length is determined, |
195 if (slen == 0) { | 249 if (slen == 0) { |
196 ses.remoteclosed(); | 250 ses.remoteclosed(); |
197 } | 251 } |
198 if (slen < 0) { | 252 if (slen < 0) { |
199 if (errno == EINTR) { | 253 if (errno == EINTR) { |
200 TRACE(("leave read_packet_init: EINTR")) | 254 TRACE2(("leave read_packet_init: EINTR")) |
201 return DROPBEAR_FAILURE; | 255 return DROPBEAR_FAILURE; |
202 } | 256 } |
203 dropbear_exit("Error reading: %s", strerror(errno)); | 257 dropbear_exit("Error reading: %s", strerror(errno)); |
204 } | 258 } |
205 | 259 |
219 &ses.keys->recv.cipher_state) != CRYPT_OK) { | 273 &ses.keys->recv.cipher_state) != CRYPT_OK) { |
220 dropbear_exit("Error decrypting"); | 274 dropbear_exit("Error decrypting"); |
221 } | 275 } |
222 len = buf_getint(ses.readbuf) + 4 + macsize; | 276 len = buf_getint(ses.readbuf) + 4 + macsize; |
223 | 277 |
224 TRACE(("packet size is %d, block %d mac %d", len, blocksize, macsize)) | 278 TRACE2(("packet size is %d, block %d mac %d", len, blocksize, macsize)) |
225 | 279 |
226 | 280 |
227 /* check packet length */ | 281 /* check packet length */ |
228 if ((len > RECV_MAX_PACKET_LEN) || | 282 if ((len > RECV_MAX_PACKET_LEN) || |
229 (len < MIN_PACKET_LEN + macsize) || | 283 (len < MIN_PACKET_LEN + macsize) || |
245 unsigned char blocksize; | 299 unsigned char blocksize; |
246 unsigned char macsize; | 300 unsigned char macsize; |
247 unsigned int padlen; | 301 unsigned int padlen; |
248 unsigned int len; | 302 unsigned int len; |
249 | 303 |
250 TRACE(("enter decrypt_packet")) | 304 TRACE2(("enter decrypt_packet")) |
251 blocksize = ses.keys->recv.algo_crypt->blocksize; | 305 blocksize = ses.keys->recv.algo_crypt->blocksize; |
252 macsize = ses.keys->recv.algo_mac->hashsize; | 306 macsize = ses.keys->recv.algo_mac->hashsize; |
253 | 307 |
254 ses.kexstate.datarecv += ses.readbuf->len; | 308 ses.kexstate.datarecv += ses.readbuf->len; |
255 | 309 |
302 ses.readbuf = NULL; | 356 ses.readbuf = NULL; |
303 buf_setpos(ses.payload, 0); | 357 buf_setpos(ses.payload, 0); |
304 | 358 |
305 ses.recvseq++; | 359 ses.recvseq++; |
306 | 360 |
307 TRACE(("leave decrypt_packet")) | 361 TRACE2(("leave decrypt_packet")) |
308 } | 362 } |
309 | 363 |
310 /* Checks the mac at the end of a decrypted readbuf. | 364 /* Checks the mac at the end of a decrypted readbuf. |
311 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ | 365 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ |
312 static int checkmac() { | 366 static int checkmac() { |
313 | 367 |
314 unsigned char mac_bytes[MAX_MAC_LEN]; | 368 unsigned char mac_bytes[MAX_MAC_LEN]; |
315 unsigned int mac_size, contents_len; | 369 unsigned int mac_size, contents_len; |
316 | 370 |
317 mac_size = ses.keys->trans.algo_mac->hashsize; | 371 mac_size = ses.keys->recv.algo_mac->hashsize; |
318 contents_len = ses.readbuf->len - mac_size; | 372 contents_len = ses.readbuf->len - mac_size; |
319 | 373 |
320 buf_setpos(ses.readbuf, 0); | 374 buf_setpos(ses.readbuf, 0); |
321 make_mac(ses.recvseq, &ses.keys->recv, ses.readbuf, contents_len, mac_bytes); | 375 make_mac(ses.recvseq, &ses.keys->recv, ses.readbuf, contents_len, mac_bytes); |
322 | 376 |
401 ses.reply_queue_tail->next = new_item; | 455 ses.reply_queue_tail->next = new_item; |
402 } else { | 456 } else { |
403 ses.reply_queue_head = new_item; | 457 ses.reply_queue_head = new_item; |
404 } | 458 } |
405 ses.reply_queue_tail = new_item; | 459 ses.reply_queue_tail = new_item; |
406 TRACE(("leave enqueue_reply_packet")) | |
407 } | 460 } |
408 | 461 |
409 void maybe_flush_reply_queue() { | 462 void maybe_flush_reply_queue() { |
410 struct packetlist *tmp_item = NULL, *curr_item = NULL; | 463 struct packetlist *tmp_item = NULL, *curr_item = NULL; |
411 if (!ses.dataallowed) | 464 if (!ses.dataallowed) |
438 encrypted in-place. */ | 491 encrypted in-place. */ |
439 unsigned char packet_type; | 492 unsigned char packet_type; |
440 unsigned int len, encrypt_buf_size; | 493 unsigned int len, encrypt_buf_size; |
441 unsigned char mac_bytes[MAX_MAC_LEN]; | 494 unsigned char mac_bytes[MAX_MAC_LEN]; |
442 | 495 |
443 TRACE(("enter encrypt_packet()")) | 496 TRACE2(("enter encrypt_packet()")) |
444 | 497 |
445 buf_setpos(ses.writepayload, 0); | 498 buf_setpos(ses.writepayload, 0); |
446 packet_type = buf_getbyte(ses.writepayload); | 499 packet_type = buf_getbyte(ses.writepayload); |
447 buf_setpos(ses.writepayload, 0); | 500 buf_setpos(ses.writepayload, 0); |
448 | 501 |
449 TRACE(("encrypt_packet type is %d", packet_type)) | 502 TRACE2(("encrypt_packet type is %d", packet_type)) |
450 | 503 |
451 if ((!ses.dataallowed && !packet_is_okay_kex(packet_type)) | 504 if ((!ses.dataallowed && !packet_is_okay_kex(packet_type))) { |
452 || 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 |
455 after the KEX, see maybe_flush_reply_queue */ | 507 after the KEX, see maybe_flush_reply_queue */ |
456 | |
457 /* We also enqueue packets here when we have sent a MSG_NEWKEYS | |
458 * packet but are yet to received one. For simplicity we just switch | |
459 * over all the keys at once. This is the 'ses.kexstate.sentnewkeys' | |
460 * case. */ | |
461 enqueue_reply_packet(); | 508 enqueue_reply_packet(); |
462 return; | 509 return; |
463 } | 510 } |
464 | 511 |
465 blocksize = ses.keys->trans.algo_crypt->blocksize; | 512 blocksize = ses.keys->trans.algo_crypt->blocksize; |
557 | 604 |
558 /* Update counts */ | 605 /* Update counts */ |
559 ses.kexstate.datatrans += writebuf->len; | 606 ses.kexstate.datatrans += writebuf->len; |
560 ses.transseq++; | 607 ses.transseq++; |
561 | 608 |
562 TRACE(("leave encrypt_packet()")) | 609 TRACE2(("leave encrypt_packet()")) |
563 } | 610 } |
564 | 611 |
565 | 612 |
566 /* Create the packet mac, and append H(seqno|clearbuf) to the output */ | 613 /* Create the packet mac, and append H(seqno|clearbuf) to the output */ |
567 /* output_mac must have ses.keys->trans.algo_mac->hashsize bytes. */ | 614 /* output_mac must have ses.keys->trans.algo_mac->hashsize bytes. */ |
570 unsigned char *output_mac) { | 617 unsigned char *output_mac) { |
571 unsigned char seqbuf[4]; | 618 unsigned char seqbuf[4]; |
572 unsigned long bufsize; | 619 unsigned long bufsize; |
573 hmac_state hmac; | 620 hmac_state hmac; |
574 | 621 |
575 TRACE(("enter writemac")) | |
576 | |
577 if (key_state->algo_mac->hashsize > 0) { | 622 if (key_state->algo_mac->hashsize > 0) { |
578 /* calculate the mac */ | 623 /* calculate the mac */ |
579 if (hmac_init(&hmac, | 624 if (hmac_init(&hmac, |
580 key_state->hash_index, | 625 key_state->hash_index, |
581 key_state->mackey, | 626 key_state->mackey, |
600 bufsize = MAX_MAC_LEN; | 645 bufsize = MAX_MAC_LEN; |
601 if (hmac_done(&hmac, output_mac, &bufsize) != CRYPT_OK) { | 646 if (hmac_done(&hmac, output_mac, &bufsize) != CRYPT_OK) { |
602 dropbear_exit("HMAC error"); | 647 dropbear_exit("HMAC error"); |
603 } | 648 } |
604 } | 649 } |
605 TRACE(("leave writemac")) | 650 TRACE2(("leave writemac")) |
606 } | 651 } |
607 | 652 |
608 #ifndef DISABLE_ZLIB | 653 #ifndef DISABLE_ZLIB |
609 /* compresses len bytes from src, outputting to dest (starting from the | 654 /* compresses len bytes from src, outputting to dest (starting from the |
610 * respective current positions. */ | 655 * respective current positions. */ |
611 static void buf_compress(buffer * dest, buffer * src, unsigned int len) { | 656 static void buf_compress(buffer * dest, buffer * src, unsigned int len) { |
612 | 657 |
613 unsigned int endpos = src->pos + len; | 658 unsigned int endpos = src->pos + len; |
614 int result; | 659 int result; |
615 | 660 |
616 TRACE(("enter buf_compress")) | 661 TRACE2(("enter buf_compress")) |
617 | 662 |
618 while (1) { | 663 while (1) { |
619 | 664 |
620 ses.keys->trans.zstream->avail_in = endpos - src->pos; | 665 ses.keys->trans.zstream->avail_in = endpos - src->pos; |
621 ses.keys->trans.zstream->next_in = | 666 ses.keys->trans.zstream->next_in = |
645 * unusual circumstances where the data grows in size after deflate(), | 690 * unusual circumstances where the data grows in size after deflate(), |
646 * but it is possible */ | 691 * but it is possible */ |
647 buf_resize(dest, dest->size + ZLIB_COMPRESS_INCR); | 692 buf_resize(dest, dest->size + ZLIB_COMPRESS_INCR); |
648 | 693 |
649 } | 694 } |
650 TRACE(("leave buf_compress")) | 695 TRACE2(("leave buf_compress")) |
651 } | 696 } |
652 #endif | 697 #endif |