зеркало из https://github.com/github/putty.git
Add a preference list for SSH-2 key exchange algorithms, on a new "Kex" panel
(which will gain more content anon). Retire BUG_SSH2_DH_GEX and add a backwards-compatibility wart, since we never did find a way of automatically detecting this alleged server bug, and in any case there was only ever one report (<3D91F3B5.7030309@inwind.it>, FWIW). Also generalise askcipher() to a new askalg() (thus touching all the front-ends). I've made some attempt to document what SSH key exchange is and why you care, but it could use some review for clarity (and outright lies). [originally from svn r5022]
This commit is contained in:
Родитель
f13f9f6420
Коммит
3c98d6e60d
64
config.c
64
config.c
|
@ -124,6 +124,48 @@ static void cipherlist_handler(union control *ctrl, void *dlg,
|
|||
}
|
||||
}
|
||||
|
||||
static void kexlist_handler(union control *ctrl, void *dlg,
|
||||
void *data, int event)
|
||||
{
|
||||
Config *cfg = (Config *)data;
|
||||
if (event == EVENT_REFRESH) {
|
||||
int i;
|
||||
|
||||
static const struct { char *s; int k; } kexes[] = {
|
||||
{ "Diffie-Hellman group 1", KEX_DHGROUP1 },
|
||||
{ "Diffie-Hellman group 14", KEX_DHGROUP14 },
|
||||
{ "Diffie-Hellman group exchange", KEX_DHGEX },
|
||||
{ "-- warn below here --", KEX_WARN }
|
||||
};
|
||||
|
||||
/* Set up the "kex preference" box. */
|
||||
/* (kexlist assumed to contain all algorithms) */
|
||||
dlg_update_start(ctrl, dlg);
|
||||
dlg_listbox_clear(ctrl, dlg);
|
||||
for (i = 0; i < KEX_MAX; i++) {
|
||||
int k = cfg->ssh_kexlist[i];
|
||||
int j;
|
||||
char *kstr = NULL;
|
||||
for (j = 0; j < (sizeof kexes) / (sizeof kexes[0]); j++) {
|
||||
if (kexes[j].k == k) {
|
||||
kstr = kexes[j].s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dlg_listbox_addwithid(ctrl, dlg, kstr, k);
|
||||
}
|
||||
dlg_update_done(ctrl, dlg);
|
||||
|
||||
} else if (event == EVENT_VALCHANGE) {
|
||||
int i;
|
||||
|
||||
/* Update array to match the list box. */
|
||||
for (i=0; i < KEX_MAX; i++)
|
||||
cfg->ssh_kexlist[i] = dlg_listbox_getid(ctrl, dlg, i);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void printerbox_handler(union control *ctrl, void *dlg,
|
||||
void *data, int event)
|
||||
{
|
||||
|
@ -1525,6 +1567,25 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
|
|||
dlg_stdcheckbox_handler,
|
||||
I(offsetof(Config,ssh2_des_cbc)));
|
||||
|
||||
/*
|
||||
* The Connection/SSH/Kex panel.
|
||||
*/
|
||||
ctrl_settitle(b, "Connection/SSH/Kex",
|
||||
"Options controlling SSH key exchange");
|
||||
|
||||
s = ctrl_getset(b, "Connection/SSH/Kex", "main",
|
||||
"Key exchange algorithm options");
|
||||
c = ctrl_draglist(s, "Algorithm selection policy", 's',
|
||||
HELPCTX(ssh_kexlist),
|
||||
kexlist_handler, P(NULL));
|
||||
c->listbox.height = 5;
|
||||
|
||||
#if 0
|
||||
s = ctrl_getset(b, "Connection/SSH/Kex", "repeat",
|
||||
"Options controlling key re-exchange");
|
||||
/* FIXME: at least time and data size */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The Connection/SSH/Auth panel.
|
||||
*/
|
||||
|
@ -1659,9 +1720,6 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
|
|||
ctrl_droplist(s, "Requires padding on SSH2 RSA signatures", 'p', 20,
|
||||
HELPCTX(ssh_bugs_rsapad2),
|
||||
sshbug_handler, I(offsetof(Config,sshbug_rsapad2)));
|
||||
ctrl_droplist(s, "Chokes on Diffie-Hellman group exchange", 'd', 20,
|
||||
HELPCTX(ssh_bugs_dhgex2),
|
||||
sshbug_handler, I(offsetof(Config,sshbug_dhgex2)));
|
||||
ctrl_droplist(s, "Misuses the session ID in PK auth", 'n', 20,
|
||||
HELPCTX(ssh_bugs_pksessid2),
|
||||
sshbug_handler, I(offsetof(Config,sshbug_pksessid2)));
|
||||
|
|
|
@ -2098,6 +2098,77 @@ these servers if you enable the \q{Enable legacy use of single-DES in
|
|||
SSH 2} option; by default this is disabled and PuTTY will stick to
|
||||
recommended ciphers.
|
||||
|
||||
\H{config-ssh-kex} The Kex panel
|
||||
|
||||
\# FIXME: This whole section is draft. Feel free to revise.
|
||||
|
||||
The Kex panel (short for \q{key exchange}) allows you to configure
|
||||
options related to SSH-2 key exchange.
|
||||
|
||||
Key exchange occurs at the start of an SSH connection (and
|
||||
occasionally thereafter); it establishes a shared secret that is used
|
||||
as the basis for all of SSH's security features. It is therefore very
|
||||
important for the security of the connection that the key exchange is
|
||||
secure.
|
||||
|
||||
Key exchange is a cryptographically intensive process; if either the
|
||||
client or the server is a relatively slow machine, the slower methods
|
||||
may take several tens of seconds to complete.
|
||||
|
||||
If connection startup is too slow, or the connection hangs
|
||||
periodically, you may want to try changing these settings.
|
||||
|
||||
If you don't understand what any of this means, it's safe to leave
|
||||
these settings alone.
|
||||
|
||||
This entire panel is only relevant to SSH protocol version 2; none of
|
||||
these settings affect SSH-1 at all.
|
||||
|
||||
\S{config-ssh-kex-order} Key exchange algorithm selection
|
||||
|
||||
\cfg{winhelp-topic}{ssh.kex.order}
|
||||
|
||||
PuTTY supports a variety of SSH-2 key exchange methods, and allows you
|
||||
to choose which one you prefer to use; configuration is similar to
|
||||
cipher selection (see \k{config-ssh-encryption}).
|
||||
|
||||
PuTTY currently supports the following varieties of Diffie-Hellman key
|
||||
exchange:
|
||||
|
||||
\b \q{Group 14}: a well-known 2048-bit group.
|
||||
|
||||
\b \q{Group 1}: a well-known 1024-bit group. This is less secure
|
||||
\#{FIXME better words} than group 14, but may be faster with slow
|
||||
client or server machines, and may be the only method supported by
|
||||
older server software.
|
||||
|
||||
\b \q{Group exchange}: with this method, instead of using a fixed
|
||||
group, PuTTY requests that the server suggest a group to use for key
|
||||
exchange; the server can avoid groups known to be weak, and possibly
|
||||
invent new ones over time, without any changes required to PuTTY's
|
||||
configuration. We recommend use of this method, if possible.
|
||||
|
||||
If the first algorithm PuTTY finds is below the \q{warn below here}
|
||||
line, you will see a warning box when you make the connection, similar
|
||||
to that for cipher selection (see \k{config-ssh-encryption}).
|
||||
|
||||
\# [Repeat key exchange bumph when config is added:] If the session
|
||||
key negotiated at connection startup is used too much or for too long,
|
||||
it may become feasible to mount attacks against the SSH connection.
|
||||
Therefore, the SSH protocol specifies that a new key exchange should
|
||||
take place every so often.
|
||||
|
||||
\# While this renegotiation is taking place, no data can pass through
|
||||
the SSH connection, so it may appear to \q{freeze}. (The occurrence of
|
||||
repeat key exchange is noted in the Event Log; see
|
||||
\k{using-eventlog}.) Usually the same algorithm is used as at the
|
||||
start of the connection, with a similar overhead.
|
||||
|
||||
\# [When options are added to frob how often this happens, we should
|
||||
hardcode the values recommended by the drafts -- 1 hour, 1GB -- in
|
||||
this documentation, in case PuTTY's defaults are obscured by Default
|
||||
Settings etc. Assuming we think they're good advice, that is.]
|
||||
|
||||
\H{config-ssh-auth} The Auth panel
|
||||
|
||||
The Auth panel allows you to configure authentication options for
|
||||
|
@ -2455,23 +2526,6 @@ to talking to OpenSSH.
|
|||
|
||||
This is an SSH2-specific bug.
|
||||
|
||||
\S{config-ssh-bug-dhgex} \q{Chokes on Diffie-Hellman group exchange}
|
||||
|
||||
\cfg{winhelp-topic}{ssh.bugs.dhgex2}
|
||||
|
||||
We have anecdotal evidence that some SSH servers claim to be able to
|
||||
perform Diffie-Hellman group exchange, but fail to actually do so
|
||||
when PuTTY tries to. If your SSH2 sessions spontaneously close
|
||||
immediately after opening the PuTTY window, it might be worth
|
||||
enabling the workaround for this bug to see if it helps.
|
||||
|
||||
We have no hard evidence that any specific version of specific
|
||||
server software reliably demonstrates this bug. Therefore, PuTTY
|
||||
will never \e{assume} a server has this bug; if you want the
|
||||
workaround, you need to enable it manually.
|
||||
|
||||
This is an SSH2-specific bug.
|
||||
|
||||
\S{config-ssh-bug-pksessid2} \q{Misuses the session ID in PK auth}
|
||||
|
||||
\cfg{winhelp-topic}{ssh.bugs.pksessid2}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: mac.c,v 1.59 2003/05/10 12:27:38 ben Exp $ */
|
||||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (c) 1999, 2003 Ben Harris
|
||||
* All rights reserved.
|
||||
|
@ -704,7 +704,7 @@ void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
|
|||
}
|
||||
}
|
||||
|
||||
void askcipher(void *frontend, char *ciphername, int cs)
|
||||
void askalg(void *frontend, const char *algtype, const char *algname)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
16
putty.h
16
putty.h
|
@ -232,6 +232,17 @@ enum {
|
|||
VT_XWINDOWS, VT_OEMANSI, VT_OEMONLY, VT_POORMAN, VT_UNICODE
|
||||
};
|
||||
|
||||
enum {
|
||||
/*
|
||||
* SSH-2 key exchange algorithms
|
||||
*/
|
||||
KEX_WARN,
|
||||
KEX_DHGROUP1,
|
||||
KEX_DHGROUP14,
|
||||
KEX_DHGEX,
|
||||
KEX_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
/*
|
||||
* SSH ciphers (both SSH1 and SSH2)
|
||||
|
@ -388,6 +399,7 @@ struct config_tag {
|
|||
* but never for loading/saving */
|
||||
int nopty;
|
||||
int compression;
|
||||
int ssh_kexlist[KEX_MAX];
|
||||
int agentfwd;
|
||||
int change_username; /* allow username switching in SSH2 */
|
||||
int ssh_cipherlist[CIPHER_MAX];
|
||||
|
@ -514,7 +526,7 @@ struct config_tag {
|
|||
/* SSH bug compatibility modes */
|
||||
int sshbug_ignore1, sshbug_plainpw1, sshbug_rsa1,
|
||||
sshbug_hmac2, sshbug_derivekey2, sshbug_rsapad2,
|
||||
sshbug_dhgex2, sshbug_pksessid2;
|
||||
sshbug_pksessid2;
|
||||
/* Options for pterm. Should split out into platform-dependent part. */
|
||||
int stamp_utmp;
|
||||
int login_shell;
|
||||
|
@ -862,7 +874,7 @@ int wc_unescape(char *output, const char *wildcard);
|
|||
void logevent(void *frontend, const char *);
|
||||
void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
|
||||
char *keystr, char *fingerprint);
|
||||
void askcipher(void *frontend, char *ciphername, int cs);
|
||||
void askalg(void *frontend, const char *algtype, const char *algname);
|
||||
int askappend(void *frontend, Filename filename);
|
||||
|
||||
/*
|
||||
|
|
25
settings.c
25
settings.c
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
struct keyval { char *s; int v; };
|
||||
|
||||
/* The cipher order given here is the default order. */
|
||||
static const struct keyval ciphernames[] = {
|
||||
{ "aes", CIPHER_AES },
|
||||
{ "blowfish", CIPHER_BLOWFISH },
|
||||
|
@ -20,6 +21,13 @@ static const struct keyval ciphernames[] = {
|
|||
{ "des", CIPHER_DES }
|
||||
};
|
||||
|
||||
static const struct keyval kexnames[] = {
|
||||
{ "dh-gex-sha1", KEX_DHGEX },
|
||||
{ "dh-group14-sha1", KEX_DHGROUP14 },
|
||||
{ "dh-group1-sha1", KEX_DHGROUP1 },
|
||||
{ "WARN", KEX_WARN }
|
||||
};
|
||||
|
||||
static void gpps(void *handle, const char *name, const char *def,
|
||||
char *val, int len)
|
||||
{
|
||||
|
@ -227,6 +235,7 @@ void save_open_settings(void *sesskey, int do_host, Config *cfg)
|
|||
write_setting_i(sesskey, "ChangeUsername", cfg->change_username);
|
||||
wprefs(sesskey, "Cipher", ciphernames, CIPHER_MAX,
|
||||
cfg->ssh_cipherlist);
|
||||
wprefs(sesskey, "KEX", kexnames, KEX_MAX, cfg->ssh_kexlist);
|
||||
write_setting_i(sesskey, "AuthTIS", cfg->try_tis_auth);
|
||||
write_setting_i(sesskey, "AuthKI", cfg->try_ki_auth);
|
||||
write_setting_i(sesskey, "SshNoShell", cfg->ssh_no_shell);
|
||||
|
@ -358,7 +367,6 @@ void save_open_settings(void *sesskey, int do_host, Config *cfg)
|
|||
write_setting_i(sesskey, "BugHMAC2", 2-cfg->sshbug_hmac2);
|
||||
write_setting_i(sesskey, "BugDeriveKey2", 2-cfg->sshbug_derivekey2);
|
||||
write_setting_i(sesskey, "BugRSAPad2", 2-cfg->sshbug_rsapad2);
|
||||
write_setting_i(sesskey, "BugDHGEx2", 2-cfg->sshbug_dhgex2);
|
||||
write_setting_i(sesskey, "BugPKSessID2", 2-cfg->sshbug_pksessid2);
|
||||
write_setting_i(sesskey, "StampUtmp", cfg->stamp_utmp);
|
||||
write_setting_i(sesskey, "LoginShell", cfg->login_shell);
|
||||
|
@ -492,6 +500,20 @@ void load_open_settings(void *sesskey, int do_host, Config *cfg)
|
|||
gppi(sesskey, "ChangeUsername", 0, &cfg->change_username);
|
||||
gprefs(sesskey, "Cipher", "\0",
|
||||
ciphernames, CIPHER_MAX, cfg->ssh_cipherlist);
|
||||
{
|
||||
/* Backward-compatibility: we used to have an option to
|
||||
* disable gex under the "bugs" panel after one report of
|
||||
* a server which offered it then choked, but we never got
|
||||
* a server version string or any other reports. */
|
||||
char *default_kexes;
|
||||
gppi(sesskey, "BugDHGEx2", 0, &i); i = 2-i;
|
||||
if (i == FORCE_ON)
|
||||
default_kexes = "dh-group14-sha1,dh-group1-sha1,WARN,dh-gex-sha1";
|
||||
else
|
||||
default_kexes = "dh-gex-sha1,dh-group14-sha1,dh-group1-sha1,WARN";
|
||||
gprefs(sesskey, "KEX", default_kexes,
|
||||
kexnames, KEX_MAX, cfg->ssh_kexlist);
|
||||
}
|
||||
gppi(sesskey, "SshProt", 2, &cfg->sshprot);
|
||||
gppi(sesskey, "SSH2DES", 0, &cfg->ssh2_des_cbc);
|
||||
gppi(sesskey, "AuthTIS", 0, &cfg->try_tis_auth);
|
||||
|
@ -667,7 +689,6 @@ void load_open_settings(void *sesskey, int do_host, Config *cfg)
|
|||
}
|
||||
gppi(sesskey, "BugDeriveKey2", 0, &i); cfg->sshbug_derivekey2 = 2-i;
|
||||
gppi(sesskey, "BugRSAPad2", 0, &i); cfg->sshbug_rsapad2 = 2-i;
|
||||
gppi(sesskey, "BugDHGEx2", 0, &i); cfg->sshbug_dhgex2 = 2-i;
|
||||
gppi(sesskey, "BugPKSessID2", 0, &i); cfg->sshbug_pksessid2 = 2-i;
|
||||
gppi(sesskey, "StampUtmp", 1, &cfg->stamp_utmp);
|
||||
gppi(sesskey, "LoginShell", 1, &cfg->login_shell);
|
||||
|
|
107
ssh.c
107
ssh.c
|
@ -162,7 +162,7 @@ static const char *const ssh2_disconnect_reasons[] = {
|
|||
#define BUG_CHOKES_ON_RSA 8
|
||||
#define BUG_SSH2_RSA_PADDING 16
|
||||
#define BUG_SSH2_DERIVEKEY 32
|
||||
#define BUG_SSH2_DH_GEX 64
|
||||
/* 64 was BUG_SSH2_DH_GEX, now spare */
|
||||
#define BUG_SSH2_PK_SESSIONID 128
|
||||
|
||||
#define translate(x) if (type == x) return #x
|
||||
|
@ -360,12 +360,6 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
|
|||
#define SSH_MAX_BACKLOG 32768
|
||||
#define OUR_V2_WINSIZE 16384
|
||||
|
||||
const static struct ssh_kex *kex_algs[] = {
|
||||
&ssh_diffiehellman_gex,
|
||||
&ssh_diffiehellman_group14,
|
||||
&ssh_diffiehellman_group1,
|
||||
};
|
||||
|
||||
const static struct ssh_signkey *hostkey_algs[] = { &ssh_rsa, &ssh_dss };
|
||||
|
||||
static void *nullmac_make_context(void)
|
||||
|
@ -2058,14 +2052,6 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring)
|
|||
ssh->remote_bugs |= BUG_SSH2_PK_SESSIONID;
|
||||
logevent("We believe remote version has SSH2 public-key-session-ID bug");
|
||||
}
|
||||
|
||||
if (ssh->cfg.sshbug_dhgex2 == FORCE_ON) {
|
||||
/*
|
||||
* User specified the SSH2 DH GEX bug.
|
||||
*/
|
||||
ssh->remote_bugs |= BUG_SSH2_DH_GEX;
|
||||
logevent("We believe remote version has SSH2 DH group exchange bug");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2761,7 +2747,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen,
|
|||
|
||||
/* Warn about chosen cipher if necessary. */
|
||||
if (warn)
|
||||
askcipher(ssh->frontend, cipher_string, 0);
|
||||
askalg(ssh->frontend, "cipher", cipher_string);
|
||||
}
|
||||
|
||||
switch (s->cipher_type) {
|
||||
|
@ -4321,6 +4307,8 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen,
|
|||
int hostkeylen, siglen;
|
||||
void *hkey; /* actual host key */
|
||||
unsigned char exchange_hash[20];
|
||||
int n_preferred_kex;
|
||||
const struct ssh_kex *preferred_kex[KEX_MAX];
|
||||
int n_preferred_ciphers;
|
||||
const struct ssh2_ciphers *preferred_ciphers[CIPHER_MAX];
|
||||
const struct ssh_compress *preferred_comp;
|
||||
|
@ -4337,6 +4325,37 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen,
|
|||
|
||||
s->first_kex = 1;
|
||||
|
||||
{
|
||||
int i;
|
||||
/*
|
||||
* Set up the preferred key exchange. (NULL => warn below here)
|
||||
*/
|
||||
s->n_preferred_kex = 0;
|
||||
for (i = 0; i < KEX_MAX; i++) {
|
||||
switch (ssh->cfg.ssh_kexlist[i]) {
|
||||
case KEX_DHGEX:
|
||||
s->preferred_kex[s->n_preferred_kex++] =
|
||||
&ssh_diffiehellman_gex;
|
||||
break;
|
||||
case KEX_DHGROUP14:
|
||||
s->preferred_kex[s->n_preferred_kex++] =
|
||||
&ssh_diffiehellman_group14;
|
||||
break;
|
||||
case KEX_DHGROUP1:
|
||||
s->preferred_kex[s->n_preferred_kex++] =
|
||||
&ssh_diffiehellman_group1;
|
||||
break;
|
||||
case CIPHER_WARN:
|
||||
/* Flag for later. Don't bother if it's the last in
|
||||
* the list. */
|
||||
if (i < KEX_MAX - 1) {
|
||||
s->preferred_kex[s->n_preferred_kex++] = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int i;
|
||||
/*
|
||||
|
@ -4388,7 +4407,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen,
|
|||
|
||||
begin_key_exchange:
|
||||
{
|
||||
int i, j, cipherstr_started;
|
||||
int i, j, commalist_started;
|
||||
|
||||
/*
|
||||
* Enable queueing of outgoing auth- or connection-layer
|
||||
|
@ -4409,13 +4428,14 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen,
|
|||
ssh2_pkt_addbyte(s->pktout, (unsigned char) random_byte());
|
||||
/* List key exchange algorithms. */
|
||||
ssh2_pkt_addstring_start(s->pktout);
|
||||
for (i = 0; i < lenof(kex_algs); i++) {
|
||||
if (kex_algs[i] == &ssh_diffiehellman_gex &&
|
||||
(ssh->remote_bugs & BUG_SSH2_DH_GEX))
|
||||
continue;
|
||||
ssh2_pkt_addstring_str(s->pktout, kex_algs[i]->name);
|
||||
if (i < lenof(kex_algs) - 1)
|
||||
commalist_started = 0;
|
||||
for (i = 0; i < s->n_preferred_kex; i++) {
|
||||
const struct ssh_kex *k = s->preferred_kex[i];
|
||||
if (!k) continue; /* warning flag */
|
||||
if (commalist_started)
|
||||
ssh2_pkt_addstring_str(s->pktout, ",");
|
||||
ssh2_pkt_addstring_str(s->pktout, s->preferred_kex[i]->name);
|
||||
commalist_started = 1;
|
||||
}
|
||||
/* List server host key algorithms. */
|
||||
ssh2_pkt_addstring_start(s->pktout);
|
||||
|
@ -4426,28 +4446,28 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen,
|
|||
}
|
||||
/* List client->server encryption algorithms. */
|
||||
ssh2_pkt_addstring_start(s->pktout);
|
||||
cipherstr_started = 0;
|
||||
commalist_started = 0;
|
||||
for (i = 0; i < s->n_preferred_ciphers; i++) {
|
||||
const struct ssh2_ciphers *c = s->preferred_ciphers[i];
|
||||
if (!c) continue; /* warning flag */
|
||||
for (j = 0; j < c->nciphers; j++) {
|
||||
if (cipherstr_started)
|
||||
if (commalist_started)
|
||||
ssh2_pkt_addstring_str(s->pktout, ",");
|
||||
ssh2_pkt_addstring_str(s->pktout, c->list[j]->name);
|
||||
cipherstr_started = 1;
|
||||
commalist_started = 1;
|
||||
}
|
||||
}
|
||||
/* List server->client encryption algorithms. */
|
||||
ssh2_pkt_addstring_start(s->pktout);
|
||||
cipherstr_started = 0;
|
||||
commalist_started = 0;
|
||||
for (i = 0; i < s->n_preferred_ciphers; i++) {
|
||||
const struct ssh2_ciphers *c = s->preferred_ciphers[i];
|
||||
if (!c) continue; /* warning flag */
|
||||
for (j = 0; j < c->nciphers; j++) {
|
||||
if (cipherstr_started)
|
||||
if (commalist_started)
|
||||
ssh2_pkt_addstring_str(s->pktout, ",");
|
||||
ssh2_pkt_addstring_str(s->pktout, c->list[j]->name);
|
||||
cipherstr_started = 1;
|
||||
commalist_started = 1;
|
||||
}
|
||||
}
|
||||
/* List client->server MAC algorithms. */
|
||||
|
@ -4528,15 +4548,26 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen,
|
|||
s->sccomp_tobe = NULL;
|
||||
pktin->savedpos += 16; /* skip garbage cookie */
|
||||
ssh_pkt_getstring(pktin, &str, &len); /* key exchange algorithms */
|
||||
for (i = 0; i < lenof(kex_algs); i++) {
|
||||
if (kex_algs[i] == &ssh_diffiehellman_gex &&
|
||||
(ssh->remote_bugs & BUG_SSH2_DH_GEX))
|
||||
continue;
|
||||
if (in_commasep_string(kex_algs[i]->name, str, len)) {
|
||||
ssh->kex = kex_algs[i];
|
||||
s->warn = 0;
|
||||
for (i = 0; i < s->n_preferred_kex; i++) {
|
||||
const struct ssh_kex *k = s->preferred_kex[i];
|
||||
if (!k) {
|
||||
s->warn = 1;
|
||||
} else if (in_commasep_string(k->name, str, len)) {
|
||||
ssh->kex = k;
|
||||
}
|
||||
if (ssh->kex) {
|
||||
if (s->warn)
|
||||
askalg(ssh->frontend, "key-exchange algorithm",
|
||||
ssh->kex->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ssh->kex) {
|
||||
bombout(("Couldn't agree a key exchange algorithm (available: %s)",
|
||||
str ? str : "(null)"));
|
||||
crStop(0);
|
||||
}
|
||||
ssh_pkt_getstring(pktin, &str, &len); /* host key algorithms */
|
||||
for (i = 0; i < lenof(hostkey_algs); i++) {
|
||||
if (in_commasep_string(hostkey_algs[i]->name, str, len)) {
|
||||
|
@ -4560,7 +4591,8 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen,
|
|||
}
|
||||
if (s->cscipher_tobe) {
|
||||
if (s->warn)
|
||||
askcipher(ssh->frontend, s->cscipher_tobe->name, 1);
|
||||
askalg(ssh->frontend, "client-to-server cipher",
|
||||
s->cscipher_tobe->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -4586,7 +4618,8 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen,
|
|||
}
|
||||
if (s->sccipher_tobe) {
|
||||
if (s->warn)
|
||||
askcipher(ssh->frontend, s->sccipher_tobe->name, 2);
|
||||
askalg(ssh->frontend, "server-to-client cipher",
|
||||
s->sccipher_tobe->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2351,22 +2351,19 @@ void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
|
|||
}
|
||||
|
||||
/*
|
||||
* Ask whether the selected cipher is acceptable (since it was
|
||||
* Ask whether the selected algorithm is acceptable (since it was
|
||||
* below the configured 'warn' threshold).
|
||||
* cs: 0 = both ways, 1 = client->server, 2 = server->client
|
||||
*/
|
||||
void askcipher(void *frontend, char *ciphername, int cs)
|
||||
void askalg(void *frontend, const char *algtype, const char *algname)
|
||||
{
|
||||
static const char msg[] =
|
||||
"The first %scipher supported by the server is "
|
||||
"The first %s supported by the server is "
|
||||
"%s, which is below the configured warning threshold.\n"
|
||||
"Continue with connection?";
|
||||
char *text;
|
||||
int ret;
|
||||
|
||||
text = dupprintf(msg, (cs == 0) ? "" :
|
||||
(cs == 1) ? "client-to-server " : "server-to-client ",
|
||||
ciphername);
|
||||
text = dupprintf(msg, algtype, algname);
|
||||
ret = messagebox(GTK_WIDGET(get_window(frontend)),
|
||||
"PuTTY Security Alert", text,
|
||||
string_width("Continue with connection?"),
|
||||
|
|
|
@ -143,18 +143,17 @@ void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
|
|||
}
|
||||
|
||||
/*
|
||||
* Ask whether the selected cipher is acceptable (since it was
|
||||
* Ask whether the selected algorithm is acceptable (since it was
|
||||
* below the configured 'warn' threshold).
|
||||
* cs: 0 = both ways, 1 = client->server, 2 = server->client
|
||||
*/
|
||||
void askcipher(void *frontend, char *ciphername, int cs)
|
||||
void askalg(void *frontend, const char *algtype, const char *algname)
|
||||
{
|
||||
static const char msg[] =
|
||||
"The first %scipher supported by the server is\n"
|
||||
"The first %s supported by the server is\n"
|
||||
"%s, which is below the configured warning threshold.\n"
|
||||
"Continue with connection? (y/n) ";
|
||||
static const char msg_batch[] =
|
||||
"The first %scipher supported by the server is\n"
|
||||
"The first %s supported by the server is\n"
|
||||
"%s, which is below the configured warning threshold.\n"
|
||||
"Connection abandoned.\n";
|
||||
static const char abandoned[] = "Connection abandoned.\n";
|
||||
|
@ -162,17 +161,11 @@ void askcipher(void *frontend, char *ciphername, int cs)
|
|||
char line[32];
|
||||
|
||||
if (console_batch_mode) {
|
||||
fprintf(stderr, msg_batch,
|
||||
(cs == 0) ? "" :
|
||||
(cs == 1) ? "client-to-server " : "server-to-client ",
|
||||
ciphername);
|
||||
fprintf(stderr, msg_batch, algtype, algname);
|
||||
cleanup_exit(1);
|
||||
}
|
||||
|
||||
fprintf(stderr, msg,
|
||||
(cs == 0) ? "" :
|
||||
(cs == 1) ? "client-to-server " : "server-to-client ",
|
||||
ciphername);
|
||||
fprintf(stderr, msg, algtype, algname);
|
||||
fflush(stderr);
|
||||
|
||||
{
|
||||
|
|
|
@ -147,21 +147,20 @@ void update_specials_menu(void *frontend)
|
|||
}
|
||||
|
||||
/*
|
||||
* Ask whether the selected cipher is acceptable (since it was
|
||||
* Ask whether the selected algorithm is acceptable (since it was
|
||||
* below the configured 'warn' threshold).
|
||||
* cs: 0 = both ways, 1 = client->server, 2 = server->client
|
||||
*/
|
||||
void askcipher(void *frontend, char *ciphername, int cs)
|
||||
void askalg(void *frontend, const char *algtype, const char *algname)
|
||||
{
|
||||
HANDLE hin;
|
||||
DWORD savemode, i;
|
||||
|
||||
static const char msg[] =
|
||||
"The first %scipher supported by the server is\n"
|
||||
"The first %s supported by the server is\n"
|
||||
"%s, which is below the configured warning threshold.\n"
|
||||
"Continue with connection? (y/n) ";
|
||||
static const char msg_batch[] =
|
||||
"The first %scipher supported by the server is\n"
|
||||
"The first %s supported by the server is\n"
|
||||
"%s, which is below the configured warning threshold.\n"
|
||||
"Connection abandoned.\n";
|
||||
static const char abandoned[] = "Connection abandoned.\n";
|
||||
|
@ -169,17 +168,11 @@ void askcipher(void *frontend, char *ciphername, int cs)
|
|||
char line[32];
|
||||
|
||||
if (console_batch_mode) {
|
||||
fprintf(stderr, msg_batch,
|
||||
(cs == 0) ? "" :
|
||||
(cs == 1) ? "client-to-server " : "server-to-client ",
|
||||
ciphername);
|
||||
fprintf(stderr, msg_batch, algtype, algname);
|
||||
cleanup_exit(1);
|
||||
}
|
||||
|
||||
fprintf(stderr, msg,
|
||||
(cs == 0) ? "" :
|
||||
(cs == 1) ? "client-to-server " : "server-to-client ",
|
||||
ciphername);
|
||||
fprintf(stderr, msg, algtype, algname);
|
||||
fflush(stderr);
|
||||
|
||||
hin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
|
|
|
@ -777,24 +777,21 @@ void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
|
|||
}
|
||||
|
||||
/*
|
||||
* Ask whether the selected cipher is acceptable (since it was
|
||||
* Ask whether the selected algorithm is acceptable (since it was
|
||||
* below the configured 'warn' threshold).
|
||||
* cs: 0 = both ways, 1 = client->server, 2 = server->client
|
||||
*/
|
||||
void askcipher(void *frontend, char *ciphername, int cs)
|
||||
void askalg(void *frontend, const char *algtype, const char *algname)
|
||||
{
|
||||
static const char mbtitle[] = "%s Security Alert";
|
||||
static const char msg[] =
|
||||
"The first %.35scipher supported by the server\n"
|
||||
"The first %s supported by the server\n"
|
||||
"is %.64s, which is below the configured\n"
|
||||
"warning threshold.\n"
|
||||
"Do you want to continue with this connection?\n";
|
||||
char *message, *title;
|
||||
int mbret;
|
||||
|
||||
message = dupprintf(msg, ((cs == 0) ? "" :
|
||||
(cs == 1) ? "client-to-server " :
|
||||
"server-to-client "), ciphername);
|
||||
message = dupprintf(msg, algtype, algname);
|
||||
title = dupprintf(mbtitle, appname);
|
||||
mbret = MessageBox(NULL, message, title,
|
||||
MB_ICONWARNING | MB_YESNO);
|
||||
|
|
|
@ -86,6 +86,7 @@
|
|||
#define WINHELP_CTX_ssh_protocol "ssh.protocol"
|
||||
#define WINHELP_CTX_ssh_command "ssh.command"
|
||||
#define WINHELP_CTX_ssh_compress "ssh.compress"
|
||||
#define WINHELP_CTX_ssh_kexlist "ssh.kex.order"
|
||||
#define WINHELP_CTX_ssh_auth_privkey "ssh.auth.privkey"
|
||||
#define WINHELP_CTX_ssh_auth_agentfwd "ssh.auth.agentfwd"
|
||||
#define WINHELP_CTX_ssh_auth_changeuser "ssh.auth.changeuser"
|
||||
|
@ -116,5 +117,4 @@
|
|||
#define WINHELP_CTX_ssh_bugs_hmac2 "ssh.bugs.hmac2"
|
||||
#define WINHELP_CTX_ssh_bugs_derivekey2 "ssh.bugs.derivekey2"
|
||||
#define WINHELP_CTX_ssh_bugs_rsapad2 "ssh.bugs.rsapad2"
|
||||
#define WINHELP_CTX_ssh_bugs_dhgex2 "ssh.bugs.dhgex2"
|
||||
#define WINHELP_CTX_ssh_bugs_pksessid2 "ssh.bugs.pksessid2"
|
||||
|
|
Загрузка…
Ссылка в новой задаче