diff options
author | Matt Johnston <matt@ucc.asn.au> | 2008-09-14 06:47:51 +0000 |
---|---|---|
committer | Matt Johnston <matt@ucc.asn.au> | 2008-09-14 06:47:51 +0000 |
commit | 1c72a35ddb79eede31657a450b8ba35aed24c79e (patch) | |
tree | e6f6ae8bac919e2696678d7a680dce410a1ea91a /packet.c | |
parent | cdbe853595d1ba06be4127d86c60a9bc2e9e3545 (diff) | |
parent | 460bf4382257a262fda862f66d6fe97c749f5bb7 (diff) |
propagate from branch 'au.asn.ucc.matt.dropbear' (head f21045c791002d81fc6b8dde6537ea481e513eb2)
to branch 'au.asn.ucc.matt.dropbear.dbclient-netcat-alike' (head d1f69334581dc4c35f9ca16aa5355074c9dd315d)
--HG--
branch : dbclient-netcat-alike
extra : convert_revision : 22bbe895accc3995b48f07b556e45d546ff1ce5d
Diffstat (limited to 'packet.c')
-rw-r--r-- | packet.c | 76 |
1 files changed, 69 insertions, 7 deletions
@@ -71,6 +71,8 @@ void write_packet() { dropbear_exit("error writing"); } } + + ses.last_packet_time = time(NULL); if (written == 0) { ses.remoteclosed(); @@ -212,7 +214,7 @@ static void read_packet_init() { buf_setpos(ses.readbuf, blocksize); /* check packet length */ - if ((len > MAX_PACKET_LEN) || + if ((len > RECV_MAX_PACKET_LEN) || (len < MIN_PACKET_LEN + macsize) || ((len - macsize) % blocksize != 0)) { dropbear_exit("bad packet size %d", len); @@ -281,7 +283,7 @@ void decrypt_packet() { /* payload length */ /* - 4 - 1 is for LEN and PADLEN values */ len = ses.decryptreadbuf->len - padlen - 4 - 1; - if ((len > MAX_PAYLOAD_LEN) || (len < 1)) { + if ((len > RECV_MAX_PAYLOAD_LEN) || (len < 1)) { dropbear_exit("bad packet size"); } @@ -403,7 +405,60 @@ static buffer* buf_decompress(buffer* buf, unsigned int len) { #endif +/* returns 1 if the packet is a valid type during kex (see 7.1 of rfc4253) */ +static int packet_is_okay_kex(unsigned char type) { + if (type >= SSH_MSG_USERAUTH_REQUEST) { + return 0; + } + if (type == SSH_MSG_SERVICE_REQUEST || type == SSH_MSG_SERVICE_ACCEPT) { + return 0; + } + if (type == SSH_MSG_KEXINIT) { + /* XXX should this die horribly if !dataallowed ?? */ + return 0; + } + return 1; +} + +static void enqueue_reply_packet() { + struct packetlist * new_item = NULL; + new_item = m_malloc(sizeof(struct packetlist)); + new_item->next = NULL; + + new_item->payload = buf_newcopy(ses.writepayload); + buf_setpos(ses.writepayload, 0); + buf_setlen(ses.writepayload, 0); + + if (ses.reply_queue_tail) { + ses.reply_queue_tail->next = new_item; + } else { + ses.reply_queue_head = new_item; + } + ses.reply_queue_tail = new_item; + TRACE(("leave enqueue_reply_packet")) +} +void maybe_flush_reply_queue() { + struct packetlist *tmp_item = NULL, *curr_item = NULL; + if (!ses.dataallowed) + { + TRACE(("maybe_empty_reply_queue - no data allowed")) + return; + } + + for (curr_item = ses.reply_queue_head; curr_item; ) { + CHECKCLEARTOWRITE(); + buf_putbytes(ses.writepayload, + curr_item->payload->data, curr_item->payload->len); + + buf_free(curr_item->payload); + tmp_item = curr_item; + curr_item = curr_item->next; + m_free(tmp_item); + encrypt_packet(); + } + ses.reply_queue_head = ses.reply_queue_tail = NULL; +} /* encrypt the writepayload, putting into writebuf, ready for write_packet() * to put on the wire */ @@ -413,9 +468,20 @@ void encrypt_packet() { unsigned char blocksize, macsize; buffer * writebuf; /* the packet which will go on the wire */ buffer * clearwritebuf; /* unencrypted, possibly compressed */ + unsigned char type; + type = ses.writepayload->data[0]; TRACE(("enter encrypt_packet()")) - TRACE(("encrypt_packet type is %d", ses.writepayload->data[0])) + TRACE(("encrypt_packet type is %d", type)) + + if (!ses.dataallowed && !packet_is_okay_kex(type)) { + /* During key exchange only particular packets are allowed. + Since this type isn't OK we just enqueue it to send + after the KEX, see maybe_flush_reply_queue */ + enqueue_reply_packet(); + return; + } + blocksize = ses.keys->trans_algo_crypt->blocksize; macsize = ses.keys->trans_algo_mac->hashsize; @@ -446,10 +512,6 @@ void encrypt_packet() { } /* finished with payload */ - buf_burn(ses.writepayload); /* XXX This is probably a good idea, and isn't - _that_ likely to hurt performance too badly. - Buffers can have cleartext passwords etc, or - other sensitive data */ buf_setpos(ses.writepayload, 0); buf_setlen(ses.writepayload, 0); |