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

Merge the looking up of channel numbers for SSH-2 channel messages into

a single function which also handles checking that channels exist and
are properly open.  This should make PuTTY a little less tolerant of
servers that send bogus messages.

[originally from svn r7751]
This commit is contained in:
Ben Harris 2007-09-30 19:42:31 +00:00
parent ef370ee6fa
commit da5d553afc

82
ssh.c
View File

@ -6276,6 +6276,30 @@ static void ssh2_set_window(struct ssh_channel *c, int newwin)
} }
} }
/*
* Find the channel associated with a message. If there's no channel,
* or it's not properly open, make a noise about it and return NULL.
*/
static struct ssh_channel *ssh2_channel_msg(Ssh ssh, struct Packet *pktin)
{
unsigned localid = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
c = find234(ssh->channels, &localid, ssh_channelfind);
if (!c ||
(c->halfopen && pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION &&
pktin->type != SSH2_MSG_CHANNEL_OPEN_FAILURE)) {
char *buf = dupprintf("Received %s for %s channel %u",
ssh2_pkt_type(ssh->pkt_kctx, ssh->pkt_actx,
pktin->type),
c ? "half-open" : "nonexistent", localid);
ssh_disconnect(ssh, NULL, buf, SSH2_DISCONNECT_PROTOCOL_ERROR, FALSE);
sfree(buf);
return NULL;
}
return c;
}
static void ssh2_msg_channel_failure(Ssh ssh, struct Packet *pktin) static void ssh2_msg_channel_failure(Ssh ssh, struct Packet *pktin)
{ {
/* /*
@ -6284,13 +6308,12 @@ static void ssh2_msg_channel_failure(Ssh ssh, struct Packet *pktin)
* sent with want_reply false or are sent before this handler gets * sent with want_reply false or are sent before this handler gets
* installed. * installed.
*/ */
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c; struct ssh_channel *c;
struct winadj *wa; struct winadj *wa;
c = find234(ssh->channels, &i, ssh_channelfind); c = ssh2_channel_msg(ssh, pktin);
if (!c) if (!c)
return; /* nonexistent channel */ return;
wa = c->v.v2.winadj_head; wa = c->v.v2.winadj_head;
if (!wa) if (!wa)
logevent("excess SSH_MSG_CHANNEL_FAILURE"); logevent("excess SSH_MSG_CHANNEL_FAILURE");
@ -6310,10 +6333,11 @@ static void ssh2_msg_channel_failure(Ssh ssh, struct Packet *pktin)
static void ssh2_msg_channel_window_adjust(Ssh ssh, struct Packet *pktin) static void ssh2_msg_channel_window_adjust(Ssh ssh, struct Packet *pktin)
{ {
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c; struct ssh_channel *c;
c = find234(ssh->channels, &i, ssh_channelfind); c = ssh2_channel_msg(ssh, pktin);
if (c && !c->closes) { if (!c)
return;
if (!c->closes) {
c->v.v2.remwindow += ssh_pkt_getuint32(pktin); c->v.v2.remwindow += ssh_pkt_getuint32(pktin);
ssh2_try_send_and_unthrottle(c); ssh2_try_send_and_unthrottle(c);
} }
@ -6323,11 +6347,10 @@ static void ssh2_msg_channel_data(Ssh ssh, struct Packet *pktin)
{ {
char *data; char *data;
int length; int length;
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c; struct ssh_channel *c;
c = find234(ssh->channels, &i, ssh_channelfind); c = ssh2_channel_msg(ssh, pktin);
if (!c) if (!c)
return; /* nonexistent channel */ return;
if (pktin->type == SSH2_MSG_CHANNEL_EXTENDED_DATA && if (pktin->type == SSH2_MSG_CHANNEL_EXTENDED_DATA &&
ssh_pkt_getuint32(pktin) != SSH2_EXTENDED_DATA_STDERR) ssh_pkt_getuint32(pktin) != SSH2_EXTENDED_DATA_STDERR)
return; /* extended but not stderr */ return; /* extended but not stderr */
@ -6414,12 +6437,11 @@ static void ssh2_msg_channel_data(Ssh ssh, struct Packet *pktin)
static void ssh2_msg_channel_eof(Ssh ssh, struct Packet *pktin) static void ssh2_msg_channel_eof(Ssh ssh, struct Packet *pktin)
{ {
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c; struct ssh_channel *c;
c = find234(ssh->channels, &i, ssh_channelfind); c = ssh2_channel_msg(ssh, pktin);
if (!c) if (!c)
return; /* nonexistent channel */ return;
if (c->type == CHAN_X11) { if (c->type == CHAN_X11) {
/* /*
@ -6438,16 +6460,12 @@ static void ssh2_msg_channel_eof(Ssh ssh, struct Packet *pktin)
static void ssh2_msg_channel_close(Ssh ssh, struct Packet *pktin) static void ssh2_msg_channel_close(Ssh ssh, struct Packet *pktin)
{ {
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c; struct ssh_channel *c;
struct Packet *pktout; struct Packet *pktout;
c = find234(ssh->channels, &i, ssh_channelfind); c = ssh2_channel_msg(ssh, pktin);
if (!c || c->halfopen) { if (!c)
bombout(("Received CHANNEL_CLOSE for %s channel %d\n",
c ? "half-open" : "nonexistent", i));
return; return;
}
/* Do pre-close processing on the channel. */ /* Do pre-close processing on the channel. */
switch (c->type) { switch (c->type) {
case CHAN_MAINSESSION: case CHAN_MAINSESSION:
@ -6500,13 +6518,12 @@ static void ssh2_msg_channel_close(Ssh ssh, struct Packet *pktin)
static void ssh2_msg_channel_open_confirmation(Ssh ssh, struct Packet *pktin) static void ssh2_msg_channel_open_confirmation(Ssh ssh, struct Packet *pktin)
{ {
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c; struct ssh_channel *c;
struct Packet *pktout; struct Packet *pktout;
c = find234(ssh->channels, &i, ssh_channelfind); c = ssh2_channel_msg(ssh, pktin);
if (!c) if (!c)
return; /* nonexistent channel */ return;
if (c->type != CHAN_SOCKDATA_DORMANT) if (c->type != CHAN_SOCKDATA_DORMANT)
return; /* dunno why they're confirming this */ return; /* dunno why they're confirming this */
c->remoteid = ssh_pkt_getuint32(pktin); c->remoteid = ssh_pkt_getuint32(pktin);
@ -6538,14 +6555,13 @@ static void ssh2_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
"Unknown channel type", "Unknown channel type",
"Resource shortage", "Resource shortage",
}; };
unsigned i = ssh_pkt_getuint32(pktin);
unsigned reason_code; unsigned reason_code;
char *reason_string; char *reason_string;
int reason_length; int reason_length;
struct ssh_channel *c; struct ssh_channel *c;
c = find234(ssh->channels, &i, ssh_channelfind); c = ssh2_channel_msg(ssh, pktin);
if (!c) if (!c)
return; /* nonexistent channel */ return;
if (c->type != CHAN_SOCKDATA_DORMANT) if (c->type != CHAN_SOCKDATA_DORMANT)
return; /* dunno why they're failing this */ return; /* dunno why they're failing this */
@ -6564,30 +6580,18 @@ static void ssh2_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
static void ssh2_msg_channel_request(Ssh ssh, struct Packet *pktin) static void ssh2_msg_channel_request(Ssh ssh, struct Packet *pktin)
{ {
unsigned localid;
char *type; char *type;
int typelen, want_reply; int typelen, want_reply;
int reply = SSH2_MSG_CHANNEL_FAILURE; /* default */ int reply = SSH2_MSG_CHANNEL_FAILURE; /* default */
struct ssh_channel *c; struct ssh_channel *c;
struct Packet *pktout; struct Packet *pktout;
localid = ssh_pkt_getuint32(pktin); c = ssh2_channel_msg(ssh, pktin);
if (!c)
return;
ssh_pkt_getstring(pktin, &type, &typelen); ssh_pkt_getstring(pktin, &type, &typelen);
want_reply = ssh2_pkt_getbool(pktin); want_reply = ssh2_pkt_getbool(pktin);
/*
* First, check that the channel exists. Otherwise,
* we can instantly disconnect with a rude message.
*/
c = find234(ssh->channels, &localid, ssh_channelfind);
if (!c) {
char *buf = dupprintf("Received channel request for nonexistent"
" channel %d", localid);
ssh_disconnect(ssh, NULL, buf, SSH2_DISCONNECT_PROTOCOL_ERROR, FALSE);
sfree(buf);
return;
}
/* /*
* Having got the channel number, we now look at * Having got the channel number, we now look at
* the request type string to see if it's something * the request type string to see if it's something