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