1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +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

18
ssh.c
View File

@ -666,6 +666,7 @@ struct ssh_channel {
unsigned char *message;
unsigned char msglen[4];
unsigned lensofar, totallen;
int outstanding_requests;
} a;
struct ssh_x11_channel {
Socket s;
@ -3201,6 +3202,7 @@ static void ssh_agentf_callback(void *cv, void *reply, int replylen)
Ssh ssh = c->ssh;
void *sentreply = reply;
c->u.a.outstanding_requests--;
if (!sentreply) {
/* Fake SSH_AGENT_FAILURE. */
sentreply = "\0\0\0\1\5";
@ -3220,6 +3222,12 @@ static void ssh_agentf_callback(void *cv, void *reply, int replylen)
}
if (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->u.a.lensofar = 0;
c->u.a.message = NULL;
c->u.a.outstanding_requests = 0;
add234(ssh->channels, c);
send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
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) {
void *reply;
int replylen;
c->u.a.outstanding_requests++;
if (agent_query(c->u.a.message,
c->u.a.totallen,
&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) {
void *reply;
int replylen;
c->u.a.outstanding_requests++;
if (agent_query(c->u.a.message,
c->u.a.totallen,
&reply, &replylen,
@ -6985,8 +6996,10 @@ static void ssh2_channel_got_eof(struct ssh_channel *c)
if (c->type == CHAN_X11) {
x11_send_eof(c->u.x11.s);
} else if (c->type == CHAN_AGENT) {
/* Manufacture an outgoing EOF in response to the incoming one. */
sshfwd_write_eof(c);
if (c->u.a.outstanding_requests == 0) {
/* Manufacture an outgoing EOF in response to the incoming one. */
sshfwd_write_eof(c);
}
} else if (c->type == CHAN_SOCKDATA) {
pfd_send_eof(c->u.pfd.s);
} else if (c->type == CHAN_MAINSESSION) {
@ -7408,6 +7421,7 @@ static void ssh2_msg_channel_open(Ssh ssh, struct Packet *pktin)
else {
c->type = CHAN_AGENT; /* identify channel type */
c->u.a.lensofar = 0;
c->u.a.outstanding_requests = 0;
}
} else {
error = "Unsupported channel type requested";