From 049fcf1ac572e1a13dc1281c26bbf3512c533fb7 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Mon, 29 Sep 2008 02:23:04 +0000 Subject: Add support for zlib@openssh.com delayed compression. Are still advertising 'zlib' for the server, need to allow delayed-only as an option --HG-- extra : convert_revision : 319df675cc3c9b35a10b7d8357c94f33fdab1a46 --- cli-auth.c | 2 ++ common-algo.c | 1 + common-kex.c | 23 +++++++++++++++++++---- dbclient.1 | 1 + kex.h | 5 +++++ packet.c | 13 +++++++------ session.h | 2 ++ svr-auth.c | 2 ++ sysoptions.h | 1 + 9 files changed, 40 insertions(+), 10 deletions(-) diff --git a/cli-auth.c b/cli-auth.c index 1024538..731d769 100644 --- a/cli-auth.c +++ b/cli-auth.c @@ -229,6 +229,8 @@ void recv_msg_userauth_failure() { void recv_msg_userauth_success() { TRACE(("received msg_userauth_success")) + /* Note: in delayed-zlib mode, setting authdone here + * will enable compression in the transport layer */ ses.authstate.authdone = 1; cli_ses.state = USERAUTH_SUCCESS_RCVD; cli_ses.lastauthtype = AUTH_TYPE_NONE; diff --git a/common-algo.c b/common-algo.c index 21ac96a..d38c5e5 100644 --- a/common-algo.c +++ b/common-algo.c @@ -124,6 +124,7 @@ algo_type sshhashes[] = { algo_type sshcompress[] = { #ifndef DISABLE_ZLIB {"zlib", DROPBEAR_COMP_ZLIB, NULL, 1}, + {"zlib@openssh.com", DROPBEAR_COMP_ZLIB_DELAY, NULL, 1}, #endif {"none", DROPBEAR_COMP_NONE, NULL, 1}, {NULL, 0, NULL, 0} diff --git a/common-kex.c b/common-kex.c index e9c655d..80eb2a1 100644 --- a/common-kex.c +++ b/common-kex.c @@ -331,12 +331,26 @@ void gen_new_keys() { } #ifndef DISABLE_ZLIB + +int is_compress_trans() { + return ses.keys->trans_algo_comp == DROPBEAR_COMP_ZLIB + || (ses.authstate.authdone + && ses.keys->trans_algo_comp == DROPBEAR_COMP_ZLIB_DELAY); +} + +int is_compress_recv() { + return ses.keys->recv_algo_comp == DROPBEAR_COMP_ZLIB + || (ses.authstate.authdone + && ses.keys->recv_algo_comp == DROPBEAR_COMP_ZLIB_DELAY); +} + /* Set up new zlib compression streams, close the old ones. Only * called from gen_new_keys() */ static void gen_new_zstreams() { /* create new zstreams */ - if (ses.newkeys->recv_algo_comp == DROPBEAR_COMP_ZLIB) { + if (ses.newkeys->recv_algo_comp == DROPBEAR_COMP_ZLIB + || ses.newkeys->recv_algo_comp == DROPBEAR_COMP_ZLIB_DELAY) { ses.newkeys->recv_zstream = (z_streamp)m_malloc(sizeof(z_stream)); ses.newkeys->recv_zstream->zalloc = Z_NULL; ses.newkeys->recv_zstream->zfree = Z_NULL; @@ -348,7 +362,8 @@ static void gen_new_zstreams() { ses.newkeys->recv_zstream = NULL; } - if (ses.newkeys->trans_algo_comp == DROPBEAR_COMP_ZLIB) { + if (ses.newkeys->trans_algo_comp == DROPBEAR_COMP_ZLIB + || ses.newkeys->trans_algo_comp == DROPBEAR_COMP_ZLIB_DELAY) { ses.newkeys->trans_zstream = (z_streamp)m_malloc(sizeof(z_stream)); ses.newkeys->trans_zstream->zalloc = Z_NULL; ses.newkeys->trans_zstream->zfree = Z_NULL; @@ -360,7 +375,7 @@ static void gen_new_zstreams() { } else { ses.newkeys->trans_zstream = NULL; } - + /* clean up old keys */ if (ses.keys->recv_zstream != NULL) { if (inflateEnd(ses.keys->recv_zstream) == Z_STREAM_ERROR) { @@ -377,7 +392,7 @@ static void gen_new_zstreams() { m_free(ses.keys->trans_zstream); } } -#endif +#endif /* DISABLE_ZLIB */ /* Executed upon receiving a kexinit message from the client to initiate diff --git a/dbclient.1 b/dbclient.1 index 033672d..934e34a 100644 --- a/dbclient.1 +++ b/dbclient.1 @@ -10,6 +10,7 @@ dbclient \- lightweight SSH2 client .I l\fR:\fIh\fR:\fIr\fR] [\-l .IR user ] .I host +.RI [ command ] .SH DESCRIPTION .B dbclient is a SSH 2 client designed to be small enough to be used in small memory diff --git a/kex.h b/kex.h index d3dd187..a3bdc7a 100644 --- a/kex.h +++ b/kex.h @@ -37,6 +37,11 @@ void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv); void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them, sign_key *hostkey); +#ifndef DISABLE_ZLIB +int is_compress_trans(); +int is_compress_recv(); +#endif + void recv_msg_kexdh_init(); /* server */ void send_msg_kexdh_init(); /* client */ diff --git a/packet.c b/packet.c index 30f4758..5ba99c3 100644 --- a/packet.c +++ b/packet.c @@ -290,10 +290,9 @@ void decrypt_packet() { buf_setpos(ses.decryptreadbuf, PACKET_PAYLOAD_OFF); #ifndef DISABLE_ZLIB - if (ses.keys->recv_algo_comp == DROPBEAR_COMP_ZLIB) { + if (is_compress_recv()) { /* decompress */ ses.payload = buf_decompress(ses.decryptreadbuf, len); - } else #endif { @@ -469,6 +468,7 @@ void encrypt_packet() { buffer * writebuf; /* the packet which will go on the wire */ buffer * clearwritebuf; /* unencrypted, possibly compressed */ unsigned char type; + unsigned int clear_len; type = ses.writepayload->data[0]; TRACE(("enter encrypt_packet()")) @@ -488,11 +488,12 @@ void encrypt_packet() { /* Encrypted packet len is payload+5, then worst case is if we are 3 away * from a blocksize multiple. In which case we need to pad to the * multiple, then add another blocksize (or MIN_PACKET_LEN) */ - clearwritebuf = buf_new((ses.writepayload->len+4+1) + MIN_PACKET_LEN + 3 + clear_len = (ses.writepayload->len+4+1) + MIN_PACKET_LEN + 3; + #ifndef DISABLE_ZLIB - + ZLIB_COMPRESS_INCR /* bit of a kludge, but we can't know len*/ + clear_len += ZLIB_COMPRESS_INCR; /* bit of a kludge, but we can't know len*/ #endif - ); + clearwritebuf = buf_new(clear_len); buf_setlen(clearwritebuf, PACKET_PAYLOAD_OFF); buf_setpos(clearwritebuf, PACKET_PAYLOAD_OFF); @@ -500,7 +501,7 @@ void encrypt_packet() { #ifndef DISABLE_ZLIB /* compression */ - if (ses.keys->trans_algo_comp == DROPBEAR_COMP_ZLIB) { + if (is_compress_trans()) { buf_compress(clearwritebuf, ses.writepayload, ses.writepayload->len); } else #endif diff --git a/session.h b/session.h index b63a258..96f4363 100644 --- a/session.h +++ b/session.h @@ -71,6 +71,8 @@ struct key_context { char recv_algo_comp; /* compression */ char trans_algo_comp; + int allow_compress; /* whether compression has started (useful in + zlib@openssh.com delayed compression case) */ #ifndef DISABLE_ZLIB z_streamp recv_zstream; z_streamp trans_zstream; diff --git a/svr-auth.c b/svr-auth.c index 4adf809..5da0aa7 100644 --- a/svr-auth.c +++ b/svr-auth.c @@ -368,6 +368,8 @@ void send_msg_userauth_success() { buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_SUCCESS); encrypt_packet(); + /* authdone must be set after encrypt_packet() for + * delayed-zlib mode */ ses.authstate.authdone = 1; ses.connect_time = 0; diff --git a/sysoptions.h b/sysoptions.h index 6b17151..4899e42 100644 --- a/sysoptions.h +++ b/sysoptions.h @@ -68,6 +68,7 @@ #define DROPBEAR_COMP_NONE 0 #define DROPBEAR_COMP_ZLIB 1 +#define DROPBEAR_COMP_ZLIB_DELAY 2 /* Required for pubkey auth */ #if defined(ENABLE_SVR_PUBKEY_AUTH) || defined(DROPBEAR_CLIENT) -- cgit v1.2.3