mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
Log the server's diagnostics if main channel open fails.
This has been a FIXME in the code for ages, because back when the main channel was always a pty session or a program run in a pipe, there weren't that many circumstances in which the actual CHANNEL_OPEN could return failure, so it never seemed like a priority to get round to pulling the error information out of the CHANNEL_OPEN_FAILURE response message and including it in PuTTY or Plink's local error message. However, 'plink -nc' is the real reason why this is actually important; if you tell the SSH server to make a direct-tcpip network connection as its main channel, then that can fail for all the usual network-unreliability reasons, and you actually do want to know which (did you misspell the hostname, or is the target server refusing connections, or has network connectivity failed?). This actually bit me today when I had such a network failure, and had to debug it by pulling that information manually out of a packet log. Time to eliminate that FIXME. So I've pulled the error-extracting code out of the previous handler for OPEN_FAILURE on non-main channels into a separate function, and arranged to call that function if the main channel open fails too. In the process I've made a couple of minor tweaks, e.g. if the server sends back a reason code we haven't heard of, we say _what_ that reason code was, and also we at least make a token effort to spot if we see a packet other than OPEN_{CONFIRMATION,FAILURE} reaching the main loop in response to the main channel-open.
This commit is contained in:
parent
f31a72ba09
commit
a9e1053c8a
61
ssh.c
61
ssh.c
@ -8496,18 +8496,37 @@ static void ssh2_msg_channel_open_confirmation(Ssh ssh, struct Packet *pktin)
|
||||
ssh_channel_try_eof(c); /* in case we had a pending EOF */
|
||||
}
|
||||
|
||||
static void ssh2_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
|
||||
static char *ssh2_channel_open_failure_error_text(struct Packet *pktin)
|
||||
{
|
||||
static const char *const reasons[] = {
|
||||
"<unknown reason code>",
|
||||
"Administratively prohibited",
|
||||
"Connect failed",
|
||||
"Unknown channel type",
|
||||
"Resource shortage",
|
||||
NULL,
|
||||
"Administratively prohibited",
|
||||
"Connect failed",
|
||||
"Unknown channel type",
|
||||
"Resource shortage",
|
||||
};
|
||||
unsigned reason_code;
|
||||
const char *reason_code_string;
|
||||
char reason_code_buf[256];
|
||||
char *reason_string;
|
||||
int reason_length;
|
||||
|
||||
reason_code = ssh_pkt_getuint32(pktin);
|
||||
if (reason_code < lenof(reasons) && reasons[reason_code]) {
|
||||
reason_code_string = reasons[reason_code];
|
||||
} else {
|
||||
reason_code_string = reason_code_buf;
|
||||
sprintf(reason_code_buf, "unknown reason code %#x", reason_code);
|
||||
}
|
||||
|
||||
ssh_pkt_getstring(pktin, &reason_string, &reason_length);
|
||||
|
||||
return dupprintf("%s [%.*s]", reason_code_string,
|
||||
reason_length, NULLTOEMPTY(reason_string));
|
||||
}
|
||||
|
||||
static void ssh2_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
|
||||
{
|
||||
struct ssh_channel *c;
|
||||
|
||||
c = ssh_channel_msg(ssh, pktin);
|
||||
@ -8516,14 +8535,9 @@ static void ssh2_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
|
||||
assert(c->halfopen); /* ssh_channel_msg will have enforced this */
|
||||
|
||||
if (c->type == CHAN_SOCKDATA) {
|
||||
reason_code = ssh_pkt_getuint32(pktin);
|
||||
if (reason_code >= lenof(reasons))
|
||||
reason_code = 0; /* ensure reasons[reason_code] in range */
|
||||
ssh_pkt_getstring(pktin, &reason_string, &reason_length);
|
||||
logeventf(ssh, "Forwarded connection refused by server: %s [%.*s]",
|
||||
reasons[reason_code], reason_length,
|
||||
NULLTOEMPTY(reason_string));
|
||||
|
||||
char *errtext = ssh2_channel_open_failure_error_text(pktin);
|
||||
logeventf(ssh, "Forwarded connection refused by server: %s", errtext);
|
||||
sfree(errtext);
|
||||
pfd_close(c->u.pfd.pf);
|
||||
} else if (c->type == CHAN_ZOMBIE) {
|
||||
/*
|
||||
@ -10727,15 +10741,24 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
|
||||
ssh->ncmode = FALSE;
|
||||
}
|
||||
crWaitUntilV(pktin);
|
||||
if (pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) {
|
||||
bombout(("Server refused to open channel"));
|
||||
if (pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION &&
|
||||
pktin->type != SSH2_MSG_CHANNEL_OPEN_FAILURE) {
|
||||
bombout(("Server sent strange packet %d in response to main "
|
||||
"channel open request", pktin->type));
|
||||
crStopV;
|
||||
/* FIXME: error data comes back in FAILURE packet */
|
||||
}
|
||||
}
|
||||
if (ssh_pkt_getuint32(pktin) != ssh->mainchan->localid) {
|
||||
bombout(("Server's channel confirmation cited wrong channel"));
|
||||
bombout(("Server's response to main channel open cited wrong"
|
||||
" channel number"));
|
||||
crStopV;
|
||||
}
|
||||
if (pktin->type == SSH2_MSG_CHANNEL_OPEN_FAILURE) {
|
||||
char *errtext = ssh2_channel_open_failure_error_text(pktin);
|
||||
bombout(("Server refused to open main channel: %s", errtext));
|
||||
sfree(errtext);
|
||||
crStopV;
|
||||
}
|
||||
|
||||
ssh->mainchan->remoteid = ssh_pkt_getuint32(pktin);
|
||||
ssh->mainchan->halfopen = FALSE;
|
||||
ssh->mainchan->type = CHAN_MAINSESSION;
|
||||
|
Loading…
Reference in New Issue
Block a user