]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - ssh.c
Don't try sending on sharing channels.
[PuTTY.git] / ssh.c
diff --git a/ssh.c b/ssh.c
index d531dfd49d2d95fc956f4f8e0635608f0d7099ca..dd9696225bdf79e98b2b16bd57130f944395cc83 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -76,6 +76,10 @@ static const char *const ssh2_disconnect_reasons[] = {
 #define BUG_CHOKES_ON_SSH2_IGNORE               512
 #define BUG_CHOKES_ON_WINADJ                   1024
 #define BUG_SENDS_LATE_REQUEST_REPLY           2048
+#define BUG_SSH2_OLDGEX                        4096
+
+#define DH_MIN_SIZE 1024
+#define DH_MAX_SIZE 8192
 
 /*
  * Codes for terminal modes.
@@ -247,6 +251,7 @@ static char *ssh2_pkt_type(Pkt_KCtx pkt_kctx, Pkt_ACtx pkt_actx, int type)
     translate(SSH2_MSG_NEWKEYS);
     translatek(SSH2_MSG_KEXDH_INIT, SSH2_PKTCTX_DHGROUP);
     translatek(SSH2_MSG_KEXDH_REPLY, SSH2_PKTCTX_DHGROUP);
+    translatek(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD, SSH2_PKTCTX_DHGEX);
     translatek(SSH2_MSG_KEX_DH_GEX_REQUEST, SSH2_PKTCTX_DHGEX);
     translatek(SSH2_MSG_KEX_DH_GEX_GROUP, SSH2_PKTCTX_DHGEX);
     translatek(SSH2_MSG_KEX_DH_GEX_INIT, SSH2_PKTCTX_DHGEX);
@@ -2805,6 +2810,17 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring)
        logevent("We believe remote version has SSH-2 ignore bug");
     }
 
+    if (conf_get_int(ssh->conf, CONF_sshbug_oldgex2) == FORCE_ON ||
+       (conf_get_int(ssh->conf, CONF_sshbug_oldgex2) == AUTO &&
+        (wc_match("OpenSSH_2.[235]*", imp)))) {
+       /*
+        * These versions only support the original (pre-RFC4419)
+        * SSH-2 GEX request.
+        */
+       ssh->remote_bugs |= BUG_SSH2_OLDGEX;
+       logevent("We believe remote version has outdated SSH-2 GEX");
+    }
+
     if (conf_get_int(ssh->conf, CONF_sshbug_winadj) == FORCE_ON) {
        /*
         * Servers that don't support our winadj request for one
@@ -2817,11 +2833,15 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring)
     if (conf_get_int(ssh->conf, CONF_sshbug_chanreq) == FORCE_ON ||
        (conf_get_int(ssh->conf, CONF_sshbug_chanreq) == AUTO &&
         (wc_match("OpenSSH_[2-5].*", imp) ||
-         wc_match("OpenSSH_6.[0-6]*", imp)))) {
+         wc_match("OpenSSH_6.[0-6]*", imp) ||
+         wc_match("dropbear_0.[2-4][0-9]*", imp) ||
+         wc_match("dropbear_0.5[01]*", imp)))) {
        /*
-        * These versions have the SSH-2 channel request bug. 6.7 and
-        * above do not:
+        * These versions have the SSH-2 channel request bug.
+        * OpenSSH 6.7 and above do not:
         * https://bugzilla.mindrot.org/show_bug.cgi?id=1818
+        * dropbear_0.52 and above do not:
+        * https://secure.ucc.asn.au/hg/dropbear/rev/cd02449b709c
         */
        ssh->remote_bugs |= BUG_SENDS_LATE_REQUEST_REPLY;
        logevent("We believe remote version has SSH-2 channel request bug");
@@ -6591,8 +6611,19 @@ static void do_ssh2_transport(Ssh ssh, void *vin, int inlen,
              * much data.
              */
             s->pbits = 512 << ((s->nbits - 1) / 64);
-            s->pktout = ssh2_pkt_init(SSH2_MSG_KEX_DH_GEX_REQUEST);
-            ssh2_pkt_adduint32(s->pktout, s->pbits);
+            if (s->pbits < DH_MIN_SIZE)
+                s->pbits = DH_MIN_SIZE;
+            if (s->pbits > DH_MAX_SIZE)
+                s->pbits = DH_MAX_SIZE;
+            if ((ssh->remote_bugs & BUG_SSH2_OLDGEX)) {
+                s->pktout = ssh2_pkt_init(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD);
+                ssh2_pkt_adduint32(s->pktout, s->pbits);
+            } else {
+                s->pktout = ssh2_pkt_init(SSH2_MSG_KEX_DH_GEX_REQUEST);
+                ssh2_pkt_adduint32(s->pktout, DH_MIN_SIZE);
+                ssh2_pkt_adduint32(s->pktout, s->pbits);
+                ssh2_pkt_adduint32(s->pktout, DH_MAX_SIZE);
+            }
             ssh2_pkt_send_noqueue(ssh, s->pktout);
 
             crWaitUntilV(pktin);
@@ -6645,6 +6676,13 @@ static void do_ssh2_transport(Ssh ssh, void *vin, int inlen,
         }
         ssh_pkt_getstring(pktin, &s->sigdata, &s->siglen);
 
+        {
+            const char *err = dh_validate_f(ssh->kex_ctx, s->f);
+            if (err) {
+                bombout(("key exchange reply failed validation: %s", err));
+                crStopV;
+            }
+        }
         s->K = dh_find_K(ssh->kex_ctx, s->f);
 
         /* We assume everything from now on will be quick, and it might
@@ -6653,7 +6691,11 @@ static void do_ssh2_transport(Ssh ssh, void *vin, int inlen,
 
         hash_string(ssh->kex->hash, ssh->exhash, s->hostkeydata, s->hostkeylen);
         if (!ssh->kex->pdata) {
+            if (!(ssh->remote_bugs & BUG_SSH2_OLDGEX))
+                hash_uint32(ssh->kex->hash, ssh->exhash, DH_MIN_SIZE);
             hash_uint32(ssh->kex->hash, ssh->exhash, s->pbits);
+            if (!(ssh->remote_bugs & BUG_SSH2_OLDGEX))
+                hash_uint32(ssh->kex->hash, ssh->exhash, DH_MAX_SIZE);
             hash_mpint(ssh->kex->hash, ssh->exhash, s->p);
             hash_mpint(ssh->kex->hash, ssh->exhash, s->g);
         }
@@ -7566,9 +7608,14 @@ static void ssh_check_termination(Ssh ssh)
     }
 }
 
-void ssh_sharing_downstream_connected(Ssh ssh, unsigned id)
+void ssh_sharing_downstream_connected(Ssh ssh, unsigned id,
+                                      const char *peerinfo)
 {
-    logeventf(ssh, "Connection sharing downstream #%u connected", id);
+    if (peerinfo)
+        logeventf(ssh, "Connection sharing downstream #%u connected from %s",
+                  id, peerinfo);
+    else
+        logeventf(ssh, "Connection sharing downstream #%u connected", id);
 }
 
 void ssh_sharing_downstream_disconnected(Ssh ssh, unsigned id)
@@ -9416,6 +9463,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
                     logevent("Sent public key signature");
                    s->type = AUTH_TYPE_PUBLICKEY;
                    key->alg->freekey(key->data);
+                    sfree(key->comment);
+                    sfree(key);
                }
 
 #ifndef NO_GSSAPI
@@ -10276,7 +10325,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
             * Try to send data on all channels if we can.
             */
            for (i = 0; NULL != (c = index234(ssh->channels, i)); i++)
-               ssh2_try_send_and_unthrottle(ssh, c);
+                if (c->type != CHAN_SHARING)
+                    ssh2_try_send_and_unthrottle(ssh, c);
        }
     }
 
@@ -10598,6 +10648,8 @@ static const char *ssh_init(void *frontend_handle, void **backend_handle,
     ssh->sent_console_eof = FALSE;
     ssh->got_pty = FALSE;
     ssh->bare_connection = FALSE;
+    ssh->X11_fwd_enabled = FALSE;
+    ssh->connshare = NULL;
     ssh->attempting_connshare = FALSE;
 
     *backend_handle = ssh;