X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/0183b2423868df18b2297c9052854e5a7db79425..b9d7bcadee831e9b59fb785f2464a5fc1897bd1a:/ssh.c diff --git a/ssh.c b/ssh.c index 677ff870..0a815bb6 100644 --- a/ssh.c +++ b/ssh.c @@ -401,23 +401,27 @@ const static struct ssh_mac *buggymacs[] = { &ssh_sha1_buggy, &ssh_md5, &ssh_mac_none }; -static void ssh_comp_none_init(void) +static void *ssh_comp_none_init(void) +{ + return NULL; +} +static void ssh_comp_none_cleanup(void *handle) { } -static int ssh_comp_none_block(unsigned char *block, int len, +static int ssh_comp_none_block(void *handle, unsigned char *block, int len, unsigned char **outblock, int *outlen) { return 0; } -static int ssh_comp_none_disable(void) +static int ssh_comp_none_disable(void *handle) { return 0; } const static struct ssh_compress ssh_comp_none = { "none", - ssh_comp_none_init, ssh_comp_none_block, - ssh_comp_none_init, ssh_comp_none_block, - ssh_comp_none_disable + 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_disable, NULL }; extern const struct ssh_compress ssh_zlib; const static struct ssh_compress *compressions[] = { @@ -551,6 +555,8 @@ struct ssh_tag { Socket s; + void *ldisc; + unsigned char session_key[32]; int v1_compressing; int v1_remote_protoflags; @@ -566,9 +572,11 @@ struct ssh_tag { const struct ssh_mac *csmac, *scmac; void *cs_mac_ctx, *sc_mac_ctx; const struct ssh_compress *cscomp, *sccomp; + void *cs_comp_ctx, *sc_comp_ctx; const struct ssh_kex *kex; const struct ssh_signkey *hostkey; unsigned char v2_session_id[20]; + void *kex_ctx; char *savedhost; int savedport; @@ -831,7 +839,8 @@ static int ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen) if (ssh->v1_compressing) { unsigned char *decompblk; int decomplen; - zlib_decompress_block(ssh->pktin.body - 1, ssh->pktin.length + 1, + zlib_decompress_block(ssh->sc_comp_ctx, + ssh->pktin.body - 1, ssh->pktin.length + 1, &decompblk, &decomplen); if (ssh->pktin.maxlen < st->pad + decomplen) { @@ -1005,7 +1014,8 @@ static int ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen) unsigned char *newpayload; int newlen; if (ssh->sccomp && - ssh->sccomp->decompress(ssh->pktin.data + 5, ssh->pktin.length - 5, + ssh->sccomp->decompress(ssh->sc_comp_ctx, + ssh->pktin.data + 5, ssh->pktin.length - 5, &newpayload, &newlen)) { if (ssh->pktin.maxlen < newlen + 5) { ssh->pktin.maxlen = newlen + 5; @@ -1170,7 +1180,8 @@ static int s_wrpkt_prepare(Ssh ssh) if (ssh->v1_compressing) { unsigned char *compblk; int complen; - zlib_compress_block(ssh->pktout.body - 1, ssh->pktout.length + 1, + zlib_compress_block(ssh->cs_comp_ctx, + ssh->pktout.body - 1, ssh->pktout.length + 1, &compblk, &complen); ssh1_pktout_size(ssh, complen - 1); memcpy(ssh->pktout.body - 1, compblk, complen); @@ -1456,7 +1467,8 @@ static int ssh2_pkt_construct(Ssh ssh) unsigned char *newpayload; int newlen; if (ssh->cscomp && - ssh->cscomp->compress(ssh->pktout.data + 5, ssh->pktout.length - 5, + ssh->cscomp->compress(ssh->cs_comp_ctx, ssh->pktout.data + 5, + ssh->pktout.length - 5, &newpayload, &newlen)) { ssh->pktout.length = 5; ssh2_pkt_adddata(ssh, newpayload, newlen); @@ -3190,8 +3202,10 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) } logevent("Started compression"); ssh->v1_compressing = TRUE; - zlib_compress_init(); - zlib_decompress_init(); + ssh->cs_comp_ctx = zlib_compress_init(); + logevent("Initialised zlib (RFC1950) compression"); + ssh->sc_comp_ctx = zlib_decompress_init(); + logevent("Initialised zlib (RFC1950) decompression"); } /* @@ -3221,7 +3235,8 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) if (ssh->eof_needed) ssh_special(ssh, TS_EOF); - ldisc_send(NULL, 0, 0); /* cause ldisc to notice changes */ + if (ssh->ldisc) + ldisc_send(ssh->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */ ssh->send_ok = 1; ssh->channels = newtree234(ssh_channelcmp); while (1) { @@ -3953,12 +3968,12 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt) } s->p = ssh2_pkt_getmp(ssh); s->g = ssh2_pkt_getmp(ssh); - dh_setup_group(s->p, s->g); + ssh->kex_ctx = dh_setup_group(s->p, s->g); s->kex_init_value = SSH2_MSG_KEX_DH_GEX_INIT; s->kex_reply_value = SSH2_MSG_KEX_DH_GEX_REPLY; } else { ssh->pkt_ctx |= SSH2_PKTCTX_DHGROUP1; - dh_setup_group1(); + ssh->kex_ctx = dh_setup_group1(); s->kex_init_value = SSH2_MSG_KEXDH_INIT; s->kex_reply_value = SSH2_MSG_KEXDH_REPLY; } @@ -3967,7 +3982,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt) /* * Now generate and send e for Diffie-Hellman. */ - s->e = dh_create_e(s->nbits * 2); + s->e = dh_create_e(ssh->kex_ctx, s->nbits * 2); ssh2_pkt_init(ssh, s->kex_init_value); ssh2_pkt_addmp(ssh, s->e); ssh2_pkt_send(ssh); @@ -3981,7 +3996,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt) s->f = ssh2_pkt_getmp(ssh); ssh2_pkt_getstring(ssh, &s->sigdata, &s->siglen); - s->K = dh_find_K(s->f); + s->K = dh_find_K(ssh->kex_ctx, s->f); sha_string(&ssh->exhash, s->hostkeydata, s->hostkeylen); if (ssh->kex == &ssh_diffiehellman_gex) { @@ -3994,7 +4009,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt) sha_mpint(&ssh->exhash, s->K); SHA_Final(&ssh->exhash, s->exchange_hash); - dh_cleanup(); + dh_cleanup(ssh->kex_ctx); #if 0 debug(("Exchange hash is:\n")); @@ -4063,10 +4078,16 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt) ssh->scmac = s->scmac_tobe; ssh->sc_mac_ctx = ssh->scmac->make_context(); + if (ssh->cs_comp_ctx) + ssh->cscomp->compress_cleanup(ssh->cs_comp_ctx); ssh->cscomp = s->cscomp_tobe; + ssh->cs_comp_ctx = ssh->cscomp->compress_init(); + + if (ssh->sc_comp_ctx) + ssh->sccomp->decompress_cleanup(ssh->sc_comp_ctx); ssh->sccomp = s->sccomp_tobe; - ssh->cscomp->compress_init(); - ssh->sccomp->decompress_init(); + ssh->sc_comp_ctx = ssh->sccomp->decompress_init(); + /* * Set IVs after keys. Here we use the exchange hash from the * _first_ key exchange. @@ -4097,6 +4118,16 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt) sprintf(buf, "Initialised %.200s server->client encryption", ssh->sccipher->text_name); logevent(buf); + if (ssh->cscomp->text_name) { + sprintf(buf, "Initialised %.200s compression", + ssh->cscomp->text_name); + logevent(buf); + } + if (ssh->sccomp->text_name) { + sprintf(buf, "Initialised %.200s decompression", + ssh->sccomp->text_name); + logevent(buf); + } } @@ -4925,7 +4956,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) * bytes we should adjust our string length * by. */ - stringlen -= ssh->cscomp->disable_compression(); + stringlen -= + ssh->cscomp->disable_compression(ssh->cs_comp_ctx); } ssh2_pkt_init(ssh, SSH2_MSG_IGNORE); ssh2_pkt_addstring_start(ssh); @@ -5350,7 +5382,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) /* * Transfer data! */ - ldisc_send(NULL, 0, 0); /* cause ldisc to notice changes */ + if (ssh->ldisc) + ldisc_send(ssh->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */ ssh->send_ok = 1; while (1) { crReturnV; @@ -5816,13 +5849,16 @@ static char *ssh_init(void *frontend_handle, void **backend_handle, ssh->scmac = NULL; ssh->sc_mac_ctx = NULL; ssh->cscomp = NULL; + ssh->cs_comp_ctx = NULL; ssh->sccomp = NULL; + ssh->sc_comp_ctx = NULL; ssh->kex = NULL; ssh->hostkey = NULL; ssh->exitcode = -1; ssh->state = SSH_STATE_PREPACKET; ssh->size_needed = FALSE; ssh->eof_needed = FALSE; + ssh->ldisc = NULL; { static const struct Packet empty = { 0, 0, NULL, NULL, 0 }; ssh->pktin = ssh->pktout = empty; @@ -6102,6 +6138,12 @@ static int ssh_ldisc(void *handle, int option) return FALSE; } +static void ssh_provide_ldisc(void *handle, void *ldisc) +{ + Ssh ssh = (Ssh) handle; + ssh->ldisc = ldisc; +} + static int ssh_return_exitcode(void *handle) { Ssh ssh = (Ssh) handle; @@ -6129,6 +6171,7 @@ Backend ssh_backend = { ssh_return_exitcode, ssh_sendok, ssh_ldisc, + ssh_provide_ldisc, ssh_unthrottle, 22 };