diff --git a/algo.h b/algo.h index 955864bd57438068e0d65244f315a8d79ff03d51..1758c51cebd411f0df35b7abdf8ede0c80a9f605 100644 --- a/algo.h +++ b/algo.h @@ -51,6 +51,7 @@ extern algo_type sshhostkey[]; extern algo_type sshciphers[]; extern algo_type sshhashes[]; extern algo_type ssh_compress[]; +extern algo_type ssh_delaycompress[]; extern algo_type ssh_nocompress[]; extern const struct dropbear_cipher dropbear_nocipher; diff --git a/cli-runopts.c b/cli-runopts.c index 11c689051c66f08e23ffb25594b29cb862b2b3e2..467776b5bc79455c6d925cb06f5ee92340e30b5c 100644 --- a/cli-runopts.c +++ b/cli-runopts.c @@ -156,7 +156,7 @@ void cli_getopts(int argc, char ** argv) { cli_opts.proxycmd = NULL; #endif #ifndef DISABLE_ZLIB - opts.enable_compress = 1; + opts.compress_mode = DROPBEAR_COMPRESS_ON; #endif #ifdef ENABLE_USER_ALGO_LIST opts.cipher_list = NULL; @@ -609,7 +609,7 @@ static void parse_multihop_hostname(const char* orighostarg, const char* argv0) passthrough_args, remainder); #ifndef DISABLE_ZLIB /* The stream will be incompressible since it's encrypted. */ - opts.enable_compress = 0; + opts.compress_mode = DROPBEAR_COMPRESS_OFF; #endif m_free(passthrough_args); } diff --git a/common-algo.c b/common-algo.c index 95c53f4c34ba38413521ceaca18f3acf0488597c..9abc33031141fe25237c20298782862d47b898e5 100644 --- a/common-algo.c +++ b/common-algo.c @@ -205,6 +205,12 @@ algo_type ssh_compress[] = { {"none", DROPBEAR_COMP_NONE, NULL, 1, NULL}, {NULL, 0, NULL, 0, NULL} }; + +algo_type ssh_delaycompress[] = { + {"zlib@openssh.com", DROPBEAR_COMP_ZLIB_DELAY, NULL, 1, NULL}, + {"none", DROPBEAR_COMP_NONE, NULL, 1, NULL}, + {NULL, 0, NULL, 0, NULL} +}; #endif algo_type ssh_nocompress[] = { diff --git a/common-kex.c b/common-kex.c index 65746a20044b485a5976028f003e10e8dde0d567..7d93708ef1a7c7189d52d619a7daf65fee5d9bd9 100644 --- a/common-kex.c +++ b/common-kex.c @@ -238,14 +238,24 @@ void recv_msg_newkeys() { void kexfirstinitialise() { ses.kexstate.donefirstkex = 0; -#ifndef DISABLE_ZLIB - if (opts.enable_compress) { - ses.compress_algos = ssh_compress; - } else -#endif +#ifdef DISABLE_ZLIB + ses.compress_algos = ssh_nocompress; +#else + switch (opts.compress_mode) { - ses.compress_algos = ssh_nocompress; + case DROPBEAR_COMPRESS_DELAYED: + ses.compress_algos = ssh_delaycompress; + break; + + case DROPBEAR_COMPRESS_ON: + ses.compress_algos = ssh_compress; + break; + + case DROPBEAR_COMPRESS_OFF: + ses.compress_algos = ssh_nocompress; + break; } +#endif kexinitialise(); } diff --git a/options.h b/options.h index 644ec72a06f001f7afd249b8849d2322bde1feb4..6339b0a4738eea67cb825de6c8744c5e49f2d64b 100644 --- a/options.h +++ b/options.h @@ -174,6 +174,11 @@ much traffic. */ #define DROPBEAR_ZLIB_WINDOW_BITS 15 #endif +/* Server won't allow zlib compression until after authentication. Prevents + flaws in the zlib library being unauthenticated exploitable flaws. + Some old ssh clients may not support the alternative zlib@openssh.com method */ +#define DROPBEAR_SERVER_DELAY_ZLIB 1 + /* Whether to do reverse DNS lookups. */ /*#define DO_HOST_LOOKUP */ diff --git a/runopts.h b/runopts.h index d0b6613388ef77262b2f6136bf444023faf1e6ff..87567164a60a4af3821aa7324f426650a5aa70f3 100644 --- a/runopts.h +++ b/runopts.h @@ -44,7 +44,11 @@ typedef struct runopts { /* TODO: add a commandline flag. Currently this is on by default if compression * is compiled in, but disabled for a client's non-final multihop stages. (The * intermediate stages are compressed streams, so are uncompressible. */ - int enable_compress; + enum { + DROPBEAR_COMPRESS_DELAYED, /* Server only */ + DROPBEAR_COMPRESS_ON, + DROPBEAR_COMPRESS_OFF, + } compress_mode; #endif #ifdef ENABLE_USER_ALGO_LIST diff --git a/svr-runopts.c b/svr-runopts.c index 13608131a99996318eb6073349c871a1cc09ac9c..09fc9af56c0396500fbaf8f9a660ac4a767a50fa 100644 --- a/svr-runopts.c +++ b/svr-runopts.c @@ -140,9 +140,15 @@ void svr_getopts(int argc, char ** argv) { #ifdef ENABLE_SVR_REMOTETCPFWD svr_opts.noremotetcp = 0; #endif + #ifndef DISABLE_ZLIB - opts.enable_compress = 1; +#if DROPBEAR_SERVER_DELAY_ZLIB + opts.compress_mode = DROPBEAR_COMPRESS_DELAYED; +#else + opts.compress_mode = DROPBEAR_COMPRESS_ON; #endif +#endif + /* not yet opts.ipv4 = 1; opts.ipv6 = 1;