mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-25 01:02:24 +00:00
Remove fatal-error reporting from scan_kexinits.
This will allow it to be called in a second circumstance where we're trying to find out whether something _would_ have worked, so that we never want to terminate the connection.
This commit is contained in:
parent
0b00e4ce26
commit
fdc891d170
@ -1005,13 +1005,27 @@ static bool kexinit_keyword_found(ptrlen list, ptrlen keyword)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ssh2_scan_kexinits(
|
typedef struct ScanKexinitsResult {
|
||||||
|
bool success;
|
||||||
|
|
||||||
|
/* only if success is false */
|
||||||
|
enum {
|
||||||
|
SKR_INCOMPLETE,
|
||||||
|
SKR_UNKNOWN_ID,
|
||||||
|
SKR_NO_AGREEMENT,
|
||||||
|
} error;
|
||||||
|
|
||||||
|
const char *kind; /* what kind of thing did we fail to sort out? */
|
||||||
|
ptrlen desc; /* and what was it? or what was the available list? */
|
||||||
|
} ScanKexinitsResult;
|
||||||
|
|
||||||
|
static ScanKexinitsResult ssh2_scan_kexinits(
|
||||||
ptrlen client_kexinit, ptrlen server_kexinit, bool we_are_server,
|
ptrlen client_kexinit, ptrlen server_kexinit, bool we_are_server,
|
||||||
struct kexinit_algorithm_list kexlists[NKEXLIST],
|
struct kexinit_algorithm_list kexlists[NKEXLIST],
|
||||||
const ssh_kex **kex_alg, const ssh_keyalg **hostkey_alg,
|
const ssh_kex **kex_alg, const ssh_keyalg **hostkey_alg,
|
||||||
transport_direction *cs, transport_direction *sc,
|
transport_direction *cs, transport_direction *sc,
|
||||||
bool *warn_kex, bool *warn_hk, bool *warn_cscipher, bool *warn_sccipher,
|
bool *warn_kex, bool *warn_hk, bool *warn_cscipher, bool *warn_sccipher,
|
||||||
Ssh *ssh, bool *ignore_guess_cs_packet, bool *ignore_guess_sc_packet,
|
bool *ignore_guess_cs_packet, bool *ignore_guess_sc_packet,
|
||||||
struct server_hostkeys *server_hostkeys, unsigned *hkflags,
|
struct server_hostkeys *server_hostkeys, unsigned *hkflags,
|
||||||
bool *can_send_ext_info, bool first_time, bool *strict_kex)
|
bool *can_send_ext_info, bool first_time, bool *strict_kex)
|
||||||
{
|
{
|
||||||
@ -1040,11 +1054,10 @@ static bool ssh2_scan_kexinits(
|
|||||||
clists[i] = get_string(client);
|
clists[i] = get_string(client);
|
||||||
slists[i] = get_string(server);
|
slists[i] = get_string(server);
|
||||||
if (get_err(client) || get_err(server)) {
|
if (get_err(client) || get_err(server)) {
|
||||||
/* Report a better error than the spurious "Couldn't
|
ScanKexinitsResult skr = {
|
||||||
* agree" that we'd generate if we pressed on regardless
|
.success = false, .error = SKR_INCOMPLETE,
|
||||||
* and treated the empty get_string() result as genuine */
|
};
|
||||||
ssh_proto_error(ssh, "KEXINIT packet was incomplete");
|
return skr;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (cfirst = true, clist = clists[i];
|
for (cfirst = true, clist = clists[i];
|
||||||
@ -1092,10 +1105,11 @@ static bool ssh2_scan_kexinits(
|
|||||||
* produce a reasonably useful message instead of an
|
* produce a reasonably useful message instead of an
|
||||||
* assertion failure.
|
* assertion failure.
|
||||||
*/
|
*/
|
||||||
ssh_sw_abort(ssh, "Selected %s \"%.*s\" does not correspond to "
|
ScanKexinitsResult skr = {
|
||||||
"any supported algorithm",
|
.success = false, .error = SKR_UNKNOWN_ID,
|
||||||
kexlist_descr[i], PTRLEN_PRINTF(found));
|
.kind = kexlist_descr[i], .desc = found,
|
||||||
return false;
|
};
|
||||||
|
return skr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1150,9 +1164,11 @@ static bool ssh2_scan_kexinits(
|
|||||||
/*
|
/*
|
||||||
* Otherwise, any match failure _is_ a fatal error.
|
* Otherwise, any match failure _is_ a fatal error.
|
||||||
*/
|
*/
|
||||||
ssh_sw_abort(ssh, "Couldn't agree a %s (available: %.*s)",
|
ScanKexinitsResult skr = {
|
||||||
kexlist_descr[i], PTRLEN_PRINTF(slists[i]));
|
.success = false, .error = SKR_UNKNOWN_ID,
|
||||||
return false;
|
.kind = kexlist_descr[i], .desc = slists[i],
|
||||||
|
};
|
||||||
|
return skr;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (i) {
|
switch (i) {
|
||||||
@ -1248,7 +1264,33 @@ static bool ssh2_scan_kexinits(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
ScanKexinitsResult skr = { .success = true };
|
||||||
|
return skr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ssh2_report_scan_kexinits_error(Ssh *ssh, ScanKexinitsResult skr)
|
||||||
|
{
|
||||||
|
assert(!skr.success);
|
||||||
|
|
||||||
|
switch (skr.error) {
|
||||||
|
case SKR_INCOMPLETE:
|
||||||
|
/* Report a better error than the spurious "Couldn't
|
||||||
|
* agree" that we'd generate if we pressed on regardless
|
||||||
|
* and treated the empty get_string() result as genuine */
|
||||||
|
ssh_proto_error(ssh, "KEXINIT packet was incomplete");
|
||||||
|
break;
|
||||||
|
case SKR_UNKNOWN_ID:
|
||||||
|
ssh_sw_abort(ssh, "Selected %s \"%.*s\" does not correspond to "
|
||||||
|
"any supported algorithm",
|
||||||
|
skr.kind, PTRLEN_PRINTF(skr.desc));
|
||||||
|
break;
|
||||||
|
case SKR_NO_AGREEMENT:
|
||||||
|
ssh_sw_abort(ssh, "Couldn't agree a %s (available: %.*s)",
|
||||||
|
skr.kind, PTRLEN_PRINTF(skr.desc));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unreachable("bad ScanKexinitsResult");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool delay_outgoing_kexinit(struct ssh2_transport_state *s)
|
static inline bool delay_outgoing_kexinit(struct ssh2_transport_state *s)
|
||||||
@ -1529,16 +1571,19 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
|
|||||||
{
|
{
|
||||||
struct server_hostkeys hks = { NULL, 0, 0 };
|
struct server_hostkeys hks = { NULL, 0, 0 };
|
||||||
|
|
||||||
if (!ssh2_scan_kexinits(
|
ScanKexinitsResult skr = ssh2_scan_kexinits(
|
||||||
ptrlen_from_strbuf(s->client_kexinit),
|
ptrlen_from_strbuf(s->client_kexinit),
|
||||||
ptrlen_from_strbuf(s->server_kexinit), s->ssc != NULL,
|
ptrlen_from_strbuf(s->server_kexinit), s->ssc != NULL,
|
||||||
s->kexlists, &s->kex_alg, &s->hostkey_alg, s->cstrans,
|
s->kexlists, &s->kex_alg, &s->hostkey_alg, s->cstrans,
|
||||||
s->sctrans, &s->warn_kex, &s->warn_hk, &s->warn_cscipher,
|
s->sctrans, &s->warn_kex, &s->warn_hk, &s->warn_cscipher,
|
||||||
&s->warn_sccipher, s->ppl.ssh, NULL, &s->ignorepkt, &hks,
|
&s->warn_sccipher, NULL, &s->ignorepkt, &hks,
|
||||||
&s->hkflags, &s->can_send_ext_info, !s->got_session_id,
|
&s->hkflags, &s->can_send_ext_info, !s->got_session_id,
|
||||||
&s->strict_kex)) {
|
&s->strict_kex);
|
||||||
|
|
||||||
|
if (!skr.success) {
|
||||||
sfree(hks.indices);
|
sfree(hks.indices);
|
||||||
return; /* false means a fatal error function was called */
|
ssh2_report_scan_kexinits_error(s->ppl.ssh, skr);
|
||||||
|
return; /* we just called a fatal error function */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user