Fixes for (Backend)->size() changes -- internal declarations didn't include
[u/mdw/putty] / ssh.c
diff --git a/ssh.c b/ssh.c
index 3cc76be..258fd89 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -183,6 +183,7 @@ static const char *const ssh2_disconnect_reasons[] = {
 #define BUG_CHOKES_ON_RSA                        8
 #define BUG_SSH2_RSA_PADDING                    16
 #define BUG_SSH2_DERIVEKEY                       32
+#define BUG_SSH2_DH_GEX                          64
 
 static int ssh_pkt_ctx = 0;
 
@@ -532,6 +533,10 @@ static int savedport;
 static int ssh_send_ok;
 static int ssh_echoing, ssh_editing;
 
+static void *frontend;
+
+static int ssh_term_width, ssh_term_height;
+
 static tree234 *ssh_channels;         /* indexed by local id */
 static struct ssh_channel *mainchan;   /* primary session channel */
 static int ssh_exitcode = -1;
@@ -568,7 +573,7 @@ static int ssh1_stdout_throttling;
 static void (*ssh_protocol) (unsigned char *in, int inlen, int ispkt);
 static void ssh1_protocol(unsigned char *in, int inlen, int ispkt);
 static void ssh2_protocol(unsigned char *in, int inlen, int ispkt);
-static void ssh_size(void);
+static void ssh_size(int width, int height);
 static void ssh_special(Telnet_Special);
 static int ssh2_try_send(struct ssh_channel *c);
 static void ssh2_add_channel_data(struct ssh_channel *c, char *buf,
@@ -687,7 +692,7 @@ static void c_write(char *buf, int len)
                fputc(buf[i], stderr);
        return;
     }
-    from_backend(1, buf, len);
+    from_backend(frontend, 1, buf, len);
 }
 
 static void c_write_untrusted(char *buf, int len)
@@ -1742,6 +1747,14 @@ static void ssh_detect_bugs(char *vstring)
        ssh_remote_bugs |= BUG_SSH2_RSA_PADDING;
        logevent("We believe remote version has SSH2 RSA padding bug");
     }
+
+    if (cfg.sshbug_dhgex2 == BUG_ON) {
+       /*
+        * These versions have the SSH2 DH GEX bug.
+        */
+       ssh_remote_bugs |= BUG_SSH2_DH_GEX;
+       logevent("We believe remote version has SSH2 DH group exchange bug");
+    }
 }
 
 static int do_ssh_init(unsigned char c)
