mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +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++) {
|
for (uint32_t i = 0; i < nexts && !get_err(pktin); i++) {
|
||||||
ptrlen extname = get_string(pktin);
|
ptrlen extname = get_string(pktin);
|
||||||
ptrlen extvalue = 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);
|
pq_pop(ppl->in_pq);
|
||||||
break;
|
break;
|
||||||
|
@ -77,6 +77,8 @@ struct ssh2_userauth_state {
|
|||||||
size_t agent_keys_len;
|
size_t agent_keys_len;
|
||||||
agent_key *agent_keys;
|
agent_key *agent_keys;
|
||||||
size_t agent_key_index, agent_key_limit;
|
size_t agent_key_index, agent_key_limit;
|
||||||
|
ptrlen agent_keyalg;
|
||||||
|
unsigned signflags;
|
||||||
int len;
|
int len;
|
||||||
PktOut *pktout;
|
PktOut *pktout;
|
||||||
bool want_user_input;
|
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.
|
* 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;
|
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");
|
put_stringz(s->pktout, "publickey");
|
||||||
/* method */
|
/* method */
|
||||||
put_bool(s->pktout, false); /* no signature included */
|
put_bool(s->pktout, false); /* no signature included */
|
||||||
put_stringpl(s->pktout,
|
put_stringpl(s->pktout, s->agent_keyalg);
|
||||||
s->agent_keys[s->agent_key_index].algorithm);
|
|
||||||
put_stringpl(s->pktout, ptrlen_from_strbuf(
|
put_stringpl(s->pktout, ptrlen_from_strbuf(
|
||||||
s->agent_keys[s->agent_key_index].blob));
|
s->agent_keys[s->agent_key_index].blob));
|
||||||
pq_push(s->ppl.out_pq, s->pktout);
|
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");
|
put_stringz(s->pktout, "publickey");
|
||||||
/* method */
|
/* method */
|
||||||
put_bool(s->pktout, true); /* signature included */
|
put_bool(s->pktout, true); /* signature included */
|
||||||
put_stringpl(s->pktout,
|
put_stringpl(s->pktout, s->agent_keyalg);
|
||||||
s->agent_keys[s->agent_key_index].algorithm);
|
|
||||||
put_stringpl(s->pktout, ptrlen_from_strbuf(
|
put_stringpl(s->pktout, ptrlen_from_strbuf(
|
||||||
s->agent_keys[s->agent_key_index].blob));
|
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,
|
put_data(sigdata, s->pktout->data + 5,
|
||||||
s->pktout->length - 5);
|
s->pktout->length - 5);
|
||||||
put_stringsb(agentreq, sigdata);
|
put_stringsb(agentreq, sigdata);
|
||||||
/* And finally the (zero) flags word. */
|
/* And finally the flags word. */
|
||||||
put_uint32(agentreq, 0);
|
put_uint32(agentreq, s->signflags);
|
||||||
ssh2_userauth_agent_query(s, agentreq);
|
ssh2_userauth_agent_query(s, agentreq);
|
||||||
strbuf_free(agentreq);
|
strbuf_free(agentreq);
|
||||||
crWaitUntilV(!s->auth_agent_query);
|
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.
|
* Try the public key supplied in the configuration.
|
||||||
*
|
*
|
||||||
* First, offer the public blob to see if the server is
|
* First, try to upgrade its algorithm.
|
||||||
* willing to accept it.
|
*/
|
||||||
|
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->pktout = ssh_bpp_new_pktout(
|
||||||
s->ppl.bpp, SSH2_MSG_USERAUTH_REQUEST);
|
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, s->successor_layer->vt->name);
|
||||||
put_stringz(s->pktout, "publickey"); /* method */
|
put_stringz(s->pktout, "publickey"); /* method */
|
||||||
put_bool(s->pktout, true); /* signature follows */
|
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();
|
pkblob = strbuf_new();
|
||||||
ssh_key_public_blob(key->key, BinarySink_UPCAST(pkblob));
|
ssh_key_public_blob(key->key, BinarySink_UPCAST(pkblob));
|
||||||
put_string(s->pktout, pkblob->s, pkblob->len);
|
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,
|
put_data(sigdata, s->pktout->data + 5,
|
||||||
s->pktout->length - 5);
|
s->pktout->length - 5);
|
||||||
sigblob = strbuf_new();
|
sigblob = strbuf_new();
|
||||||
ssh_key_sign(key->key, ptrlen_from_strbuf(sigdata), 0,
|
ssh_key_sign(key->key, ptrlen_from_strbuf(sigdata),
|
||||||
BinarySink_UPCAST(sigblob));
|
s->signflags, BinarySink_UPCAST(sigblob));
|
||||||
strbuf_free(sigdata);
|
strbuf_free(sigdata);
|
||||||
ssh2_userauth_add_sigblob(
|
ssh2_userauth_add_sigblob(
|
||||||
s, s->pktout, ptrlen_from_strbuf(pkblob),
|
s, s->pktout, ptrlen_from_strbuf(pkblob),
|
||||||
|
Loading…
Reference in New Issue
Block a user