From 42fec44c8a45f9b2d1fad3bef1300490d63d4d2c Mon Sep 17 00:00:00 2001 From: Dave Hayden Date: Sun, 19 Aug 2012 13:47:50 +0200 Subject: [PATCH] compression: add support for zlib@openssh.com Add a "use_in_auth" flag to the LIBSSH2_COMP_METHOD struct and a separate "zlib@openssh.com" method, along with checking session->state for LIBSSH2_STATE_AUTHENTICATED. Appears to work on the OpenSSH servers I've tried against, and it should work as before with normal zlib compression. --- src/comp.c | 13 +++++++++++++ src/libssh2_priv.h | 1 + src/transport.c | 20 ++++++++++++++++---- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/comp.c b/src/comp.c index ed854fee..4593ce4f 100644 --- a/src/comp.c +++ b/src/comp.c @@ -96,6 +96,7 @@ comp_method_none_decomp(LIBSSH2_SESSION * session, static const LIBSSH2_COMP_METHOD comp_method_none = { "none", 0, /* not really compressing */ + 0, /* isn't used in userauth, go figure */ NULL, comp_method_none_comp, comp_method_none_decomp, @@ -330,6 +331,17 @@ comp_method_zlib_dtor(LIBSSH2_SESSION *session, int compr, void **abstract) static const LIBSSH2_COMP_METHOD comp_method_zlib = { "zlib", 1, /* yes, this compresses */ + 1, /* do compression during userauth */ + comp_method_zlib_init, + comp_method_zlib_comp, + comp_method_zlib_decomp, + comp_method_zlib_dtor, +}; + +static const LIBSSH2_COMP_METHOD comp_method_zlib_openssh = { + "zlib@openssh.com", + 1, /* yes, this compresses */ + 0, /* don't use compression during userauth */ comp_method_zlib_init, comp_method_zlib_comp, comp_method_zlib_decomp, @@ -342,6 +354,7 @@ static const LIBSSH2_COMP_METHOD comp_method_zlib = { static const LIBSSH2_COMP_METHOD *comp_methods[] = { #ifdef LIBSSH2_HAVE_ZLIB &comp_method_zlib, + &comp_method_zlib_openssh, #endif /* LIBSSH2_HAVE_ZLIB */ &comp_method_none, NULL diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h index 23545624..23fbc65c 100644 --- a/src/libssh2_priv.h +++ b/src/libssh2_priv.h @@ -892,6 +892,7 @@ struct _LIBSSH2_COMP_METHOD { const char *name; int compress; /* 1 if it does compress, 0 if it doesn't */ + int use_in_auth; /* 1 if compression should be used in userauth */ int (*init) (LIBSSH2_SESSION *session, int compress, void **abstract); int (*comp) (LIBSSH2_SESSION *session, unsigned char *dest, diff --git a/src/transport.c b/src/transport.c index 95b9a3ad..15425b92 100644 --- a/src/transport.c +++ b/src/transport.c @@ -167,6 +167,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ ) unsigned char macbuf[MAX_MACSIZE]; struct transportpacket *p = &session->packet; int rc; + int compressed; if (session->fullpacket_state == libssh2_NB_state_idle) { session->fullpacket_macstate = LIBSSH2_MAC_CONFIRMED; @@ -199,9 +200,13 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ ) session->fullpacket_payload_len -= p->padding_length; /* Check for and deal with decompression */ - if (session->remote.comp && - session->remote.comp->compress && - session->remote.comp_abstract) { + compressed = + session->local.comp != NULL && + session->local.comp->compress && + ((session->state & LIBSSH2_STATE_AUTHENTICATED) || + session->local.comp->use_in_auth); + + if (compressed && session->remote.comp_abstract) { /* * The buffer for the decompression (remote.comp_abstract) is * initialised in time when it is needed so as long it is NULL we @@ -682,6 +687,7 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, #endif struct transportpacket *p = &session->packet; int encrypted; + int compressed; ssize_t ret; int rc; const unsigned char *orgdata = data; @@ -723,7 +729,13 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session, encrypted = (session->state & LIBSSH2_STATE_NEWKEYS) ? 1 : 0; - if (encrypted && session->local.comp->compress) { + compressed = + session->local.comp != NULL && + session->local.comp->compress && + ((session->state & LIBSSH2_STATE_AUTHENTICATED) || + session->local.comp->use_in_auth); + + if (encrypted && compressed) { /* the idea here is that these function must fail if the output gets larger than what fits in the assigned buffer so thus they don't check the input size as we don't know how much it compresses */