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

Support RFC 4419.

PuTTY now uses the updated version of Diffie-Hellman group exchange,
except for a few old OpenSSH versions which Darren Tucker reports only
support the old version.

FIXME: this needs further work because the Bugs config panel has now
overflowed.

(cherry picked from commit 62a1bce7cb)
This commit is contained in:
Simon Tatham 2015-04-25 10:46:53 +01:00
parent 5ac299449e
commit 318076a183
7 changed files with 59 additions and 3 deletions

View File

@ -2603,6 +2603,9 @@ void setup_config_box(struct controlbox *b, int midsession,
ctrl_droplist(s, "Ignores SSH-2 maximum packet size", 'x', 20,
HELPCTX(ssh_bugs_maxpkt2),
sshbug_handler, I(CONF_sshbug_maxpkt2));
ctrl_droplist(s, "Only supports pre-RFC4419 SSH-2 DH GEX", 'd', 20,
HELPCTX(ssh_bugs_oldgex2),
sshbug_handler, I(CONF_sshbug_oldgex2));
ctrl_droplist(s, "Replies to requests on closed channels", 'q', 20,
HELPCTX(ssh_bugs_chanreq),
sshbug_handler, I(CONF_sshbug_chanreq));

View File

@ -3386,6 +3386,23 @@ reply to a request after it thinks the channel has entirely closed,
and terminate with an error along the lines of \q{Received
\cw{SSH2_MSG_CHANNEL_FAILURE} for nonexistent channel 256}.
\S{config-ssh-bug-oldgex2} \q{Only supports pre-RFC4419 SSH-2 DH GEX}
\cfg{winhelp-topic}{ssh.bugs.oldgex2}
The SSH key exchange method that uses Diffie-Hellman group exchange
was redesigned after its original release, to use a slightly more
sophisticated setup message. Almost all SSH implementations switched
over to the new version. (PuTTY was one of the last.) A few old
servers still only support the old one.
If this bug is detected, and the client and server negotiate
Diffie-Hellman group exchange, then PuTTY will send the old message
now known as \cw{SSH2_MSG_KEX_DH_GEX_REQUEST_OLD} in place of the new
\cw{SSH2_MSG_KEX_DH_GEX_REQUEST}.
This is an SSH-2-specific bug.
\H{config-serial} The Serial panel
The \i{Serial} panel allows you to configure options that only apply

View File

@ -837,6 +837,7 @@ void cleanup_exit(int);
X(INT, NONE, sshbug_rekey2) \
X(INT, NONE, sshbug_maxpkt2) \
X(INT, NONE, sshbug_ignore2) \
X(INT, NONE, sshbug_oldgex2) \
X(INT, NONE, sshbug_winadj) \
X(INT, NONE, sshbug_chanreq) \
/* \

View File

@ -630,6 +630,7 @@ void save_open_settings(void *sesskey, Conf *conf)
write_setting_i(sesskey, "BugPKSessID2", 2-conf_get_int(conf, CONF_sshbug_pksessid2));
write_setting_i(sesskey, "BugRekey2", 2-conf_get_int(conf, CONF_sshbug_rekey2));
write_setting_i(sesskey, "BugMaxPkt2", 2-conf_get_int(conf, CONF_sshbug_maxpkt2));
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, "StampUtmp", conf_get_int(conf, CONF_stamp_utmp));
@ -977,6 +978,7 @@ void load_open_settings(void *sesskey, Conf *conf)
i = gppi_raw(sesskey, "BugPKSessID2", 0); conf_set_int(conf, CONF_sshbug_pksessid2, 2-i);
i = gppi_raw(sesskey, "BugRekey2", 0); conf_set_int(conf, CONF_sshbug_rekey2, 2-i);
i = gppi_raw(sesskey, "BugMaxPkt2", 0); conf_set_int(conf, CONF_sshbug_maxpkt2, 2-i);
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);
conf_set_int(conf, CONF_ssh_simple, FALSE);

35
ssh.c
View File

@ -76,6 +76,10 @@ static const char *const ssh2_disconnect_reasons[] = {
#define BUG_CHOKES_ON_SSH2_IGNORE 512
#define BUG_CHOKES_ON_WINADJ 1024
#define BUG_SENDS_LATE_REQUEST_REPLY 2048
#define BUG_SSH2_OLDGEX 4096
#define DH_MIN_SIZE 1024
#define DH_MAX_SIZE 8192
/*
* Codes for terminal modes.
@ -247,6 +251,7 @@ static char *ssh2_pkt_type(Pkt_KCtx pkt_kctx, Pkt_ACtx pkt_actx, int type)
translate(SSH2_MSG_NEWKEYS);
translatek(SSH2_MSG_KEXDH_INIT, SSH2_PKTCTX_DHGROUP);
translatek(SSH2_MSG_KEXDH_REPLY, SSH2_PKTCTX_DHGROUP);
translatek(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD, SSH2_PKTCTX_DHGEX);
translatek(SSH2_MSG_KEX_DH_GEX_REQUEST, SSH2_PKTCTX_DHGEX);
translatek(SSH2_MSG_KEX_DH_GEX_GROUP, SSH2_PKTCTX_DHGEX);
translatek(SSH2_MSG_KEX_DH_GEX_INIT, SSH2_PKTCTX_DHGEX);
@ -2805,6 +2810,17 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring)
logevent("We believe remote version has SSH-2 ignore bug");
}
if (conf_get_int(ssh->conf, CONF_sshbug_oldgex2) == FORCE_ON ||
(conf_get_int(ssh->conf, CONF_sshbug_oldgex2) == AUTO &&
(wc_match("OpenSSH_2.[235]*", imp)))) {
/*
* These versions only support the original (pre-RFC4419)
* SSH-2 GEX request.
*/
ssh->remote_bugs |= BUG_SSH2_OLDGEX;
logevent("We believe remote version has outdated SSH-2 GEX");
}
if (conf_get_int(ssh->conf, CONF_sshbug_winadj) == FORCE_ON) {
/*
* Servers that don't support our winadj request for one
@ -6595,8 +6611,19 @@ static void do_ssh2_transport(Ssh ssh, void *vin, int inlen,
* much data.
*/
s->pbits = 512 << ((s->nbits - 1) / 64);
s->pktout = ssh2_pkt_init(SSH2_MSG_KEX_DH_GEX_REQUEST);
ssh2_pkt_adduint32(s->pktout, s->pbits);
if (s->pbits < DH_MIN_SIZE)
s->pbits = DH_MIN_SIZE;
if (s->pbits > DH_MAX_SIZE)
s->pbits = DH_MAX_SIZE;
if ((ssh->remote_bugs & BUG_SSH2_OLDGEX)) {
s->pktout = ssh2_pkt_init(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD);
ssh2_pkt_adduint32(s->pktout, s->pbits);
} else {
s->pktout = ssh2_pkt_init(SSH2_MSG_KEX_DH_GEX_REQUEST);
ssh2_pkt_adduint32(s->pktout, DH_MIN_SIZE);
ssh2_pkt_adduint32(s->pktout, s->pbits);
ssh2_pkt_adduint32(s->pktout, DH_MAX_SIZE);
}
ssh2_pkt_send_noqueue(ssh, s->pktout);
crWaitUntilV(pktin);
@ -6664,7 +6691,11 @@ static void do_ssh2_transport(Ssh ssh, void *vin, int inlen,
hash_string(ssh->kex->hash, ssh->exhash, s->hostkeydata, s->hostkeylen);
if (!ssh->kex->pdata) {
if (!(ssh->remote_bugs & BUG_SSH2_OLDGEX))
hash_uint32(ssh->kex->hash, ssh->exhash, DH_MIN_SIZE);
hash_uint32(ssh->kex->hash, ssh->exhash, s->pbits);
if (!(ssh->remote_bugs & BUG_SSH2_OLDGEX))
hash_uint32(ssh->kex->hash, ssh->exhash, DH_MAX_SIZE);
hash_mpint(ssh->kex->hash, ssh->exhash, s->p);
hash_mpint(ssh->kex->hash, ssh->exhash, s->g);
}

3
ssh.h
View File

@ -720,7 +720,8 @@ void platform_ssh_share_cleanup(const char *name);
#define SSH2_MSG_NEWKEYS 21 /* 0x15 */
#define SSH2_MSG_KEXDH_INIT 30 /* 0x1e */
#define SSH2_MSG_KEXDH_REPLY 31 /* 0x1f */
#define SSH2_MSG_KEX_DH_GEX_REQUEST 30 /* 0x1e */
#define SSH2_MSG_KEX_DH_GEX_REQUEST_OLD 30 /* 0x1e */
#define SSH2_MSG_KEX_DH_GEX_REQUEST 34 /* 0x1e */
#define SSH2_MSG_KEX_DH_GEX_GROUP 31 /* 0x1f */
#define SSH2_MSG_KEX_DH_GEX_INIT 32 /* 0x20 */
#define SSH2_MSG_KEX_DH_GEX_REPLY 33 /* 0x21 */

View File

@ -148,6 +148,7 @@
#define WINHELP_CTX_ssh_bugs_maxpkt2 "ssh.bugs.maxpkt2:config-ssh-bug-maxpkt2"
#define WINHELP_CTX_ssh_bugs_winadj "ssh.bugs.winadj:config-ssh-bug-winadj"
#define WINHELP_CTX_ssh_bugs_chanreq "ssh.bugs.winadj:config-ssh-bug-chanreq"
#define WINHELP_CTX_ssh_bugs_oldgex2 "ssh.bugs.oldgex2:config-ssh-bug-oldgex2"
#define WINHELP_CTX_serial_line "serial.line:config-serial-line"
#define WINHELP_CTX_serial_speed "serial.speed:config-serial-speed"
#define WINHELP_CTX_serial_databits "serial.databits:config-serial-databits"