Subject: Re: compression

Re: compression

From: Dave Hayden <dave_at_panic.com>
Date: Fri, 27 Jul 2012 14:09:19 -0700

On Jul 27, 2012, at 9:02 AM, TJ Saunders wrote:

> OpenSSH supports multiple types of compression: "zlib" (which is in the
> SSH RFCs) and "zlib_at_openssh.com", which is a non-standard (but commonly
> adopted) OpenSSH extension.
>
> libssh2 currently supports the "zlib" compression, which kicks in once the
> KEXINIT has finished. OpenSSH's "zlib_at_openssh.com" compression doesn't
> start until after successful user authentication.
>
> The change you made removes libssh2's support for "zlib" compression
> (which we would want to keep); it would be better, if possible, to add
> support for the "zlib_at_openss.com" compression along side the existing
> "zlib" compression support.

Ah, I thought that might be the case. Many thanks for the note!

Here's another stab at that code, adding a "use_in_auth" flag to the LIBSSH2_COMP_METHOD struct and a separate "zlib_at_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. (Unless, of course, I've messed something up..)

-D

diff -r -u /Users/dave/Desktop/libssh2-1.4.2/src/comp.c src/comp.c
--- /Users/dave/Desktop/libssh2-1.4.2/src/comp.c 2011-10-25 14:30:50.000000000 -0700
+++ src/comp.c 2012-07-27 13:14:46.000000000 -0700
@@ -96,6 +96,7 @@
 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,
@@ -357,6 +358,17 @@
 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_at_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,
@@ -369,6 +381,7 @@
 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 -r -u /Users/dave/Desktop/libssh2-1.4.2/src/libssh2_priv.h src/libssh2_priv.h
--- /Users/dave/Desktop/libssh2-1.4.2/src/libssh2_priv.h 2012-01-27 05:34:03.000000000 -0800
+++ src/libssh2_priv.h 2012-07-27 13:05:19.000000000 -0700
@@ -892,6 +892,7 @@
 {
     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 -r -u /Users/dave/Desktop/libssh2-1.4.2/src/transport.c src/transport.c
--- /Users/dave/Desktop/libssh2-1.4.2/src/transport.c 2012-03-16 08:39:58.000000000 -0700
+++ src/transport.c 2012-07-27 13:34:38.000000000 -0700
@@ -167,6 +167,7 @@
     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 @@
         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 @@
 #endif
     struct transportpacket *p = &session->packet;
     int encrypted;
+ int compressed;
     ssize_t ret;
     int rc;
     const unsigned char *orgdata = data;
@@ -723,7 +729,13 @@
 
     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 */
Daves-MacBook-Air:libssh2 dave$

_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel
Received on 2012-07-27