summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2008-09-29 02:23:04 +0000
committerMatt Johnston <matt@ucc.asn.au>2008-09-29 02:23:04 +0000
commit728e46fa99dd96532939764f29b324fb8b87f223 (patch)
tree62b2290f5f6e4c0c8e0a3c0263eaa991357abb24
parent1a63c07a02024ca3942ce204de6c0fc4ead4d551 (diff)
downloaddropbear-728e46fa99dd96532939764f29b324fb8b87f223.tar.gz
Add support for zlib@openssh.com delayed compression.
Are still advertising 'zlib' for the server, need to allow delayed-only as an option
-rw-r--r--cli-auth.c2
-rw-r--r--common-algo.c1
-rw-r--r--common-kex.c23
-rw-r--r--dbclient.11
-rw-r--r--kex.h5
-rw-r--r--packet.c13
-rw-r--r--session.h2
-rw-r--r--svr-auth.c2
-rw-r--r--sysoptions.h1
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)