1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00

Make ssh_compress into a pair of linked classoids.

This was mildly fiddly because there's a single vtable structure that
implements two distinct interface types, one for compression and one
for decompression - and I have actually confused them before now
(commit d4304f1b7), so I think it's important to make them actually be
separate types!
This commit is contained in:
Simon Tatham 2018-09-14 09:16:41 +01:00
parent 03fb4423af
commit d437e5402e
6 changed files with 130 additions and 99 deletions

32
ssh.c
View File

@ -335,31 +335,39 @@ const static struct ssh2_macalg *const buggymacs[] = {
&ssh_hmac_sha1_buggy, &ssh_hmac_sha1_96_buggy, &ssh_hmac_md5 &ssh_hmac_sha1_buggy, &ssh_hmac_sha1_96_buggy, &ssh_hmac_md5
}; };
static void *ssh_comp_none_init(void) static ssh_compressor *ssh_comp_none_init(void)
{ {
return NULL; return NULL;
} }
static void ssh_comp_none_cleanup(void *handle) static void ssh_comp_none_cleanup(ssh_compressor *handle)
{ {
} }
static void ssh_comp_none_block(void *handle, unsigned char *block, int len, static ssh_decompressor *ssh_decomp_none_init(void)
{
return NULL;
}
static void ssh_decomp_none_cleanup(ssh_decompressor *handle)
{
}
static void ssh_comp_none_block(ssh_compressor *handle,
unsigned char *block, int len,
unsigned char **outblock, int *outlen, unsigned char **outblock, int *outlen,
int minlen) int minlen)
{ {
} }
static int ssh_decomp_none_block(void *handle, unsigned char *block, int len, static int ssh_decomp_none_block(ssh_decompressor *handle,
unsigned char *block, int len,
unsigned char **outblock, int *outlen) unsigned char **outblock, int *outlen)
{ {
return 0; return 0;
} }
const static struct ssh_compress ssh_comp_none = { const static struct ssh_compression_alg ssh_comp_none = {
"none", NULL, "none", NULL,
ssh_comp_none_init, ssh_comp_none_cleanup, ssh_comp_none_block, ssh_comp_none_init, ssh_comp_none_cleanup, ssh_comp_none_block,
ssh_comp_none_init, ssh_comp_none_cleanup, ssh_decomp_none_block, ssh_decomp_none_init, ssh_decomp_none_cleanup, ssh_decomp_none_block,
NULL NULL
}; };
extern const struct ssh_compress ssh_zlib; const static struct ssh_compression_alg *const compressions[] = {
const static struct ssh_compress *const compressions[] = {
&ssh_zlib, &ssh_comp_none &ssh_zlib, &ssh_comp_none
}; };
@ -4853,7 +4861,7 @@ struct kexinit_algorithm {
const struct ssh2_macalg *mac; const struct ssh2_macalg *mac;
int etm; int etm;
} mac; } mac;
const struct ssh_compress *comp; const struct ssh_compression_alg *comp;
} u; } u;
}; };
@ -5025,7 +5033,7 @@ static void do_ssh2_transport(void *vctx)
const struct ssh2_cipheralg *cipher; const struct ssh2_cipheralg *cipher;
const struct ssh2_macalg *mac; const struct ssh2_macalg *mac;
int etm_mode; int etm_mode;
const struct ssh_compress *comp; const struct ssh_compression_alg *comp;
} in, out; } in, out;
ptrlen hostkeydata, sigdata; ptrlen hostkeydata, sigdata;
char *keystr, *fingerprint; char *keystr, *fingerprint;
@ -5042,7 +5050,7 @@ static void do_ssh2_transport(void *vctx)
int preferred_hk[HK_MAX]; int preferred_hk[HK_MAX];
int n_preferred_ciphers; int n_preferred_ciphers;
const struct ssh2_ciphers *preferred_ciphers[CIPHER_MAX]; const struct ssh2_ciphers *preferred_ciphers[CIPHER_MAX];
const struct ssh_compress *preferred_comp; const struct ssh_compression_alg *preferred_comp;
int userauth_succeeded; /* for delayed compression */ int userauth_succeeded; /* for delayed compression */
int pending_compression; int pending_compression;
int got_session_id; int got_session_id;
@ -5413,7 +5421,7 @@ static void do_ssh2_transport(void *vctx)
alg->u.comp = s->preferred_comp; alg->u.comp = s->preferred_comp;
} }
for (i = 0; i < lenof(compressions); i++) { for (i = 0; i < lenof(compressions); i++) {
const struct ssh_compress *c = compressions[i]; const struct ssh_compression_alg *c = compressions[i];
alg = ssh2_kexinit_addalg(s->kexlists[j], c->name); alg = ssh2_kexinit_addalg(s->kexlists[j], c->name);
alg->u.comp = c; alg->u.comp = c;
if (s->userauth_succeeded && c->delayed_name) { if (s->userauth_succeeded && c->delayed_name) {

50
ssh.h
View File

@ -603,23 +603,39 @@ struct ssh_keyalg {
#define ssh_key_ssh_id(key) ((*(key))->ssh_id) #define ssh_key_ssh_id(key) ((*(key))->ssh_id)
#define ssh_key_cache_id(key) ((*(key))->cache_id) #define ssh_key_cache_id(key) ((*(key))->cache_id)
struct ssh_compress { typedef struct ssh_compressor {
const struct ssh_compression_alg *vt;
} ssh_compressor;
typedef struct ssh_decompressor {
const struct ssh_compression_alg *vt;
} ssh_decompressor;
struct ssh_compression_alg {
const char *name; const char *name;
/* For zlib@openssh.com: if non-NULL, this name will be considered once /* For zlib@openssh.com: if non-NULL, this name will be considered once
* userauth has completed successfully. */ * userauth has completed successfully. */
const char *delayed_name; const char *delayed_name;
void *(*compress_init) (void); ssh_compressor *(*compress_new)(void);
void (*compress_cleanup) (void *); void (*compress_free)(ssh_compressor *);
void (*compress) (void *, unsigned char *block, int len, void (*compress)(ssh_compressor *, unsigned char *block, int len,
unsigned char **outblock, int *outlen, unsigned char **outblock, int *outlen,
int minlen); int minlen);
void *(*decompress_init) (void); ssh_decompressor *(*decompress_new)(void);
void (*decompress_cleanup) (void *); void (*decompress_free)(ssh_decompressor *);
int (*decompress) (void *, unsigned char *block, int len, int (*decompress)(ssh_decompressor *, unsigned char *block, int len,
unsigned char **outblock, int *outlen); unsigned char **outblock, int *outlen);
const char *text_name; const char *text_name;
}; };
#define ssh_compressor_new(alg) ((alg)->compress_new())
#define ssh_compressor_free(comp) ((comp)->vt->compress_free(comp))
#define ssh_compressor_compress(comp, in, inlen, out, outlen, minlen) \
((comp)->vt->compress(comp, in, inlen, out, outlen, minlen))
#define ssh_decompressor_new(alg) ((alg)->decompress_new())
#define ssh_decompressor_free(comp) ((comp)->vt->decompress_free(comp))
#define ssh_decompressor_decompress(comp, in, inlen, out, outlen) \
((comp)->vt->decompress(comp, in, inlen, out, outlen))
struct ssh2_userkey { struct ssh2_userkey {
ssh_key *key; /* the key itself */ ssh_key *key; /* the key itself */
char *comment; /* the key comment */ char *comment; /* the key comment */
@ -659,6 +675,7 @@ extern const struct ssh2_macalg ssh_hmac_sha1_buggy;
extern const struct ssh2_macalg ssh_hmac_sha1_96; extern const struct ssh2_macalg ssh_hmac_sha1_96;
extern const struct ssh2_macalg ssh_hmac_sha1_96_buggy; extern const struct ssh2_macalg ssh_hmac_sha1_96_buggy;
extern const struct ssh2_macalg ssh_hmac_sha256; extern const struct ssh2_macalg ssh_hmac_sha256;
extern const struct ssh_compression_alg ssh_zlib;
typedef struct AESContext AESContext; typedef struct AESContext AESContext;
AESContext *aes_make_context(void); AESContext *aes_make_context(void);
@ -1017,19 +1034,6 @@ Bignum primegen(int bits, int modulus, int residue, Bignum factor,
int phase, progfn_t pfn, void *pfnparam, unsigned firstbits); int phase, progfn_t pfn, void *pfnparam, unsigned firstbits);
void invent_firstbits(unsigned *one, unsigned *two); void invent_firstbits(unsigned *one, unsigned *two);
/*
* zlib compression.
*/
void *zlib_compress_init(void);
void zlib_compress_cleanup(void *);
void *zlib_decompress_init(void);
void zlib_decompress_cleanup(void *);
void zlib_compress_block(void *, unsigned char *block, int len,
unsigned char **outblock, int *outlen, int minlen);
int zlib_decompress_block(void *, unsigned char *block, int len,
unsigned char **outblock, int *outlen);
/* /*
* Connection-sharing API provided by platforms. This function must * Connection-sharing API provided by platforms. This function must
* either: * either:

View File

@ -21,7 +21,8 @@ struct ssh1_bpp_state {
struct crcda_ctx *crcda_ctx; struct crcda_ctx *crcda_ctx;
void *compctx, *decompctx; ssh_compressor *compctx;
ssh_decompressor *decompctx;
BinaryPacketProtocol bpp; BinaryPacketProtocol bpp;
}; };
@ -52,9 +53,9 @@ static void ssh1_bpp_free(BinaryPacketProtocol *bpp)
if (s->cipher) if (s->cipher)
ssh1_cipher_free(s->cipher); ssh1_cipher_free(s->cipher);
if (s->compctx) if (s->compctx)
zlib_compress_cleanup(s->compctx); ssh_compressor_free(s->compctx);
if (s->decompctx) if (s->decompctx)
zlib_decompress_cleanup(s->decompctx); ssh_decompressor_free(s->decompctx);
if (s->crcda_ctx) if (s->crcda_ctx)
crcda_free_context(s->crcda_ctx); crcda_free_context(s->crcda_ctx);
if (s->pktin) if (s->pktin)
@ -90,8 +91,8 @@ void ssh1_bpp_start_compression(BinaryPacketProtocol *bpp)
assert(!s->compctx); assert(!s->compctx);
assert(!s->decompctx); assert(!s->decompctx);
s->compctx = zlib_compress_init(); s->compctx = ssh_compressor_new(&ssh_zlib);
s->decompctx = zlib_decompress_init(); s->decompctx = ssh_decompressor_new(&ssh_zlib);
} }
static void ssh1_bpp_handle_input(BinaryPacketProtocol *bpp) static void ssh1_bpp_handle_input(BinaryPacketProtocol *bpp)
@ -157,9 +158,9 @@ static void ssh1_bpp_handle_input(BinaryPacketProtocol *bpp)
if (s->decompctx) { if (s->decompctx) {
unsigned char *decompblk; unsigned char *decompblk;
int decomplen; int decomplen;
if (!zlib_decompress_block(s->decompctx, if (!ssh_decompressor_decompress(
s->data + s->pad, s->length + 1, s->decompctx, s->data + s->pad, s->length + 1,
&decompblk, &decomplen)) { &decompblk, &decomplen)) {
s->bpp.error = dupprintf( s->bpp.error = dupprintf(
"Zlib decompression encountered invalid data"); "Zlib decompression encountered invalid data");
crStopV; crStopV;
@ -248,8 +249,8 @@ static void ssh1_bpp_format_packet(BinaryPacketProtocol *bpp, PktOut *pkt)
if (s->compctx) { if (s->compctx) {
unsigned char *compblk; unsigned char *compblk;
int complen; int complen;
zlib_compress_block(s->compctx, pkt->data + 12, pkt->length - 12, ssh_compressor_compress(s->compctx, pkt->data + 12, pkt->length - 12,
&compblk, &complen, 0); &compblk, &complen, 0);
/* Replace the uncompressed packet data with the compressed /* Replace the uncompressed packet data with the compressed
* version. */ * version. */
pkt->length = 12; pkt->length = 12;

View File

@ -14,8 +14,6 @@ struct ssh2_bpp_direction {
ssh2_cipher *cipher; ssh2_cipher *cipher;
ssh2_mac *mac; ssh2_mac *mac;
int etm_mode; int etm_mode;
const struct ssh_compress *comp;
void *comp_ctx;
}; };
struct ssh2_bpp_state { struct ssh2_bpp_state {
@ -28,6 +26,11 @@ struct ssh2_bpp_state {
PktIn *pktin; PktIn *pktin;
struct ssh2_bpp_direction in, out; struct ssh2_bpp_direction in, out;
/* comp and decomp logically belong in the per-direction
* substructure, except that they have different types */
ssh_decompressor *in_decomp;
ssh_compressor *out_comp;
int pending_newkeys; int pending_newkeys;
BinaryPacketProtocol bpp; BinaryPacketProtocol bpp;
@ -61,14 +64,14 @@ static void ssh2_bpp_free(BinaryPacketProtocol *bpp)
ssh2_cipher_free(s->out.cipher); ssh2_cipher_free(s->out.cipher);
if (s->out.mac) if (s->out.mac)
ssh2_mac_free(s->out.mac); ssh2_mac_free(s->out.mac);
if (s->out.comp_ctx) if (s->out_comp)
s->out.comp->compress_cleanup(s->out.comp_ctx); ssh_compressor_free(s->out_comp);
if (s->in.cipher) if (s->in.cipher)
ssh2_cipher_free(s->in.cipher); ssh2_cipher_free(s->in.cipher);
if (s->in.mac) if (s->in.mac)
ssh2_mac_free(s->in.mac); ssh2_mac_free(s->in.mac);
if (s->in.comp_ctx) if (s->in_decomp)
s->in.comp->decompress_cleanup(s->in.comp_ctx); ssh_decompressor_free(s->in_decomp);
if (s->pktin) if (s->pktin)
ssh_unref_packet(s->pktin); ssh_unref_packet(s->pktin);
sfree(s); sfree(s);
@ -78,7 +81,7 @@ void ssh2_bpp_new_outgoing_crypto(
BinaryPacketProtocol *bpp, BinaryPacketProtocol *bpp,
const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv, const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv,
const struct ssh2_macalg *mac, int etm_mode, const void *mac_key, const struct ssh2_macalg *mac, int etm_mode, const void *mac_key,
const struct ssh_compress *compression) const struct ssh_compression_alg *compression)
{ {
struct ssh2_bpp_state *s; struct ssh2_bpp_state *s;
assert(bpp->vt == &ssh2_bpp_vtable); assert(bpp->vt == &ssh2_bpp_vtable);
@ -88,8 +91,8 @@ void ssh2_bpp_new_outgoing_crypto(
ssh2_cipher_free(s->out.cipher); ssh2_cipher_free(s->out.cipher);
if (s->out.mac) if (s->out.mac)
ssh2_mac_free(s->out.mac); ssh2_mac_free(s->out.mac);
if (s->out.comp_ctx) if (s->out_comp)
s->out.comp->compress_cleanup(s->out.comp_ctx); ssh_compressor_free(s->out_comp);
if (cipher) { if (cipher) {
s->out.cipher = ssh2_cipher_new(cipher); s->out.cipher = ssh2_cipher_new(cipher);
@ -106,18 +109,17 @@ void ssh2_bpp_new_outgoing_crypto(
s->out.mac = NULL; s->out.mac = NULL;
} }
s->out.comp = compression; /* 'compression' is always non-NULL, because no compression is
/* out_comp is always non-NULL, because no compression is * indicated by ssh_comp_none. But this setup call may return a
* indicated by ssh_comp_none. So compress_init always exists, but * null out_comp. */
* it may return a null out_comp_ctx. */ s->out_comp = ssh_compressor_new(compression);
s->out.comp_ctx = compression->compress_init();
} }
void ssh2_bpp_new_incoming_crypto( void ssh2_bpp_new_incoming_crypto(
BinaryPacketProtocol *bpp, BinaryPacketProtocol *bpp,
const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv, const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv,
const struct ssh2_macalg *mac, int etm_mode, const void *mac_key, const struct ssh2_macalg *mac, int etm_mode, const void *mac_key,
const struct ssh_compress *compression) const struct ssh_compression_alg *compression)
{ {
struct ssh2_bpp_state *s; struct ssh2_bpp_state *s;
assert(bpp->vt == &ssh2_bpp_vtable); assert(bpp->vt == &ssh2_bpp_vtable);
@ -127,8 +129,8 @@ void ssh2_bpp_new_incoming_crypto(
ssh2_cipher_free(s->in.cipher); ssh2_cipher_free(s->in.cipher);
if (s->in.mac) if (s->in.mac)
ssh2_mac_free(s->in.mac); ssh2_mac_free(s->in.mac);
if (s->in.comp_ctx) if (s->in_decomp)
s->in.comp->decompress_cleanup(s->in.comp_ctx); ssh_decompressor_free(s->in_decomp);
if (cipher) { if (cipher) {
s->in.cipher = ssh2_cipher_new(cipher); s->in.cipher = ssh2_cipher_new(cipher);
@ -145,11 +147,10 @@ void ssh2_bpp_new_incoming_crypto(
s->in.mac = NULL; s->in.mac = NULL;
} }
s->in.comp = compression; /* 'compression' is always non-NULL, because no compression is
/* in_comp is always non-NULL, because no compression is * indicated by ssh_comp_none. But this setup call may return a
* indicated by ssh_comp_none. So compress_init always exists, but * null in_decomp. */
* it may return a null in_comp_ctx. */ s->in_decomp = ssh_decompressor_new(compression);
s->in.comp_ctx = compression->decompress_init();
/* Clear the pending_newkeys flag, so that handle_input below will /* Clear the pending_newkeys flag, so that handle_input below will
* start consuming the input data again. */ * start consuming the input data again. */
@ -419,8 +420,8 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
{ {
unsigned char *newpayload; unsigned char *newpayload;
int newlen; int newlen;
if (s->in.comp && s->in.comp->decompress( if (s->in_decomp && ssh_decompressor_decompress(
s->in.comp_ctx, s->data + 5, s->length - 5, s->in_decomp, s->data + 5, s->length - 5,
&newpayload, &newlen)) { &newpayload, &newlen)) {
if (s->maxlen < newlen + 5) { if (s->maxlen < newlen + 5) {
PktIn *old_pktin = s->pktin; PktIn *old_pktin = s->pktin;
@ -526,7 +527,7 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt)
cipherblk = s->out.cipher ? ssh2_cipher_alg(s->out.cipher)->blksize : 8; cipherblk = s->out.cipher ? ssh2_cipher_alg(s->out.cipher)->blksize : 8;
cipherblk = cipherblk < 8 ? 8 : cipherblk; /* or 8 if blksize < 8 */ cipherblk = cipherblk < 8 ? 8 : cipherblk; /* or 8 if blksize < 8 */
if (s->out.comp && s->out.comp_ctx) { if (s->out_comp) {
unsigned char *newpayload; unsigned char *newpayload;
int minlen, newlen; int minlen, newlen;
@ -544,8 +545,8 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt)
minlen -= 8; /* length field + min padding */ minlen -= 8; /* length field + min padding */
} }
s->out.comp->compress(s->out.comp_ctx, pkt->data + 5, pkt->length - 5, ssh_compressor_compress(s->out_comp, pkt->data + 5, pkt->length - 5,
&newpayload, &newlen, minlen); &newpayload, &newlen, minlen);
pkt->length = 5; pkt->length = 5;
put_data(pkt, newpayload, newlen); put_data(pkt, newpayload, newlen);
sfree(newpayload); sfree(newpayload);
@ -608,7 +609,7 @@ static void ssh2_bpp_format_packet(BinaryPacketProtocol *bpp, PktOut *pkt)
{ {
struct ssh2_bpp_state *s = FROMFIELD(bpp, struct ssh2_bpp_state, bpp); struct ssh2_bpp_state *s = FROMFIELD(bpp, struct ssh2_bpp_state, bpp);
if (pkt->minlen > 0 && !(s->out.comp && s->out.comp_ctx)) { if (pkt->minlen > 0 && !s->out_comp) {
/* /*
* If we've been told to pad the packet out to a given minimum * If we've been told to pad the packet out to a given minimum
* length, but we're not compressing (and hence can't get the * length, but we're not compressing (and hence can't get the

View File

@ -41,12 +41,12 @@ void ssh2_bpp_new_outgoing_crypto(
BinaryPacketProtocol *bpp, BinaryPacketProtocol *bpp,
const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv, const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv,
const struct ssh2_macalg *mac, int etm_mode, const void *mac_key, const struct ssh2_macalg *mac, int etm_mode, const void *mac_key,
const struct ssh_compress *compression); const struct ssh_compression_alg *compression);
void ssh2_bpp_new_incoming_crypto( void ssh2_bpp_new_incoming_crypto(
BinaryPacketProtocol *bpp, BinaryPacketProtocol *bpp,
const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv, const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv,
const struct ssh2_macalg *mac, int etm_mode, const void *mac_key, const struct ssh2_macalg *mac, int etm_mode, const void *mac_key,
const struct ssh_compress *compression); const struct ssh_compression_alg *compression);
BinaryPacketProtocol *ssh2_bare_bpp_new(void); BinaryPacketProtocol *ssh2_bare_bpp_new(void);

View File

@ -66,6 +66,10 @@
#define TRUE 1 #define TRUE 1
#endif #endif
typedef struct { const struct dummy *vt; } ssh_compressor;
typedef struct { const struct dummy *vt; } ssh_decompressor;
static const struct dummy { int i; } ssh_zlib;
#else #else
#include "ssh.h" #include "ssh.h"
#endif #endif
@ -600,37 +604,45 @@ static void zlib_match(struct LZ77Context *ectx, int distance, int len)
} }
} }
void *zlib_compress_init(void) struct ssh_zlib_compressor {
struct LZ77Context ectx;
ssh_compressor sc;
};
ssh_compressor *zlib_compress_init(void)
{ {
struct Outbuf *out; struct Outbuf *out;
struct LZ77Context *ectx = snew(struct LZ77Context); struct ssh_zlib_compressor *comp = snew(struct ssh_zlib_compressor);
lz77_init(ectx); lz77_init(&comp->ectx);
ectx->literal = zlib_literal; comp->sc.vt = &ssh_zlib;
ectx->match = zlib_match; comp->ectx.literal = zlib_literal;
comp->ectx.match = zlib_match;
out = snew(struct Outbuf); out = snew(struct Outbuf);
out->outbits = out->noutbits = 0; out->outbits = out->noutbits = 0;
out->firstblock = 1; out->firstblock = 1;
ectx->userdata = out; comp->ectx.userdata = out;
return ectx; return &comp->sc;
} }
void zlib_compress_cleanup(void *handle) void zlib_compress_cleanup(ssh_compressor *sc)
{ {
struct LZ77Context *ectx = (struct LZ77Context *)handle; struct ssh_zlib_compressor *comp =
sfree(ectx->userdata); FROMFIELD(sc, struct ssh_zlib_compressor, sc);
sfree(ectx->ictx); sfree(comp->ectx.userdata);
sfree(ectx); sfree(comp->ectx.ictx);
sfree(comp);
} }
void zlib_compress_block(void *handle, unsigned char *block, int len, void zlib_compress_block(ssh_compressor *sc, unsigned char *block, int len,
unsigned char **outblock, int *outlen, unsigned char **outblock, int *outlen,
int minlen) int minlen)
{ {
struct LZ77Context *ectx = (struct LZ77Context *)handle; struct ssh_zlib_compressor *comp =
struct Outbuf *out = (struct Outbuf *) ectx->userdata; FROMFIELD(sc, struct ssh_zlib_compressor, sc);
struct Outbuf *out = (struct Outbuf *) comp->ectx.userdata;
int in_block; int in_block;
out->outbuf = NULL; out->outbuf = NULL;
@ -662,7 +674,7 @@ void zlib_compress_block(void *handle, unsigned char *block, int len,
/* /*
* Do the compression. * Do the compression.
*/ */
lz77_compress(ectx, block, len, TRUE); lz77_compress(&comp->ectx, block, len, TRUE);
/* /*
* End the block (by transmitting code 256, which is * End the block (by transmitting code 256, which is
@ -875,9 +887,11 @@ struct zlib_decompress_ctx {
int winpos; int winpos;
unsigned char *outblk; unsigned char *outblk;
int outlen, outsize; int outlen, outsize;
ssh_decompressor dc;
}; };
void *zlib_decompress_init(void) ssh_decompressor *zlib_decompress_init(void)
{ {
struct zlib_decompress_ctx *dctx = snew(struct zlib_decompress_ctx); struct zlib_decompress_ctx *dctx = snew(struct zlib_decompress_ctx);
unsigned char lengths[288]; unsigned char lengths[288];
@ -895,12 +909,14 @@ void *zlib_decompress_init(void)
dctx->nbits = 0; dctx->nbits = 0;
dctx->winpos = 0; dctx->winpos = 0;
return dctx; dctx->dc.vt = &ssh_zlib;
return &dctx->dc;
} }
void zlib_decompress_cleanup(void *handle) void zlib_decompress_cleanup(ssh_decompressor *dc)
{ {
struct zlib_decompress_ctx *dctx = (struct zlib_decompress_ctx *)handle; struct zlib_decompress_ctx *dctx =
FROMFIELD(dc, struct zlib_decompress_ctx, dc);
if (dctx->currlentable && dctx->currlentable != dctx->staticlentable) if (dctx->currlentable && dctx->currlentable != dctx->staticlentable)
zlib_freetable(&dctx->currlentable); zlib_freetable(&dctx->currlentable);
@ -958,10 +974,11 @@ static void zlib_emit_char(struct zlib_decompress_ctx *dctx, int c)
#define EATBITS(n) ( dctx->nbits -= (n), dctx->bits >>= (n) ) #define EATBITS(n) ( dctx->nbits -= (n), dctx->bits >>= (n) )
int zlib_decompress_block(void *handle, unsigned char *block, int len, int zlib_decompress_block(ssh_decompressor *dc, unsigned char *block, int len,
unsigned char **outblock, int *outlen) unsigned char **outblock, int *outlen)
{ {
struct zlib_decompress_ctx *dctx = (struct zlib_decompress_ctx *)handle; struct zlib_decompress_ctx *dctx =
FROMFIELD(dc, struct zlib_decompress_ctx, dc);
const coderecord *rec; const coderecord *rec;
int code, blktype, rep, dist, nlen, header; int code, blktype, rep, dist, nlen, header;
static const unsigned char lenlenmap[] = { static const unsigned char lenlenmap[] = {
@ -1217,7 +1234,7 @@ int main(int argc, char **argv)
{ {
unsigned char buf[16], *outbuf; unsigned char buf[16], *outbuf;
int ret, outlen; int ret, outlen;
void *handle; ssh_decompressor *handle;
int noheader = FALSE, opts = TRUE; int noheader = FALSE, opts = TRUE;
char *filename = NULL; char *filename = NULL;
FILE *fp; FILE *fp;
@ -1289,7 +1306,7 @@ int main(int argc, char **argv)
#else #else
const struct ssh_compress ssh_zlib = { const struct ssh_compression_alg ssh_zlib = {
"zlib", "zlib",
"zlib@openssh.com", /* delayed version */ "zlib@openssh.com", /* delayed version */
zlib_compress_init, zlib_compress_init,