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

Support sending RFC 8332 rsa-sha2-* userauth keys.

We parse enough of EXT_INFO to spot when the server advertises support
for them, and if it does, we upgrade the key algorithm name from
"ssh-rsa" to one of the other two, and set appropriate signing flags.

This doesn't actually end up using the ssh_rsa_sha256 / ssh_rsa_sha512
vtables I set up two commits ago, because it's easier to just vary the
flags word we pass to ssh_key_sign.

The upgrade is done by ad-hoc special-case code in ssh2userauth.c. I
could have done it by introducing a new ssh_keyalg vtable method for
'please upgrade to your favourite version of yourself according to
some set of flags from the BPP', but it just didn't seem like a good
idea at this stage, because it presupposes that quirks in the
algorithm selection are going to follow a consistent pattern, and I
think it's much more likely that the next weird thing in this area
will be something totally different. So I've left it as a localised
bodge for now, and we can always refactor it into something nicer once
we have more information and know what the nicer thing _is_.
This commit is contained in:
Simon Tatham 2020-11-21 14:44:46 +00:00
parent 1243be890a
commit 33de96ffa9
2 changed files with 67 additions and 11 deletions

View File

@ -404,6 +404,33 @@ bool ssh2_common_filter_queue(PacketProtocolLayer *ppl)
for (uint32_t i = 0; i < nexts && !get_err(pktin); i++) {
ptrlen extname = get_string(pktin);
ptrlen extvalue = get_string(pktin);
if (ptrlen_eq_string(extname, "server-sig-algs")) {
/*
* Server has sent a list of signature algorithms
* it will potentially accept for user
* authentication keys. Check in particular
* whether the RFC 8332 improved versions of
* ssh-rsa are in the list, and set flags in the
* BPP if so.
*
* TODO: another thing we _could_ do here is to
* record a full list of the algorithm identifiers
* we've seen, whether we understand them
* ourselves or not. Then we could use that as a
* pre-filter during userauth, to skip keys in the
* SSH agent if we already know the server can't
* possibly accept them. (Even if the key
* algorithm is one that the agent and the server
* both understand but we do not.)
*/
ptrlen algname;
while (get_commasep_word(&extvalue, &algname)) {
if (ptrlen_eq_string(algname, "rsa-sha2-256"))
ppl->bpp->ext_info_rsa_sha256_ok = true;
if (ptrlen_eq_string(algname, "rsa-sha2-512"))
ppl->bpp->ext_info_rsa_sha512_ok = true;
}
}
}
pq_pop(ppl->in_pq);
break;

View File

@ -77,6 +77,8 @@ struct ssh2_userauth_state {
size_t agent_keys_len;
agent_key *agent_keys;
size_t agent_key_index, agent_key_limit;
ptrlen agent_keyalg;
unsigned signflags;
int len;
PktOut *pktout;
bool want_user_input;
@ -719,6 +721,19 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
/*
* Attempt public-key authentication using a key from Pageant.
*/
s->agent_keyalg = s->agent_keys[s->agent_key_index].algorithm;
s->signflags = 0;
if (ptrlen_eq_string(s->agent_keyalg, "ssh-rsa")) {
/* Try to upgrade ssh-rsa to one of the rsa-sha2-* family,
* if the server has announced support for them. */
if (s->ppl.bpp->ext_info_rsa_sha512_ok) {
s->agent_keyalg = PTRLEN_LITERAL("rsa-sha2-512");
s->signflags = SSH_AGENT_RSA_SHA2_512;
} else if (s->ppl.bpp->ext_info_rsa_sha256_ok) {
s->agent_keyalg = PTRLEN_LITERAL("rsa-sha2-256");
s->signflags = SSH_AGENT_RSA_SHA2_256;
}
}
s->ppl.bpp->pls->actx = SSH2_PKTCTX_PUBLICKEY;
@ -732,8 +747,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
put_stringz(s->pktout, "publickey");
/* method */
put_bool(s->pktout, false); /* no signature included */
put_stringpl(s->pktout,
s->agent_keys[s->agent_key_index].algorithm);
put_stringpl(s->pktout, s->agent_keyalg);
put_stringpl(s->pktout, ptrlen_from_strbuf(
s->agent_keys[s->agent_key_index].blob));
pq_push(s->ppl.out_pq, s->pktout);
@ -767,8 +781,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
put_stringz(s->pktout, "publickey");
/* method */
put_bool(s->pktout, true); /* signature included */
put_stringpl(s->pktout,
s->agent_keys[s->agent_key_index].algorithm);
put_stringpl(s->pktout, s->agent_keyalg);
put_stringpl(s->pktout, ptrlen_from_strbuf(
s->agent_keys[s->agent_key_index].blob));
@ -783,8 +796,8 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
put_data(sigdata, s->pktout->data + 5,
s->pktout->length - 5);
put_stringsb(agentreq, sigdata);
/* And finally the (zero) flags word. */
put_uint32(agentreq, 0);
/* And finally the flags word. */
put_uint32(agentreq, s->signflags);
ssh2_userauth_agent_query(s, agentreq);
strbuf_free(agentreq);
crWaitUntilV(!s->auth_agent_query);
@ -839,8 +852,24 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
/*
* Try the public key supplied in the configuration.
*
* First, offer the public blob to see if the server is
* willing to accept it.
* First, try to upgrade its algorithm.
*/
if (!strcmp(s->publickey_algorithm, "ssh-rsa")) {
/* Try to upgrade ssh-rsa to one of the rsa-sha2-* family,
* if the server has announced support for them. */
if (s->ppl.bpp->ext_info_rsa_sha512_ok) {
sfree(s->publickey_algorithm);
s->publickey_algorithm = dupstr("rsa-sha2-512");
s->signflags = SSH_AGENT_RSA_SHA2_512;
} else if (s->ppl.bpp->ext_info_rsa_sha256_ok) {
s->publickey_algorithm = dupstr("rsa-sha2-256");
s->signflags = SSH_AGENT_RSA_SHA2_256;
}
}
/*
* Offer the public blob to see if the server is willing to
* accept it.
*/
s->pktout = ssh_bpp_new_pktout(
s->ppl.bpp, SSH2_MSG_USERAUTH_REQUEST);
@ -975,7 +1004,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
put_stringz(s->pktout, s->successor_layer->vt->name);
put_stringz(s->pktout, "publickey"); /* method */
put_bool(s->pktout, true); /* signature follows */
put_stringz(s->pktout, ssh_key_ssh_id(key->key));
put_stringz(s->pktout, s->publickey_algorithm);
pkblob = strbuf_new();
ssh_key_public_blob(key->key, BinarySink_UPCAST(pkblob));
put_string(s->pktout, pkblob->s, pkblob->len);
@ -993,8 +1022,8 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
put_data(sigdata, s->pktout->data + 5,
s->pktout->length - 5);
sigblob = strbuf_new();
ssh_key_sign(key->key, ptrlen_from_strbuf(sigdata), 0,
BinarySink_UPCAST(sigblob));
ssh_key_sign(key->key, ptrlen_from_strbuf(sigdata),
s->signflags, BinarySink_UPCAST(sigblob));
strbuf_free(sigdata);
ssh2_userauth_add_sigblob(
s, s->pktout, ptrlen_from_strbuf(pkblob),