mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-25 01:02:24 +00:00
Fix rekeying when using a certified host key.
In a rekey, we expect to see the same host key again, which we enforce by comparing its cache string, which we happened to have handy. But certified host keys don't have cache strings, so this no longer works reliably - the 'assert(s->keystr)' fails. (This is what I get for making a zillion short-lived test connections and not leaving any of them running for more than 2 minutes!) Instead, we now keep the official public blob of the host key from the first key exchange, and compare that to the public blob of the one in the rekey.
This commit is contained in:
parent
1dfa0f538b
commit
958304897d
@ -952,8 +952,8 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s, bool *aborted)
|
||||
* Save this host key, to check against the one presented in
|
||||
* subsequent rekeys.
|
||||
*/
|
||||
s->hostkey_str = s->keystr;
|
||||
s->keystr = NULL;
|
||||
strbuf_clear(s->hostkeyblob);
|
||||
ssh_key_public_blob(s->hkey, BinarySink_UPCAST(s->hostkeyblob));
|
||||
} else if (s->cross_certifying) {
|
||||
assert(s->hkey);
|
||||
assert(ssh_key_alg(s->hkey) == s->cross_certifying);
|
||||
@ -969,8 +969,8 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s, bool *aborted)
|
||||
* Don't forget to store the new key as the one we'll be
|
||||
* re-checking in future normal rekeys.
|
||||
*/
|
||||
s->hostkey_str = s->keystr;
|
||||
s->keystr = NULL;
|
||||
strbuf_clear(s->hostkeyblob);
|
||||
ssh_key_public_blob(s->hkey, BinarySink_UPCAST(s->hostkeyblob));
|
||||
} else {
|
||||
/*
|
||||
* In a rekey, we never present an interactive host key
|
||||
@ -978,8 +978,12 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s, bool *aborted)
|
||||
* enforce that the key we're seeing this time is identical to
|
||||
* the one we saw before.
|
||||
*/
|
||||
assert(s->keystr); /* filled in by prior key exchange */
|
||||
if (strcmp(s->hostkey_str, s->keystr)) {
|
||||
strbuf *thisblob = strbuf_new();
|
||||
ssh_key_public_blob(s->hkey, BinarySink_UPCAST(thisblob));
|
||||
bool match = ptrlen_eq_ptrlen(ptrlen_from_strbuf(thisblob),
|
||||
ptrlen_from_strbuf(s->hostkeyblob));
|
||||
strbuf_free(thisblob);
|
||||
if (!match) {
|
||||
#ifndef FUZZING
|
||||
ssh_sw_abort(s->ppl.ssh,
|
||||
"Host key was different in repeat key exchange");
|
||||
|
@ -212,7 +212,6 @@ static void ssh2_transport_free(PacketProtocolLayer *ppl)
|
||||
sfree(s->client_greeting);
|
||||
sfree(s->server_greeting);
|
||||
sfree(s->keystr);
|
||||
sfree(s->hostkey_str);
|
||||
strbuf_free(s->hostkeyblob);
|
||||
{
|
||||
host_ca *hca;
|
||||
|
@ -140,7 +140,6 @@ struct ssh2_transport_state {
|
||||
|
||||
const ssh_kex *kex_alg;
|
||||
const ssh_keyalg *hostkey_alg;
|
||||
char *hostkey_str; /* string representation, for easy checking in rekeys */
|
||||
unsigned char session_id[MAX_HASH_LEN];
|
||||
int session_id_len;
|
||||
int dh_min_size, dh_max_size;
|
||||
@ -188,7 +187,8 @@ struct ssh2_transport_state {
|
||||
int kex_init_value, kex_reply_value;
|
||||
transport_direction in, out, *cstrans, *sctrans;
|
||||
ptrlen hostkeydata, sigdata;
|
||||
strbuf *hostkeyblob;
|
||||
strbuf *hostkeyblob; /* used in server to construct host key to
|
||||
* send to client; in client to check in rekeys */
|
||||
char *keystr;
|
||||
ssh_key *hkey; /* actual host key */
|
||||
unsigned hkflags; /* signing flags, used in server */
|
||||
|
Loading…
Reference in New Issue
Block a user