ssh_do_close() was only closing about half the channels. Fixed.
[u/mdw/putty] / ssh.c
diff --git a/ssh.c b/ssh.c
index ea4771c..825731e 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -2247,13 +2247,7 @@ static int do_ssh_init(Ssh ssh, unsigned char c)
 
     s->vstring[s->vslen] = 0;
     s->vstring[strcspn(s->vstring, "\015\012")] = '\0';/* remove EOL chars */
-    {
-       char *vlog;
-       vlog = snewn(20 + s->vslen, char);
-       sprintf(vlog, "Server version: %s", s->vstring);
-       logevent(vlog);
-       sfree(vlog);
-    }
+    logeventf(ssh, "Server version: %s", s->vstring);
     ssh_detect_bugs(ssh, s->vstring);
 
     /*
@@ -2383,7 +2377,7 @@ static void ssh_gotdata(Ssh ssh, unsigned char *data, int datalen)
 
 static int ssh_do_close(Ssh ssh, int notify_exit)
 {
-    int i, ret = 0;
+    int ret = 0;
     struct ssh_channel *c;
 
     ssh->state = SSH_STATE_CLOSED;
@@ -2396,11 +2390,11 @@ static int ssh_do_close(Ssh ssh, int notify_exit)
             ret = 1;
     }
     /*
-     * Now we must shut down any port and X forwardings going
+     * Now we must shut down any port- and X-forwarded channels going
      * through this connection.
      */
     if (ssh->channels) {
-       for (i = 0; NULL != (c = index234(ssh->channels, i)); i++) {
+       while (NULL != (c = index234(ssh->channels, 0))) {
            switch (c->type) {
              case CHAN_X11:
                x11_close(c->u.x11.s);
@@ -2409,7 +2403,7 @@ static int ssh_do_close(Ssh ssh, int notify_exit)
                pfd_close(c->u.pfd.s);
                break;
            }
-           del234(ssh->channels, c);
+           del234(ssh->channels, c); /* moving next one to index 0 */
            if (ssh->version == 2)
                bufchain_clear(&c->v.v2.outbuffer);
            sfree(c);
@@ -2433,6 +2427,7 @@ static void ssh_log(Plug plug, int type, SockAddr addr, int port,
        msg = dupprintf("Failed to connect to %s: %s", addrbuf, error_msg);
 
     logevent(msg);
+    sfree(msg);
 }
 
 static int ssh_closing(Plug plug, const char *error_msg, int error_code,
@@ -3047,17 +3042,9 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen,
                s->p = s->response + 5;
                s->nkeys = GET_32BIT(s->p);
                s->p += 4;
-               {
-                   char buf[64];
-                   sprintf(buf, "Pageant has %d SSH1 keys", s->nkeys);
-                   logevent(buf);
-               }
+               logeventf(ssh, "Pageant has %d SSH1 keys", s->nkeys);
                for (s->keyi = 0; s->keyi < s->nkeys; s->keyi++) {
-                   {
-                       char buf[64];
-                       sprintf(buf, "Trying Pageant key #%d", s->keyi);
-                       logevent(buf);
-                   }
+                   logeventf(ssh, "Trying Pageant key #%d", s->keyi);
                    if (s->publickey_blob &&
                        !memcmp(s->p, s->publickey_blob,
                                s->publickey_bloblen)) {
@@ -3266,18 +3253,18 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen,
        if (s->pwpkt_type == SSH1_CMSG_AUTH_RSA) {
            char *comment = NULL;
            int type;
-           char msgbuf[256];
            if (flags & FLAG_VERBOSE)
                c_write_str(ssh, "Trying public key authentication.\r\n");
            logeventf(ssh, "Trying public key \"%s\"",
                      filename_to_str(&ssh->cfg.keyfile));
            type = key_type(&ssh->cfg.keyfile);
            if (type != SSH_KEYTYPE_SSH1) {
-               sprintf(msgbuf, "Key is of wrong type (%s)",
-                       key_type_to_str(type));
-               logevent(msgbuf);
-               c_write_str(ssh, msgbuf);
+               char *msg = dupprintf("Key is of wrong type (%s)",
+                                     key_type_to_str(type));
+               logevent(msg);
+               c_write_str(ssh, msg);
                c_write_str(ssh, "\r\n");
+               sfree(msg);
                s->tried_publickey = 1;
                continue;
            }
@@ -3821,6 +3808,8 @@ static void ssh_setup_portfwd(Ssh ssh, const Config *cfg)
            }
        } else {
            while (*portfwd_strptr) portfwd_strptr++;
+           host[0] = 0;
+           dports[0] = 0;
            dport = dserv = -1;
            portfwd_strptr++;          /* eat the NUL and move to next one */
        }
@@ -3916,6 +3905,9 @@ static void ssh_setup_portfwd(Ssh ssh, const Config *cfg)
                    if (epf->saddr) {
                        ssh2_pkt_addstring(pktout, epf->saddr);
                    } else if (ssh->cfg.rport_acceptall) {
+                       /* XXX: ssh->cfg.rport_acceptall may not represent
+                        * what was used to open the original connection,
+                        * since it's reconfigurable. */
                        ssh2_pkt_addstring(pktout, "0.0.0.0");
                    } else {
                        ssh2_pkt_addstring(pktout, "127.0.0.1");
@@ -3962,7 +3954,7 @@ static void ssh_setup_portfwd(Ssh ssh, const Config *cfg)
            if (epf->type == 'L') {
                const char *err = pfd_addforward(epf->daddr, epf->dport,
                                                 epf->saddr, epf->sport,
-                                                ssh, &ssh->cfg,
+                                                ssh, cfg,
                                                 &epf->local,
                                                 epf->addressfamily);
 
@@ -3974,7 +3966,7 @@ static void ssh_setup_portfwd(Ssh ssh, const Config *cfg)
            } else if (epf->type == 'D') {
                const char *err = pfd_addforward(NULL, -1,
                                                 epf->saddr, epf->sport,
-                                                ssh, &ssh->cfg,
+                                                ssh, cfg,
                                                 &epf->local,
                                                 epf->addressfamily);
 
@@ -4030,7 +4022,7 @@ static void ssh_setup_portfwd(Ssh ssh, const Config *cfg)
                        ssh2_pkt_addbool(pktout, 1);/* want reply */
                        if (epf->saddr) {
                            ssh2_pkt_addstring(pktout, epf->saddr);
-                       } else if (ssh->cfg.rport_acceptall) {
+                       } else if (cfg->rport_acceptall) {
                            ssh2_pkt_addstring(pktout, "0.0.0.0");
                        } else {
                            ssh2_pkt_addstring(pktout, "127.0.0.1");
@@ -4145,7 +4137,7 @@ static void ssh1_msg_port_open(Ssh ssh, struct Packet *pktin)
     struct ssh_rportfwd pf, *pfp;
     int remoteid;
     int hostsize, port;
-    char *host, buf[1024];
+    char *host;
     const char *e;
     c = snew(struct ssh_channel);
     c->ssh = ssh;
@@ -4162,21 +4154,17 @@ static void ssh1_msg_port_open(Ssh ssh, struct Packet *pktin)
     pfp = find234(ssh->rportfwds, &pf, NULL);
 
     if (pfp == NULL) {
-       sprintf(buf, "Rejected remote port open request for %s:%d",
-               pf.dhost, port);
-       logevent(buf);
+       logeventf(ssh, "Rejected remote port open request for %s:%d",
+                 pf.dhost, port);
        send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
                    PKT_INT, remoteid, PKT_END);
     } else {
-       sprintf(buf, "Received remote port open request for %s:%d",
-               pf.dhost, port);
-       logevent(buf);
+       logeventf(ssh, "Received remote port open request for %s:%d",
+                 pf.dhost, port);
        e = pfd_newconnect(&c->u.pfd.s, pf.dhost, port,
                           c, &ssh->cfg, pfp->pfrec->addressfamily);
        if (e != NULL) {
-           char buf[256];
-           sprintf(buf, "Port open failed: %s", e);
-           logevent(buf);
+           logeventf(ssh, "Port open failed: %s", e);
            sfree(c);
            send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
                        PKT_INT, remoteid, PKT_END);
@@ -4352,11 +4340,8 @@ static void ssh1_msg_channel_data(Ssh ssh, struct Packet *pktin)
 
 static void ssh1_smsg_exit_status(Ssh ssh, struct Packet *pktin)
 {
-    char buf[100];
     ssh->exitcode = ssh_pkt_getuint32(pktin);
-    sprintf(buf, "Server sent command exit status %d",
-           ssh->exitcode);
-    logevent(buf);
+    logeventf(ssh, "Server sent command exit status %d", ssh->exitcode);
     send_packet(ssh, SSH1_CMSG_EXIT_CONFIRMATION, PKT_END);
     /*
      * In case `helpful' firewalls or proxies tack
@@ -4563,13 +4548,11 @@ static void do_ssh1_connection(Ssh ssh, unsigned char *in, int inlen,
  */
 static void ssh1_msg_debug(Ssh ssh, struct Packet *pktin)
 {
-    char *buf, *msg;
+    char *msg;
     int msglen;
 
     ssh_pkt_getstring(pktin, &msg, &msglen);
-    buf = dupprintf("Remote debug message: %.*s", msglen, msg);
-    logevent(buf);
-    sfree(buf);
+    logeventf(ssh, "Remote debug message: %.*s", msglen, msg);
 }
 
 static void ssh1_msg_disconnect(Ssh ssh, struct Packet *pktin)
@@ -5161,16 +5144,19 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
     /*
      * Now generate and send e for Diffie-Hellman.
      */
+    set_busy_status(ssh->frontend, BUSY_CPU); /* this can take a while */
     s->e = dh_create_e(ssh->kex_ctx, s->nbits * 2);
     s->pktout = ssh2_pkt_init(s->kex_init_value);
     ssh2_pkt_addmp(s->pktout, s->e);
     ssh2_pkt_send_noqueue(ssh, s->pktout);
 
+    set_busy_status(ssh->frontend, BUSY_WAITING); /* wait for server */
     crWaitUntil(pktin);
     if (pktin->type != s->kex_reply_value) {
        bombout(("expected key exchange reply packet from server"));
        crStop(0);
     }
+    set_busy_status(ssh->frontend, BUSY_CPU); /* cogitate */
     ssh_pkt_getstring(pktin, &s->hostkeydata, &s->hostkeylen);
     s->f = ssh2_pkt_getmp(pktin);
     if (!s->f) {
@@ -5181,6 +5167,10 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
 
     s->K = dh_find_K(ssh->kex_ctx, s->f);
 
+    /* We assume everything from now on will be quick, and it might
+     * involve user interaction. */
+    set_busy_status(ssh->frontend, BUSY_NOT);
+
     sha_string(&ssh->exhash, s->hostkeydata, s->hostkeylen);
     if (ssh->kex == &ssh_diffiehellman_gex) {
        sha_uint32(&ssh->exhash, s->pbits);
@@ -5737,7 +5727,6 @@ static void ssh2_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
     unsigned reason_code;
     char *reason_string;
     int reason_length;
-    char *message;
     struct ssh_channel *c;
     c = find234(ssh->channels, &i, ssh_channelfind);
     if (!c)
@@ -5749,11 +5738,8 @@ static void ssh2_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
     if (reason_code >= lenof(reasons))
        reason_code = 0; /* ensure reasons[reason_code] in range */
     ssh_pkt_getstring(pktin, &reason_string, &reason_length);
-    message = dupprintf("Forwarded connection refused by"
-                       " server: %s [%.*s]", reasons[reason_code],
-                       reason_length, reason_string);
-    logevent(message);
-    sfree(message);
+    logeventf(ssh, "Forwarded connection refused by server: %s [%.*s]",
+             reasons[reason_code], reason_length, reason_string);
 
     pfd_close(c->u.pfd.s);
 
@@ -6388,19 +6374,11 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
                    s->p = s->response + 5;
                    s->nkeys = GET_32BIT(s->p);
                    s->p += 4;
-                   {
-                       char buf[64];
-                       sprintf(buf, "Pageant has %d SSH2 keys", s->nkeys);
-                       logevent(buf);
-                   }
+                   logeventf(ssh, "Pageant has %d SSH2 keys", s->nkeys);
                    for (s->keyi = 0; s->keyi < s->nkeys; s->keyi++) {
                        void *vret;
 
-                       {
-                           char buf[64];
-                           sprintf(buf, "Trying Pageant key #%d", s->keyi);
-                           logevent(buf);
-                       }
+                       logeventf(ssh, "Trying Pageant key #%d", s->keyi);
                        s->pklen = GET_32BIT(s->p);
                        s->p += 4;
                        if (s->publickey_blob &&
@@ -7288,7 +7266,7 @@ static void ssh2_msg_disconnect(Ssh ssh, struct Packet *pktin)
 static void ssh2_msg_debug(Ssh ssh, struct Packet *pktin)
 {
     /* log the debug message */
-    char *buf, *msg;
+    char *msg;
     int msglen;
     int always_display;
 
@@ -7296,9 +7274,7 @@ static void ssh2_msg_debug(Ssh ssh, struct Packet *pktin)
     always_display = ssh2_pkt_getbool(pktin);
     ssh_pkt_getstring(pktin, &msg, &msglen);
 
-    buf = dupprintf("Remote debug message: %.*s", msglen, msg);
-    logevent(buf);
-    sfree(buf);
+    logeventf(ssh, "Remote debug message: %.*s", msglen, msg);
 }
 
 static void ssh2_msg_something_unimplemented(Ssh ssh, struct Packet *pktin)