@@ -3115,7 +3128,8 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt)
     if (!cfg.nopty) {
        send_packet(SSH1_CMSG_REQUEST_PTY,
                    PKT_STR, cfg.termtype,
-                   PKT_INT, rows, PKT_INT, cols,
+                   PKT_INT, ssh_term_height,
+                   PKT_INT, ssh_term_width,
                    PKT_INT, 0, PKT_INT, 0, PKT_CHAR, 0, PKT_END);
        ssh_state = SSH_STATE_INTERMED;
        do {
@@ -3175,7 +3189,7 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt)
 
     ssh_state = SSH_STATE_SESSION;
     if (size_needed)
-       ssh_size();
+       ssh_size(ssh_term_width, ssh_term_height);
     if (eof_needed)
        ssh_special(TS_EOF);
 
@@ -3189,7 +3203,7 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt)
                pktin.type == SSH1_SMSG_STDERR_DATA) {
                long len = GET_32BIT(pktin.body);
                int bufsize =
-                   from_backend(pktin.type == SSH1_SMSG_STDERR_DATA,
+                   from_backend(frontend, pktin.type == SSH1_SMSG_STDERR_DATA,
                                 pktin.body + 4, len);
                if (!ssh1_stdout_throttling && bufsize > SSH1_BUFFER_LIMIT) {
                    ssh1_stdout_throttling = 1;
@@ -3633,7 +3647,7 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
     /*
      * Be prepared to work around the buggy MAC problem.
      */
-    if (cfg.buggymac || (ssh_remote_bugs & BUG_SSH2_HMAC))
+    if (ssh_remote_bugs & BUG_SSH2_HMAC)
        maclist = buggymacs, nmacs = lenof(buggymacs);
     else
        maclist = macs, nmacs = lenof(macs);
@@ -3648,6 +3662,9 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
     /* List key exchange algorithms. */
     ssh2_pkt_addstring_start();
     for (i = 0; i < lenof(kex_algs); i++) {
+       if (kex_algs[i] == &ssh_diffiehellman_gex &&
+           (ssh_remote_bugs & BUG_SSH2_DH_GEX))
+           continue;
        ssh2_pkt_addstring_str(kex_algs[i]->name);
        if (i < lenof(kex_algs) - 1)
            ssh2_pkt_addstring_str(",");
@@ -3754,6 +3771,9 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
     pktin.savedpos += 16;             /* skip garbage cookie */
     ssh2_pkt_getstring(&str, &len);    /* key exchange algorithms */
     for (i = 0; i < lenof(kex_algs); i++) {
+       if (kex_algs[i] == &ssh_diffiehellman_gex &&
+           (ssh_remote_bugs & BUG_SSH2_DH_GEX))
+           continue;
        if (in_commasep_string(kex_algs[i]->name, str, len)) {
            kex = kex_algs[i];
            break;
@@ -5127,8 +5147,8 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
        ssh2_pkt_addstring("pty-req");
        ssh2_pkt_addbool(1);           /* want reply */
        ssh2_pkt_addstring(cfg.termtype);
-       ssh2_pkt_adduint32(cols);
-       ssh2_pkt_adduint32(rows);
+       ssh2_pkt_adduint32(ssh_term_width);
+       ssh2_pkt_adduint32(ssh_term_height);
        ssh2_pkt_adduint32(0);         /* pixel width */
        ssh2_pkt_adduint32(0);         /* pixel height */
        ssh2_pkt_addstring_start();
@@ -5233,7 +5253,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
 
     ssh_state = SSH_STATE_SESSION;
     if (size_needed)
-       ssh_size();
+       ssh_size(ssh_term_width, ssh_term_height);
     if (eof_needed)
        ssh_special(TS_EOF);
 
@@ -5266,7 +5286,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
                    switch (c->type) {
                      case CHAN_MAINSESSION:
                        bufsize =
-                           from_backend(pktin.type ==
+                           from_backend(frontend, pktin.type ==
                                         SSH2_MSG_CHANNEL_EXTENDED_DATA,
                                         data, length);
                        break;
@@ -5691,7 +5711,8 @@ static void ssh2_protocol(unsigned char *in, int inlen, int ispkt)
  *
  * Returns an error message, or NULL on success.
  */
-static char *ssh_init(char *host, int port, char **realhost, int nodelay)
+static char *ssh_init(void *frontend_handle,
+                     char *host, int port, char **realhost, int nodelay)
 {
     char *p;
 
@@ -5700,6 +5721,10 @@ static char *ssh_init(char *host, int port, char **realhost, int nodelay)
        return "Microsoft high encryption pack not installed!";
 #endif
 
+    frontend = frontend_handle;
+    ssh_term_width = cfg.width;
+    ssh_term_height = cfg.height;
+
     ssh_send_ok = 0;
     ssh_editing = 0;
     ssh_echoing = 0;
@@ -5760,8 +5785,11 @@ static int ssh_sendbuffer(void)
 /*
  * Called to set the size of the window from SSH's POV.
  */
-static void ssh_size(void)
+static void ssh_size(int width, int height)
 {
+    ssh_term_width = width;
+    ssh_term_height = height;
+
     switch (ssh_state) {
       case SSH_STATE_BEFORE_SIZE:
       case SSH_STATE_PREPACKET:
@@ -5772,17 +5800,19 @@ static void ssh_size(void)
        break;
       case SSH_STATE_SESSION:
        if (!cfg.nopty) {
+           if (!term)
+               return;
            if (ssh_version == 1) {
                send_packet(SSH1_CMSG_WINDOW_SIZE,
-                           PKT_INT, rows, PKT_INT, cols,
+                           PKT_INT, ssh_term_height, PKT_INT, ssh_term_width,
                            PKT_INT, 0, PKT_INT, 0, PKT_END);
            } else {
                ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
                ssh2_pkt_adduint32(mainchan->remoteid);
                ssh2_pkt_addstring("window-change");
                ssh2_pkt_addbool(0);
-               ssh2_pkt_adduint32(cols);
-               ssh2_pkt_adduint32(rows);
+               ssh2_pkt_adduint32(ssh_term_width);
+               ssh2_pkt_adduint32(ssh_term_height);
                ssh2_pkt_adduint32(0);
                ssh2_pkt_adduint32(0);
                ssh2_pkt_send();