Line discipline module now uses dynamically allocated data. Also
[u/mdw/putty] / ssh.c
diff --git a/ssh.c b/ssh.c
index c936060..0a815bb 100644 (file)
--- 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,6 +572,7 @@ 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];
@@ -832,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) {
@@ -1006,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;
@@ -1171,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);
@@ -1457,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);
@@ -3191,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");
     }
 
     /*
@@ -3222,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) {
@@ -4064,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.
@@ -4098,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);
+       }
     }
 
 
@@ -4926,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);
@@ -5351,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;
@@ -5817,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;
@@ -6103,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;
@@ -6130,6 +6171,7 @@ Backend ssh_backend = {
     ssh_return_exitcode,
     ssh_sendok,
     ssh_ldisc,
+    ssh_provide_ldisc,
     ssh_unthrottle,
     22
 };