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

Work around key algorithm naming change in OpenSSH <= 7.7.

When you send a "publickey" USERAUTH_REQUEST containing a certified
RSA key, and you want to use a SHA-2 based RSA algorithm, modern
OpenSSH expects you to send the algorithm string as
rsa-sha2-NNN-cert-v01@openssh.com. But 7.7 and earlier didn't
recognise those names, and expected the algorithm string in the
userauth request packet to be ssh-rsa-cert-v01@... and would then
follow it with an rsa-sha2-NNN signature.

OpenSSH itself has a bug workaround for its own older versions. Follow
suit.
This commit is contained in:
Simon Tatham 2023-05-04 18:24:18 +01:00
parent cfe6fd95a7
commit d663356634
8 changed files with 82 additions and 2 deletions

View File

@ -3173,6 +3173,11 @@ void setup_config_box(struct controlbox *b, bool midsession,
s = ctrl_getset(b, "Connection/SSH/More bugs", "main",
"Detection of known bugs in SSH servers");
ctrl_droplist(s, "Rejects rsa-sha2-*-cert*@openssh.com in userauth",
'j', 20,
HELPCTX(ssh_bugs_rsa_sha2_cert_userauth),
sshbug_handler,
I(CONF_sshbug_rsa_sha2_cert_userauth));
ctrl_droplist(s, "Requires padding on SSH-2 RSA signatures", 'p', 20,
HELPCTX(ssh_bugs_rsapad2),
sshbug_handler, I(CONF_sshbug_rsapad2));

View File

@ -3664,6 +3664,23 @@ connection would deadlock. We don't know of any servers that do this,
but if there is one, then this flag will make PuTTY unable to speak to
them at all.
\S{config-ssh-bug-rsa-sha2-cert-userauth} \q{Rejects
\cw{rsa-sha2-*-cert*@openssh.com} in userauth}
If PuTTY is trying to do SSH-2 user authentication using an RSA key,
and the server is using one of the newer SHA-2 based versions of the
SSH RSA protocol, and the user's key is also a certificate, then
earlier versions of OpenSSH (up to 7.7) disagree with later versions
about the right key algorithm string to send in the
\cw{SSH2_MSG_USERAUTH_REQUEST} packet. Modern versions send a string
that indicates both the SHA-2 nature and the certificate nature of the
key, such as \cq{rsa-sha2-512-cert-v01@openssh.com}. Earlier versions
would reject that, and insist on seeing
\cq{ssh-rsa-cert-v01@openssh.com} followed by a SHA-2 based signature.
PuTTY should auto-detect the presence of this bug in earlier OpenSSH
and adjust to send the right string.
\S{config-ssh-bug-sig} \q{Requires padding on SSH-2 \i{RSA} \i{signatures}}
Versions below 3.3 of \i{OpenSSH} require SSH-2 RSA signatures to be

View File

@ -2025,6 +2025,7 @@ NORETURN void cleanup_exit(int);
X(INT, NONE, sshbug_chanreq) \
X(INT, NONE, sshbug_dropstart) \
X(INT, NONE, sshbug_filter_kexinit) \
X(INT, NONE, sshbug_rsa_sha2_cert_userauth) \
/* \
* ssh_simple means that we promise never to open any channel \
* other than the main one, which means it can safely use a very \

View File

@ -785,6 +785,7 @@ void save_open_settings(settings_w *sesskey, Conf *conf)
write_setting_i(sesskey, "BugOldGex2", 2-conf_get_int(conf, CONF_sshbug_oldgex2));
write_setting_i(sesskey, "BugWinadj", 2-conf_get_int(conf, CONF_sshbug_winadj));
write_setting_i(sesskey, "BugChanReq", 2-conf_get_int(conf, CONF_sshbug_chanreq));
write_setting_i(sesskey, "BugRSASHA2CertUserauth", 2-conf_get_int(conf, CONF_sshbug_rsa_sha2_cert_userauth));
write_setting_i(sesskey, "BugDropStart", 2-conf_get_int(conf, CONF_sshbug_dropstart));
write_setting_i(sesskey, "BugFilterKexinit", 2-conf_get_int(conf, CONF_sshbug_filter_kexinit));
write_setting_b(sesskey, "StampUtmp", conf_get_bool(conf, CONF_stamp_utmp));
@ -1266,6 +1267,7 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
i = gppi_raw(sesskey, "BugOldGex2", 0); conf_set_int(conf, CONF_sshbug_oldgex2, 2-i);
i = gppi_raw(sesskey, "BugWinadj", 0); conf_set_int(conf, CONF_sshbug_winadj, 2-i);
i = gppi_raw(sesskey, "BugChanReq", 0); conf_set_int(conf, CONF_sshbug_chanreq, 2-i);
i = gppi_raw(sesskey, "BugRSASHA2CertUserauth", 0); conf_set_int(conf, CONF_sshbug_rsa_sha2_cert_userauth, 2-i);
i = gppi_raw(sesskey, "BugDropStart", 1); conf_set_int(conf, CONF_sshbug_dropstart, 2-i);
i = gppi_raw(sesskey, "BugFilterKexinit", 1); conf_set_int(conf, CONF_sshbug_filter_kexinit, 2-i);
conf_set_bool(conf, CONF_ssh_simple, false);

1
ssh.h
View File

@ -1882,6 +1882,7 @@ void old_keyfile_warning(void);
X(BUG_SENDS_LATE_REQUEST_REPLY) \
X(BUG_SSH2_OLDGEX) \
X(BUG_REQUIRES_FILTERED_KEXINIT) \
X(BUG_RSA_SHA2_CERT_USERAUTH) \
/* end of list */
#define TMP_DECLARE_LOG2_ENUM(thing) log2_##thing,
enum { SSH_IMPL_BUG_LIST(TMP_DECLARE_LOG2_ENUM) };

View File

@ -135,6 +135,8 @@ static void ssh2_userauth_ki_write_responses(
static void ssh2_userauth_final_output(PacketProtocolLayer *ppl);
static void ssh2_userauth_print_banner(struct ssh2_userauth_state *s);
static ptrlen workaround_rsa_sha2_cert_userauth(
struct ssh2_userauth_state *s, ptrlen id);
static const PacketProtocolLayerVtable ssh2_userauth_vtable = {
.free = ssh2_userauth_free,
@ -2381,9 +2383,19 @@ static void ssh2_userauth_add_alg_and_publickey(
* bare key algorithms, or nothing useful will happen. */
const ssh_keyalg *pkalg_base =
pkalg->base_alg ? pkalg->base_alg : pkalg;
/* Construct an algorithm string that includes both the
* signature subtype (e.g. rsa-sha2-512) and the
* certificate-ness. Exception: in earlier versions of
* OpenSSH we don't want to do that, and must send just
* ssh-rsa-cert-... even when we're delivering a non-SHA-1
* signature. */
const ssh_keyalg *output_alg =
ssh_keyalg_related_alg(certalg, pkalg_base);
put_stringz(pkt, output_alg->ssh_id);
ptrlen output_id = ptrlen_from_asciz(output_alg->ssh_id);
output_id = workaround_rsa_sha2_cert_userauth(s, output_id);
put_stringpl(pkt, output_id);
}
put_stringpl(pkt, ptrlen_from_strbuf(s->detached_cert_blob));
done = true;
@ -2430,11 +2442,30 @@ static void ssh2_userauth_add_alg_and_publickey(
return;
}
/* In all other cases, just put in what we were given. */
/* In all other cases, basically just put in what we were given -
* except for the same bug workaround as above. */
alg = workaround_rsa_sha2_cert_userauth(s, alg);
put_stringpl(pkt, alg);
put_stringpl(pkt, pkblob);
}
static ptrlen workaround_rsa_sha2_cert_userauth(
struct ssh2_userauth_state *s, ptrlen id)
{
if (!(s->ppl.remote_bugs & BUG_RSA_SHA2_CERT_USERAUTH))
return id;
/*
* No need to try to do this in a general way based on the
* relations between ssh_keyalgs; we know there are a limited
* number of affected versions of OpenSSH, so this doesn't have to
* be futureproof against later additions to the family.
*/
if (ptrlen_eq_string(id, "rsa-sha2-256-cert-v01@openssh.com") ||
ptrlen_eq_string(id, "rsa-sha2-512-cert-v01@openssh.com"))
return PTRLEN_LITERAL("ssh-rsa-cert-v01@openssh.com");
return id;
}
/*
* Helper function to add an SSH-2 signature blob to a packet. Expects
* to be shown the public key blob as well as the signature blob.

View File

@ -612,6 +612,28 @@ static void ssh_detect_bugs(struct ssh_verstring_state *s)
bpp_logevent("We believe remote version requires us to "
"filter our KEXINIT");
}
if (conf_get_int(s->conf, CONF_sshbug_rsa_sha2_cert_userauth) == FORCE_ON ||
(conf_get_int(s->conf, CONF_sshbug_rsa_sha2_cert_userauth) == AUTO &&
(wc_match("OpenSSH_7.[2-7]*", imp)))) {
/*
* These versions have the bug in which using RSA/SHA-2
* authentication with a certified key requires the key
* algorithm to be sent as ssh-rsa-cert-... instead of
* rsa-sha2-NNN-cert-...
*
* OpenSSH 7.8 wants rsa-sha2-NNN-cert-...:
* https://github.com/openssh/openssh-portable/commit/4ba0d54794814ec0de1ec87987d0c3b89379b436
* (also labelled "OpenBSD-Commit-ID:
* c6e9f6d45eed8962ad502d315d7eaef32c419dde")
*
* OpenSSH 7.2 was the first release supporting RSA/SHA-2
* at all, so this bug is irrelevant to anything before that.
*/
s->remote_bugs |= BUG_RSA_SHA2_CERT_USERAUTH;
bpp_logevent("We believe remote version has SSH-2 "
"RSA/SHA-2/certificate userauth bug");
}
}
const char *ssh_verstring_get_remote(BinaryPacketProtocol *bpp)

View File

@ -167,6 +167,7 @@ typedef const char *HelpCtx;
#define WINHELP_CTX_ssh_bugs_pksessid2 "config-ssh-bug-pksessid2"
#define WINHELP_CTX_ssh_bugs_rekey2 "config-ssh-bug-rekey"
#define WINHELP_CTX_ssh_bugs_maxpkt2 "config-ssh-bug-maxpkt2"
#define WINHELP_CTX_ssh_bugs_rsa_sha2_cert_userauth "config-ssh-bug-rsa-sha2-cert-userauth"
#define WINHELP_CTX_ssh_bugs_winadj "config-ssh-bug-winadj"
#define WINHELP_CTX_ssh_bugs_chanreq "config-ssh-bug-chanreq"
#define WINHELP_CTX_ssh_bugs_oldgex2 "config-ssh-bug-oldgex2"