diff --git a/include/libssh/priv.h b/include/libssh/priv.h index f24102ff..6ad7ca7e 100644 --- a/include/libssh/priv.h +++ b/include/libssh/priv.h @@ -785,7 +785,7 @@ unsigned char *bin_to_base64(const unsigned char *source, int len); /* gzip.c */ int compress_buffer(SSH_SESSION *session,ssh_buffer buf); -int decompress_buffer(SSH_SESSION *session,ssh_buffer buf); +int decompress_buffer(SSH_SESSION *session,ssh_buffer buf, size_t maxlen); /* wrapper.c */ int crypt_set_algorithms(SSH_SESSION *); diff --git a/libssh/gzip.c b/libssh/gzip.c index 0b2638c2..f82ff5a5 100644 --- a/libssh/gzip.c +++ b/libssh/gzip.c @@ -143,7 +143,7 @@ static z_stream *initdecompress(SSH_SESSION *session) { return stream; } -static ssh_buffer gzip_decompress(SSH_SESSION *session, ssh_buffer source) { +static ssh_buffer gzip_decompress(SSH_SESSION *session, ssh_buffer source, size_t maxlen) { z_stream *zin = session->current_crypto->compress_in_ctx; void *in_ptr = buffer_get_rest(source); unsigned long in_size = buffer_get_rest_len(source); @@ -183,17 +183,21 @@ static ssh_buffer gzip_decompress(SSH_SESSION *session, ssh_buffer source) { buffer_free(dest); return NULL; } - + if (buffer_get_len(dest) > maxlen){ + /* Size of packet exceded, avoid a denial of service attack */ + buffer_free(dest); + return NULL; + } zin->next_out = out_buf; } while (zin->avail_out == 0); return dest; } -int decompress_buffer(SSH_SESSION *session,ssh_buffer buf){ +int decompress_buffer(SSH_SESSION *session,ssh_buffer buf, size_t maxlen){ ssh_buffer dest = NULL; - dest = gzip_decompress(session,buf); + dest = gzip_decompress(session,buf, maxlen); if (dest == NULL) { return -1; } diff --git a/libssh/packet.c b/libssh/packet.c index f0a56b17..0952f341 100644 --- a/libssh/packet.c +++ b/libssh/packet.c @@ -192,7 +192,7 @@ static int packet_read2(SSH_SESSION *session) { #if defined(HAVE_LIBZ) && defined(WITH_LIBZ) if (session->current_crypto && session->current_crypto->do_compress_in) { ssh_log(session, SSH_LOG_PACKET, "Decompressing in_buffer ..."); - if (decompress_buffer(session, session->in_buffer) < 0) { + if (decompress_buffer(session, session->in_buffer, MAX_PACKET_LEN) < 0) { goto error; } }