Mercurial > dropbear
comparison packet.c @ 1069:2fa71c3b2827 pam
merge pam branch up to date
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 16 Mar 2015 21:34:05 +0800 |
parents | 16584026a1f0 |
children | 686cd3e8e13e |
comparison
equal
deleted
inserted
replaced
1068:9a6395ddb1b6 | 1069:2fa71c3b2827 |
---|---|
32 #include "kex.h" | 32 #include "kex.h" |
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 | 38 |
38 static int read_packet_init(); | 39 static int read_packet_init(); |
39 static void make_mac(unsigned int seqno, const struct key_context_directional * key_state, | 40 static void make_mac(unsigned int seqno, const struct key_context_directional * key_state, |
40 buffer * clear_buf, unsigned int clear_len, | 41 buffer * clear_buf, unsigned int clear_len, |
41 unsigned char *output_mac); | 42 unsigned char *output_mac); |
53 #endif | 54 #endif |
54 | 55 |
55 /* non-blocking function writing out a current encrypted packet */ | 56 /* non-blocking function writing out a current encrypted packet */ |
56 void write_packet() { | 57 void write_packet() { |
57 | 58 |
58 int len, written; | 59 ssize_t written; |
59 buffer * writebuf = NULL; | |
60 unsigned packet_type; | |
61 #ifdef HAVE_WRITEV | 60 #ifdef HAVE_WRITEV |
62 struct iovec *iov = NULL; | 61 struct iovec *iov = NULL; |
63 int i; | 62 int iov_count; |
64 struct Link *l; | |
65 int iov_max_count; | |
66 #endif | 63 #endif |
67 | 64 |
68 TRACE2(("enter write_packet")) | 65 TRACE2(("enter write_packet")) |
69 dropbear_assert(!isempty(&ses.writequeue)); | 66 dropbear_assert(!isempty(&ses.writequeue)); |
70 | 67 |
71 #if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV)) | 68 #if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV)) |
72 | 69 |
73 #ifndef IOV_MAX | 70 iov = packet_queue_to_iovec(&ses.writequeue, &iov_count); |
74 #define IOV_MAX UIO_MAXIOV | |
75 #endif | |
76 | |
77 /* Make sure the size of the iov is below the maximum allowed by the OS. */ | |
78 iov_max_count = ses.writequeue.count; | |
79 if (iov_max_count > IOV_MAX) | |
80 { | |
81 iov_max_count = IOV_MAX; | |
82 } | |
83 | |
84 iov = m_malloc(sizeof(*iov) * iov_max_count); | |
85 for (l = ses.writequeue.head, i = 0; l; l = l->link, i++) | |
86 { | |
87 writebuf = (buffer*)l->item; | |
88 packet_type = writebuf->data[writebuf->len-1]; | |
89 len = writebuf->len - 1 - writebuf->pos; | |
90 dropbear_assert(len > 0); | |
91 TRACE2(("write_packet writev #%d type %d len %d/%d", i, packet_type, | |
92 len, writebuf->len-1)) | |
93 iov[i].iov_base = buf_getptr(writebuf, len); | |
94 iov[i].iov_len = len; | |
95 } | |
96 /* This may return EAGAIN. The main loop sometimes | 71 /* This may return EAGAIN. The main loop sometimes |
97 calls write_packet() without bothering to test with select() since | 72 calls write_packet() without bothering to test with select() since |
98 it's likely to be necessary */ | 73 it's likely to be necessary */ |
99 written = writev(ses.sock_out, iov, iov_max_count); | 74 written = writev(ses.sock_out, iov, iov_count); |
100 if (written < 0) { | 75 if (written < 0) { |
101 if (errno == EINTR || errno == EAGAIN) { | 76 if (errno == EINTR || errno == EAGAIN) { |
77 TRACE2(("leave write_packet: EINTR")) | |
102 m_free(iov); | 78 m_free(iov); |
103 TRACE2(("leave write_packet: EINTR")) | |
104 return; | 79 return; |
105 } else { | 80 } else { |
106 dropbear_exit("Error writing: %s", strerror(errno)); | 81 dropbear_exit("Error writing: %s", strerror(errno)); |
107 } | 82 } |
108 } | 83 } |
84 m_free(iov); | |
85 | |
86 packet_queue_consume(&ses.writequeue, written); | |
109 | 87 |
110 if (written == 0) { | 88 if (written == 0) { |
111 ses.remoteclosed(); | 89 ses.remoteclosed(); |
112 } | 90 } |
113 | 91 |
114 while (written > 0) { | |
115 writebuf = (buffer*)examine(&ses.writequeue); | |
116 len = writebuf->len - 1 - writebuf->pos; | |
117 if (len > written) { | |
118 /* partial buffer write */ | |
119 buf_incrpos(writebuf, written); | |
120 written = 0; | |
121 } else { | |
122 written -= len; | |
123 dequeue(&ses.writequeue); | |
124 buf_free(writebuf); | |
125 } | |
126 } | |
127 | |
128 m_free(iov); | |
129 #else /* No writev () */ | 92 #else /* No writev () */ |
130 /* Get the next buffer in the queue of encrypted packets to write*/ | 93 /* Get the next buffer in the queue of encrypted packets to write*/ |
131 writebuf = (buffer*)examine(&ses.writequeue); | 94 writebuf = (buffer*)examine(&ses.writequeue); |
132 | 95 |
133 /* The last byte of the buffer is not to be transmitted, but is | 96 /* The last byte of the buffer is not to be transmitted, but is |
281 &ses.keys->recv.cipher_state) != CRYPT_OK) { | 244 &ses.keys->recv.cipher_state) != CRYPT_OK) { |
282 dropbear_exit("Error decrypting"); | 245 dropbear_exit("Error decrypting"); |
283 } | 246 } |
284 len = buf_getint(ses.readbuf) + 4 + macsize; | 247 len = buf_getint(ses.readbuf) + 4 + macsize; |
285 | 248 |
286 TRACE2(("packet size is %d, block %d mac %d", len, blocksize, macsize)) | 249 TRACE2(("packet size is %u, block %u mac %u", len, blocksize, macsize)) |
287 | 250 |
288 | 251 |
289 /* check packet length */ | 252 /* check packet length */ |
290 if ((len > RECV_MAX_PACKET_LEN) || | 253 if ((len > RECV_MAX_PACKET_LEN) || |
291 (len < MIN_PACKET_LEN + macsize) || | 254 (len < MIN_PACKET_LEN + macsize) || |
292 ((len - macsize) % blocksize != 0)) { | 255 ((len - macsize) % blocksize != 0)) { |
293 dropbear_exit("Integrity error (bad packet size %d)", len); | 256 dropbear_exit("Integrity error (bad packet size %u)", len); |
294 } | 257 } |
295 | 258 |
296 if (len > ses.readbuf->size) { | 259 if (len > ses.readbuf->size) { |
297 buf_resize(ses.readbuf, len); | 260 ses.readbuf = buf_resize(ses.readbuf, len); |
298 } | 261 } |
299 buf_setlen(ses.readbuf, len); | 262 buf_setlen(ses.readbuf, len); |
300 buf_setpos(ses.readbuf, blocksize); | 263 buf_setpos(ses.readbuf, blocksize); |
301 return DROPBEAR_SUCCESS; | 264 return DROPBEAR_SUCCESS; |
302 } | 265 } |
340 | 303 |
341 /* payload length */ | 304 /* payload length */ |
342 /* - 4 - 1 is for LEN and PADLEN values */ | 305 /* - 4 - 1 is for LEN and PADLEN values */ |
343 len = ses.readbuf->len - padlen - 4 - 1 - macsize; | 306 len = ses.readbuf->len - padlen - 4 - 1 - macsize; |
344 if ((len > RECV_MAX_PAYLOAD_LEN+ZLIB_COMPRESS_EXPANSION) || (len < 1)) { | 307 if ((len > RECV_MAX_PAYLOAD_LEN+ZLIB_COMPRESS_EXPANSION) || (len < 1)) { |
345 dropbear_exit("Bad packet size %d", len); | 308 dropbear_exit("Bad packet size %u", len); |
346 } | 309 } |
347 | 310 |
348 buf_setpos(ses.readbuf, PACKET_PAYLOAD_OFF); | 311 buf_setpos(ses.readbuf, PACKET_PAYLOAD_OFF); |
349 | 312 |
350 #ifndef DISABLE_ZLIB | 313 #ifndef DISABLE_ZLIB |
351 if (is_compress_recv()) { | 314 if (is_compress_recv()) { |
352 /* decompress */ | 315 /* decompress */ |
353 ses.payload = buf_decompress(ses.readbuf, len); | 316 ses.payload = buf_decompress(ses.readbuf, len); |
317 buf_setpos(ses.payload, 0); | |
318 ses.payload_beginning = 0; | |
319 buf_free(ses.readbuf); | |
354 } else | 320 } else |
355 #endif | 321 #endif |
356 { | 322 { |
323 ses.payload = ses.readbuf; | |
324 ses.payload_beginning = ses.payload->pos; | |
325 buf_setlen(ses.payload, ses.payload->pos + len); | |
357 /* copy payload */ | 326 /* copy payload */ |
358 ses.payload = buf_new(len); | 327 //ses.payload = buf_new(len); |
359 memcpy(ses.payload->data, buf_getptr(ses.readbuf, len), len); | 328 //memcpy(ses.payload->data, buf_getptr(ses.readbuf, len), len); |
360 buf_incrlen(ses.payload, len); | 329 //buf_incrlen(ses.payload, len); |
361 } | 330 } |
362 | |
363 buf_free(ses.readbuf); | |
364 ses.readbuf = NULL; | 331 ses.readbuf = NULL; |
365 buf_setpos(ses.payload, 0); | |
366 | 332 |
367 ses.recvseq++; | 333 ses.recvseq++; |
368 | 334 |
369 TRACE2(("leave decrypt_packet")) | 335 TRACE2(("leave decrypt_packet")) |
370 } | 336 } |
433 /* Already been increased as large as it can go, | 399 /* Already been increased as large as it can go, |
434 * yet didn't finish up the decompression */ | 400 * yet didn't finish up the decompression */ |
435 dropbear_exit("bad packet, oversized decompressed"); | 401 dropbear_exit("bad packet, oversized decompressed"); |
436 } | 402 } |
437 new_size = MIN(RECV_MAX_PAYLOAD_LEN, ret->size + ZLIB_DECOMPRESS_INCR); | 403 new_size = MIN(RECV_MAX_PAYLOAD_LEN, ret->size + ZLIB_DECOMPRESS_INCR); |
438 buf_resize(ret, new_size); | 404 ret = buf_resize(ret, new_size); |
439 } | 405 } |
440 } | 406 } |
441 } | 407 } |
442 #endif | 408 #endif |
443 | 409 |
672 TRACE2(("leave writemac")) | 638 TRACE2(("leave writemac")) |
673 } | 639 } |
674 | 640 |
675 #ifndef DISABLE_ZLIB | 641 #ifndef DISABLE_ZLIB |
676 /* compresses len bytes from src, outputting to dest (starting from the | 642 /* compresses len bytes from src, outputting to dest (starting from the |
677 * respective current positions. */ | 643 * respective current positions. dest must have sufficient space, |
644 * len+ZLIB_COMPRESS_EXPANSION */ | |
678 static void buf_compress(buffer * dest, buffer * src, unsigned int len) { | 645 static void buf_compress(buffer * dest, buffer * src, unsigned int len) { |
679 | 646 |
680 unsigned int endpos = src->pos + len; | 647 unsigned int endpos = src->pos + len; |
681 int result; | 648 int result; |
682 | 649 |
683 TRACE2(("enter buf_compress")) | 650 TRACE2(("enter buf_compress")) |
684 | 651 |
685 while (1) { | 652 dropbear_assert(dest->size - dest->pos >= len+ZLIB_COMPRESS_EXPANSION); |
686 | 653 |
687 ses.keys->trans.zstream->avail_in = endpos - src->pos; | 654 ses.keys->trans.zstream->avail_in = endpos - src->pos; |
688 ses.keys->trans.zstream->next_in = | 655 ses.keys->trans.zstream->next_in = |
689 buf_getptr(src, ses.keys->trans.zstream->avail_in); | 656 buf_getptr(src, ses.keys->trans.zstream->avail_in); |
690 | 657 |
691 ses.keys->trans.zstream->avail_out = dest->size - dest->pos; | 658 ses.keys->trans.zstream->avail_out = dest->size - dest->pos; |
692 ses.keys->trans.zstream->next_out = | 659 ses.keys->trans.zstream->next_out = |
693 buf_getwriteptr(dest, ses.keys->trans.zstream->avail_out); | 660 buf_getwriteptr(dest, ses.keys->trans.zstream->avail_out); |
694 | 661 |
695 result = deflate(ses.keys->trans.zstream, Z_SYNC_FLUSH); | 662 result = deflate(ses.keys->trans.zstream, Z_SYNC_FLUSH); |
696 | 663 |
697 buf_setpos(src, endpos - ses.keys->trans.zstream->avail_in); | 664 buf_setpos(src, endpos - ses.keys->trans.zstream->avail_in); |
698 buf_setlen(dest, dest->size - ses.keys->trans.zstream->avail_out); | 665 buf_setlen(dest, dest->size - ses.keys->trans.zstream->avail_out); |
699 buf_setpos(dest, dest->len); | 666 buf_setpos(dest, dest->len); |
700 | 667 |
701 if (result != Z_OK) { | 668 if (result != Z_OK) { |
702 dropbear_exit("zlib error"); | 669 dropbear_exit("zlib error"); |
703 } | 670 } |
704 | 671 |
705 if (ses.keys->trans.zstream->avail_in == 0) { | 672 /* fails if destination buffer wasn't large enough */ |
706 break; | 673 dropbear_assert(ses.keys->trans.zstream->avail_in == 0); |
707 } | |
708 | |
709 dropbear_assert(ses.keys->trans.zstream->avail_out == 0); | |
710 | |
711 /* the buffer has been filled, we must extend. This only happens in | |
712 * unusual circumstances where the data grows in size after deflate(), | |
713 * but it is possible */ | |
714 buf_resize(dest, dest->size + ZLIB_COMPRESS_EXPANSION); | |
715 | |
716 } | |
717 TRACE2(("leave buf_compress")) | 674 TRACE2(("leave buf_compress")) |
718 } | 675 } |
719 #endif | 676 #endif |