1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 18:07:59 +00:00

Hiroshi Oota points out that PuTTY's agent forwarding sockets can get

confused if they receive a request followed by immediate EOF, since we
currently send outgoing EOF as soon as we see the incoming one - and
then, when the response comes back from the real SSH agent, we send it
along anyway as channel data in spite of having sent EOF.

To fix this, I introduce a new field for each agent channel which
counts the number of calls to ssh_agentf_callback that are currently
expected, and we don't send EOF on an agent channel until we've both
received EOF and that value drops to zero.

[originally from svn r9651]
This commit is contained in:
Simon Tatham 2012-09-08 10:40:36 +00:00
parent 33c58dd91b
commit 14539a7719

14
ssh.c
View File

@ -666,6 +666,7 @@ struct ssh_channel {
unsigned char *message; unsigned char *message;
unsigned char msglen[4]; unsigned char msglen[4];
unsigned lensofar, totallen; unsigned lensofar, totallen;
int outstanding_requests;
} a; } a;
struct ssh_x11_channel { struct ssh_x11_channel {
Socket s; Socket s;
@ -3201,6 +3202,7 @@ static void ssh_agentf_callback(void *cv, void *reply, int replylen)
Ssh ssh = c->ssh; Ssh ssh = c->ssh;
void *sentreply = reply; void *sentreply = reply;
c->u.a.outstanding_requests--;
if (!sentreply) { if (!sentreply) {
/* Fake SSH_AGENT_FAILURE. */ /* Fake SSH_AGENT_FAILURE. */
sentreply = "\0\0\0\1\5"; sentreply = "\0\0\0\1\5";
@ -3220,6 +3222,12 @@ static void ssh_agentf_callback(void *cv, void *reply, int replylen)
} }
if (reply) if (reply)
sfree(reply); sfree(reply);
/*
* If we've already seen an incoming EOF but haven't sent an
* outgoing one, this may be the moment to send it.
*/
if (c->u.a.outstanding_requests == 0 && (c->closes & CLOSES_RCVD_EOF))
sshfwd_write_eof(c);
} }
/* /*
@ -4827,6 +4835,7 @@ static void ssh1_smsg_agent_open(Ssh ssh, struct Packet *pktin)
c->type = CHAN_AGENT; /* identify channel type */ c->type = CHAN_AGENT; /* identify channel type */
c->u.a.lensofar = 0; c->u.a.lensofar = 0;
c->u.a.message = NULL; c->u.a.message = NULL;
c->u.a.outstanding_requests = 0;
add234(ssh->channels, c); add234(ssh->channels, c);
send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION, send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
PKT_INT, c->remoteid, PKT_INT, c->localid, PKT_INT, c->remoteid, PKT_INT, c->localid,
@ -5052,6 +5061,7 @@ static void ssh1_msg_channel_data(Ssh ssh, struct Packet *pktin)
if (c->u.a.lensofar == c->u.a.totallen) { if (c->u.a.lensofar == c->u.a.totallen) {
void *reply; void *reply;
int replylen; int replylen;
c->u.a.outstanding_requests++;
if (agent_query(c->u.a.message, if (agent_query(c->u.a.message,
c->u.a.totallen, c->u.a.totallen,
&reply, &replylen, &reply, &replylen,
@ -6847,6 +6857,7 @@ static void ssh2_msg_channel_data(Ssh ssh, struct Packet *pktin)
if (c->u.a.lensofar == c->u.a.totallen) { if (c->u.a.lensofar == c->u.a.totallen) {
void *reply; void *reply;
int replylen; int replylen;
c->u.a.outstanding_requests++;
if (agent_query(c->u.a.message, if (agent_query(c->u.a.message,
c->u.a.totallen, c->u.a.totallen,
&reply, &replylen, &reply, &replylen,
@ -6985,8 +6996,10 @@ static void ssh2_channel_got_eof(struct ssh_channel *c)
if (c->type == CHAN_X11) { if (c->type == CHAN_X11) {
x11_send_eof(c->u.x11.s); x11_send_eof(c->u.x11.s);
} else if (c->type == CHAN_AGENT) { } else if (c->type == CHAN_AGENT) {
if (c->u.a.outstanding_requests == 0) {
/* Manufacture an outgoing EOF in response to the incoming one. */ /* Manufacture an outgoing EOF in response to the incoming one. */
sshfwd_write_eof(c); sshfwd_write_eof(c);
}
} else if (c->type == CHAN_SOCKDATA) { } else if (c->type == CHAN_SOCKDATA) {
pfd_send_eof(c->u.pfd.s); pfd_send_eof(c->u.pfd.s);
} else if (c->type == CHAN_MAINSESSION) { } else if (c->type == CHAN_MAINSESSION) {
@ -7408,6 +7421,7 @@ static void ssh2_msg_channel_open(Ssh ssh, struct Packet *pktin)
else { else {
c->type = CHAN_AGENT; /* identify channel type */ c->type = CHAN_AGENT; /* identify channel type */
c->u.a.lensofar = 0; c->u.a.lensofar = 0;
c->u.a.outstanding_requests = 0;
} }
} else { } else {
error = "Unsupported channel type requested"; error = "Unsupported channel type requested";