1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-26 09:42:25 +00:00

Don't close SSH-2 channels with outstanding channel requests on local error.

In sshfwd_unclean_close(), get ssh2_check_close() to handle sending
SSH_MSG_CHANNEL_CLOSE.  That way, it can hold off doing so until any
outstanding channel requests are processed.

Also add event log message for unclean channel closures.

[originally from svn r9631]
This commit is contained in:
Ben Harris 2012-08-27 17:37:44 +00:00
parent 3fa95b2a7f
commit 0768c8557d

26
ssh.c
View File

@ -4278,25 +4278,19 @@ void sshfwd_write_eof(struct ssh_channel *c)
void sshfwd_unclean_close(struct ssh_channel *c) void sshfwd_unclean_close(struct ssh_channel *c)
{ {
Ssh ssh = c->ssh; Ssh ssh = c->ssh;
struct Packet *pktout;
if (ssh->state == SSH_STATE_CLOSED) if (ssh->state == SSH_STATE_CLOSED)
return; 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) { switch (c->type) {
case CHAN_X11: case CHAN_X11:
x11_close(c->u.x11.s); x11_close(c->u.x11.s);
logevent("Forwarded X11 connection terminated due to local error");
break; break;
case CHAN_SOCKDATA: case CHAN_SOCKDATA:
case CHAN_SOCKDATA_DORMANT: case CHAN_SOCKDATA_DORMANT:
pfd_close(c->u.pfd.s); pfd_close(c->u.pfd.s);
logevent("Forwarded port closed due to local error");
break; break;
} }
c->type = CHAN_ZOMBIE; c->type = CHAN_ZOMBIE;
@ -6946,18 +6940,20 @@ static void ssh2_channel_check_close(struct ssh_channel *c)
Ssh ssh = c->ssh; Ssh ssh = c->ssh;
struct Packet *pktout; struct Packet *pktout;
if ((c->closes & (CLOSES_SENT_EOF | CLOSES_RCVD_EOF | CLOSES_SENT_CLOSE)) if ((!((CLOSES_SENT_EOF | CLOSES_RCVD_EOF) & ~c->closes) ||
== (CLOSES_SENT_EOF | CLOSES_RCVD_EOF) && !c->v.v2.chanreq_head) { c->type == CHAN_ZOMBIE) &&
!c->v.v2.chanreq_head &&
!(c->closes & CLOSES_SENT_CLOSE)) {
/* /*
* We have both sent and received EOF, and we have no * We have both sent and received EOF (or the channel is a
* outstanding channel requests, which means the * zombie), and we have no outstanding channel requests, which
* channel is in final wind-up. But we haven't sent CLOSE, so * means the channel is in final wind-up. But we haven't sent
* let's do so now. * CLOSE, so let's do so now.
*/ */
pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_CLOSE); pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_CLOSE);
ssh2_pkt_adduint32(pktout, c->remoteid); ssh2_pkt_adduint32(pktout, c->remoteid);
ssh2_pkt_send(ssh, pktout); ssh2_pkt_send(ssh, pktout);
c->closes |= CLOSES_SENT_CLOSE; c->closes |= CLOSES_SENT_EOF | CLOSES_SENT_CLOSE;
} }
if (!((CLOSES_SENT_CLOSE | CLOSES_RCVD_CLOSE) & ~c->closes)) { if (!((CLOSES_SENT_CLOSE | CLOSES_RCVD_CLOSE) & ~c->closes)) {