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