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:
parent
1243be890a
commit
33de96ffa9
@ -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;
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user