diff --git a/cli-auth.c b/cli-auth.c index 10245387e5a353b649d6d899a19228a318396e74..731d769697295144328a008c2e84e78ce2130519 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 21ac96a49a1fd4169480049205e7ceb2c944a607..d38c5e55ca4955c196de712bdcf8f3bb7dccb75f 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 e9c655dfa52e8493e6377c7639f021ea356e9ddf..80eb2a1615c76ca279f7a067bbaa22a53e154785 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 033672d0e5f1890cd68c6ca0c0357ca3385531f5..934e34acc292334aed064f5e64aaef99dba3854b 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 d3dd1874929e5b92a6c9b7c5f1772ca8b9ffef34..a3bdc7a72f5725f6d92838912efc50f837bab4dc 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 30f4758689bb1bc6f2b20fea01a0a15b2a8179fe..5ba99c30bf2401418a05bc66aeca1271d75364b0 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 b63a258c009d1f44663a6c258fb5315b6eb1a232..96f436341bc282c73fd324249b767a111318db59 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 4adf80989bb163a6ea457505163a9de4eea390dd..5da0aa70c2110b1571c3d0989de49f1a70f6cee9 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 6b171515819fa80115879cdfb882d8e609aa2d04..4899e4203cef56527fdfd9501d69feb36fae85ca 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)