X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/beff003a9e3e1b746473ea81f3ffad3dfcfc5f6f..208a0f09f8b18915b46d6ad39fc7c2c8f62fb930:/ssh.c diff --git a/ssh.c b/ssh.c index 6471c4b8..ef503bf5 100644 --- a/ssh.c +++ b/ssh.c @@ -558,7 +558,15 @@ enum { /* channel types */ CHAN_X11, CHAN_AGENT, CHAN_SOCKDATA, - CHAN_SOCKDATA_DORMANT /* one the remote hasn't confirmed */ + CHAN_SOCKDATA_DORMANT, /* one the remote hasn't confirmed */ + /* + * CHAN_ZOMBIE is used to indicate a channel for which we've + * already destroyed the local data source: for instance, if a + * forwarded port experiences a socket error on the local side, we + * immediately destroy its local socket and turn the SSH channel + * into CHAN_ZOMBIE. + */ + CHAN_ZOMBIE }; /* @@ -4250,6 +4258,35 @@ void sshfwd_write_eof(struct ssh_channel *c) ssh_channel_try_eof(c); } +void sshfwd_unclean_close(struct ssh_channel *c) +{ + Ssh ssh = c->ssh; + struct Packet *pktout; + + if (ssh->state == SSH_STATE_CLOSED) + return; + + if (!(c->closes & CLOSES_SENT_CLOSE)) { + pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_CLOSE); + ssh2_pkt_adduint32(pktout, c->remoteid); + ssh2_pkt_send(ssh, pktout); + c->closes |= CLOSES_SENT_EOF | CLOSES_SENT_CLOSE; + } + + switch (c->type) { + case CHAN_X11: + x11_close(c->u.x11.s); + break; + case CHAN_SOCKDATA: + case CHAN_SOCKDATA_DORMANT: + pfd_close(c->u.pfd.s); + break; + } + c->type = CHAN_ZOMBIE; + + ssh2_channel_check_close(c); +} + int sshfwd_write(struct ssh_channel *c, char *buf, int len) { Ssh ssh = c->ssh; @@ -5741,6 +5778,12 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen, break; } } + if (!ssh->hostkey) { + bombout(("Couldn't agree a host key algorithm (available: %s)", + str ? str : "(null)")); + crStop(0); + } + s->guessok = s->guessok && first_in_commasep_string(hostkey_algs[0]->name, str, len); ssh_pkt_getstring(pktin, &str, &len); /* client->server cipher */ @@ -6564,7 +6607,6 @@ static void ssh2_set_window(struct ssh_channel *c, int newwin) */ if ((ssh->remote_bugs & BUG_SSH2_MAXPKT) && newwin > OUR_V2_MAXPKT) newwin = OUR_V2_MAXPKT; - /* * Only send a WINDOW_ADJUST if there's significantly more window @@ -7000,7 +7042,7 @@ static void ssh2_msg_channel_close(Ssh ssh, struct Packet *pktin) /* * Send outgoing EOF. */ - sshfwd_write_eof(ssh->mainchan); + sshfwd_write_eof(c); } /* @@ -10001,6 +10043,12 @@ static void ssh_unthrottle(void *handle, int bufsize) } } } + + /* + * Now process any SSH connection data that was stashed in our + * queue while we were frozen. + */ + ssh_process_queued_incoming_data(ssh); } void ssh_send_port_open(void *channel, char *hostname, int port, char *org)