mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
Merge SSH fixes from 'pre-0.79'.
This commit is contained in:
commit
356ccf489b
5
config.c
5
config.c
@ -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));
|
||||
|
@ -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
|
||||
|
1
putty.h
1
putty.h
@ -2002,6 +2002,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 \
|
||||
|
@ -759,6 +759,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));
|
||||
@ -1240,6 +1241,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
1
ssh.h
@ -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) };
|
||||
|
15
ssh/ssh.c
15
ssh/ssh.c
@ -474,7 +474,8 @@ void ssh_remote_error(Ssh *ssh, const char *fmt, ...)
|
||||
if (ssh->base_layer || !ssh->session_started) {
|
||||
GET_FORMATTED_MSG;
|
||||
|
||||
ssh_ppl_final_output(ssh->base_layer);
|
||||
if (ssh->base_layer)
|
||||
ssh_ppl_final_output(ssh->base_layer);
|
||||
|
||||
/* Error messages sent by the remote don't count as clean exits */
|
||||
ssh->exitcode = 128;
|
||||
@ -494,7 +495,8 @@ void ssh_remote_eof(Ssh *ssh, const char *fmt, ...)
|
||||
if (ssh->base_layer || !ssh->session_started) {
|
||||
GET_FORMATTED_MSG;
|
||||
|
||||
ssh_ppl_final_output(ssh->base_layer);
|
||||
if (ssh->base_layer)
|
||||
ssh_ppl_final_output(ssh->base_layer);
|
||||
|
||||
/* EOF from the remote, if we were expecting it, does count as
|
||||
* a clean exit */
|
||||
@ -519,7 +521,8 @@ void ssh_proto_error(Ssh *ssh, const char *fmt, ...)
|
||||
if (ssh->base_layer || !ssh->session_started) {
|
||||
GET_FORMATTED_MSG;
|
||||
|
||||
ssh_ppl_final_output(ssh->base_layer);
|
||||
if (ssh->base_layer)
|
||||
ssh_ppl_final_output(ssh->base_layer);
|
||||
|
||||
ssh->exitcode = 128;
|
||||
|
||||
@ -538,7 +541,8 @@ void ssh_sw_abort(Ssh *ssh, const char *fmt, ...)
|
||||
if (ssh->base_layer || !ssh->session_started) {
|
||||
GET_FORMATTED_MSG;
|
||||
|
||||
ssh_ppl_final_output(ssh->base_layer);
|
||||
if (ssh->base_layer)
|
||||
ssh_ppl_final_output(ssh->base_layer);
|
||||
|
||||
ssh->exitcode = 128;
|
||||
|
||||
@ -557,7 +561,8 @@ void ssh_user_close(Ssh *ssh, const char *fmt, ...)
|
||||
if (ssh->base_layer || !ssh->session_started) {
|
||||
GET_FORMATTED_MSG;
|
||||
|
||||
ssh_ppl_final_output(ssh->base_layer);
|
||||
if (ssh->base_layer)
|
||||
ssh_ppl_final_output(ssh->base_layer);
|
||||
|
||||
/* Closing the connection due to user action, even if the
|
||||
* action is the user aborting during authentication prompts,
|
||||
|
@ -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,
|
||||
@ -2377,7 +2379,28 @@ static void ssh2_userauth_add_alg_and_publickey(
|
||||
ppl_logevent("Sending public key with certificate from \"%s\"",
|
||||
filename_to_str(s->detached_cert_file));
|
||||
}
|
||||
put_stringz(pkt, ssh_keyalg_related_alg(certalg, pkalg)->ssh_id);
|
||||
{
|
||||
/* Strip off any existing certificate-nature from pkalg,
|
||||
* for the case where we're replacing a cert embedded in
|
||||
* the key with the detached one. The second argument of
|
||||
* ssh_keyalg_related_alg is expected to be one of the
|
||||
* 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);
|
||||
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;
|
||||
goto out;
|
||||
@ -2423,11 +2446,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.
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user