From 2c9c6388caa7e80195bffd93be7be7369c20bb98 Mon Sep 17 00:00:00 2001 From: simon Date: Sun, 8 Sep 2002 13:28:38 +0000 Subject: [PATCH] Introduce the Bugs control panel, for overriding PuTTY's server version number checks to determine the presence or absence of server bugs. git-svn-id: svn://svn.tartarus.org/sgt/putty@1936 cda61777-01e9-0310-a592-d414129be87e --- doc/config.but | 160 ++++++++++++++++++++++++++++++++++++++++++++++++------ putty.h | 5 ++ settings.c | 23 ++++++-- ssh.c | 37 ++++++++----- winctrls.c | 34 ++++++++++++ windlg.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- winstuff.h | 2 + 7 files changed, 387 insertions(+), 42 deletions(-) diff --git a/doc/config.but b/doc/config.but index f032ccfc..4a855e0e 100644 --- a/doc/config.but +++ b/doc/config.but @@ -1,4 +1,4 @@ -\versionid $Id: config.but,v 1.36 2002/09/08 13:25:58 jacob Exp $ +\versionid $Id: config.but,v 1.37 2002/09/08 13:28:38 simon Exp $ \C{config} Configuring PuTTY @@ -1356,6 +1356,10 @@ server. Keepalives are only supported in Telnet and SSH; the Rlogin and Raw protocols offer no way of implementing them. +Note that if you are using SSH1 and the server has a bug that makes +it unable to deal with SSH1 ignore messages (see +\k{config-ssh-bug-ignore1}), enabling keepalives will have no effect. + \S{config-nodelay} \q{Disable Nagle's algorithm} \cfg{winhelp-topic}{connection.nodelay} @@ -1662,20 +1666,6 @@ If you select \q{1 only} or \q{2 only} here, PuTTY will only connect if the server you connect to offers the SSH protocol version you have specified. -\S{config-ssh-macbug} \q{Imitate SSH 2 MAC bug} - -\cfg{winhelp-topic}{ssh.buggymac} - -This option \e{should} now be unnecessary. It existed in order to -work around a bug in early versions (2.3.0 and below) of the SSH -server software from \cw{ssh.com}. The symptom of this problem would -be that PuTTY would die unexpectedly at the beginning of the -session, saying \q{Incorrect MAC received on packet}. - -Current versions of PuTTY attempt to detect these faulty servers and -enable the bug compatibility automatically, so you should never need -to use this option any more. - \S{config-ssh-encryption} Encryption algorithm selection \cfg{winhelp-topic}{ssh.ciphers} @@ -1870,6 +1860,146 @@ SSH server machine can connect to the forwarded port.) Note that this feature is only available in the SSH 2 protocol, and not all SSH 2 servers support it (OpenSSH 3.0 does not, for example). +\H{config-ssh-bugs} The Bugs panel + +Not all SSH servers work properly. Various existing servers have +bugs in them, which can make it impossible for a client to talk to +them unless it knows about the bug and works around it. + +Since most servers announce their software version number at the +beginning of the SSH connection, PuTTY will attempt to detect which +bugs it can expect to see in the server and automatically enable +workarounds. However, sometimes it will make mistakes; if the server +has been deliberately configured to conceal its version number, or +if the server is a version which PuTTY's bug database does not know +about, then PuTTY will not know what bugs to expect. + +The Bugs panel allows you to manually configure the bugs PuTTY +expects to see in the server. Each bug can be configured in three +states: + +\b \q{Off}: PuTTY will assume the server does not have the bug. + +\b \q{On}: PuTTY will assume the server \e{does} have the bug. + +\b \q{Auto}: PuTTY will use the server's version number announcement +to try to guess whether or not the server has the bug. + +\S{config-ssh-bug-ignore1} \q{Chokes on SSH1 ignore messages} + +\cfg{winhelp-topic}{ssh.bugs.ignore1} + +An ignore message (SSH_MSG_IGNORE) is a message in the SSH protocol +which can be sent from the client to the server, or from the server +to the client, at any time. Either side is required to ignore the +message whenever it receives it. PuTTY uses ignore messages to hide +the password packet in SSH1, so that a listener cannot tell the +length of the user's password; it also uses ignore messages for +connection keepalives (see \k{config-keepalive}). + +If this bug is detected, PuTTY will stop using ignore messages. This +means that keepalives will stop working, and PuTTY will have to fall +back to a secondary defence against SSH1 password-length +eavesdropping. See \k{config-ssh-bug-plainpw1}. If this bug is +enabled when talking to a correct server, the session will succeed, +but keepalives will not work and the session might be more +vulnerable to eavesdroppers than it could be. + +This is an SSH1-specific bug. No known SSH2 server fails to deal +with SSH2 ignore messages. + +\S{config-ssh-bug-plainpw1} \q{Refuses all SSH1 password camouflage} + +\cfg{winhelp-topic}{ssh.bugs.plainpw1} + +When talking to an SSH1 server which cannot deal with ignore +messages (see \k{config-ssh-bug-ignore1}), PuTTY will attempt to +disguise the length of the user's password by sending additional +padding \e{within} the password packet. This is technically a +violation of the SSH1 specification, and so PuTTY will only do it +when it cannot use standards-compliant ignore messages as +camouflage. In this sense, for a server to refuse to accept a padded +password packet is not really a bug, but it does make life +inconvenient if the server can also not handle ignore messages. + +If this \q{bug} is detected, PuTTY will have no choice but to send +the user's password with no form of camouflage, so that an +eavesdropping user will be easily able to find out the exact length +of the password. If this bug is enabled when talking to a correct +server, the session will succeed, but will be more vulnerable to +eavesdroppers than it could be. + +This is an SSH1-specific bug. SSH2 is secure against this type of +attack. + +\S{config-ssh-bug-rsa1} \q{Chokes on SSH1 RSA authentication} + +\cfg{winhelp-topic}{ssh.bugs.rsa1} + +Some SSH1 servers cannot deal with RSA authentication messages at +all. If Pageant is running and contains any SSH1 keys, PuTTY will +normally automatically try RSA authentication before falling back to +passwords, so these servers will crash when they see the RSA attempt. + +If this bug is detected, PuTTY will go straight to password +authentication. If this bug is enabled when talking to a correct +server, the session will succeed, but of course RSA authentication +will be impossible. + +This is an SSH1-specific bug. + +\S{config-ssh-bug-hmac2} \q{Miscomputes SSH2 HMAC keys} + +\cfg{winhelp-topic}{ssh.bugs.hmac2} + +Versions 2.3.0 and below of the SSH server software from +\cw{ssh.com} compute the keys for their HMAC message authentication +codes incorrectly. A typical symptom of this problem is that PuTTY +dies unexpectedly at the beginning of the session, saying +\q{Incorrect MAC received on packet}. + +If this bug is detected, PuTTY will compute its HMAC keys in the +same way as the buggy server, so that communication will still be +possible. If this bug is enabled when talking to a correct server, +communication will fail. + +This is an SSH2-specific bug. + +\S{config-ssh-bug-derivekey2} \q{Miscomputes SSH2 encryption keys} + +\cfg{winhelp-topic}{ssh.bugs.derivekey2} + +Versions below 2.1.0 of the SSH server software from \cw{ssh.com} +compute the keys for the session encryption incorrectly. This +problem can cause various error messages, such as \q{Incoming packet +was garbled on decryption}, or possibly even \q{Out of memory}. + +If this bug is detected, PuTTY will compute its encryption keys in +the same way as the buggy server, so that communication will still +be possible. If this bug is enabled when talking to a correct +server, communication will fail. + +This is an SSH2-specific bug. + +\S{config-ssh-bug-ssh} \q{Requires padding on SSH2 RSA signatures} + +\cfg{winhelp-topic}{ssh.bugs.rsapad2} + +Versions below 3.3 of OpenSSH require SSH2 RSA signatures to be +padded with zero bytes to the same length as the RSA key modulus. +The SSH2 draft specification says that an unpadded signature MUST be +accepted, so this is a bug. A typical symptom of this problem is +that PuTTY mysteriously fails RSA authentication once in every few +hundred attempts, and falls back to passwords. + +If this bug is detected, PuTTY will pad its signatures in the way +OpenSSH expects. If this bug is enabled when talking to a correct +server, it is likely that no damage will be done, since correct +servers usually still accept padded signatures because they're used +to talking to OpenSSH. + +This is an SSH2-specific bug. + \H{config-file} Storing configuration in a file PuTTY does not currently support storing its configuration in a file diff --git a/putty.h b/putty.h index 9994b859..e98bd7da 100644 --- a/putty.h +++ b/putty.h @@ -368,6 +368,11 @@ typedef struct { int lport_acceptall; /* accept conns from hosts other than localhost */ int rport_acceptall; /* same for remote forwarded ports (SSH2 only) */ char portfwd[1024]; /* [LR]localport\thost:port\000[LR]localport\thost:port\000\000 */ + /* SSH bug compatibility modes */ + enum { + BUG_AUTO, BUG_OFF, BUG_ON + } sshbug_ignore1, sshbug_plainpw1, sshbug_rsa1, + sshbug_hmac2, sshbug_derivekey2, sshbug_rsapad2; } Config; /* diff --git a/settings.c b/settings.c index febd9505..faed9e5a 100644 --- a/settings.c +++ b/settings.c @@ -189,7 +189,6 @@ void save_settings(char *section, int do_host, Config * cfg) write_setting_i(sesskey, "AuthTIS", cfg->try_tis_auth); write_setting_i(sesskey, "AuthKI", cfg->try_ki_auth); write_setting_i(sesskey, "SshProt", cfg->sshprot); - write_setting_i(sesskey, "BuggyMAC", cfg->buggymac); write_setting_i(sesskey, "SSH2DES", cfg->ssh2_des_cbc); write_setting_s(sesskey, "PublicKeyFile", cfg->keyfile); write_setting_s(sesskey, "RemoteCommand", cfg->remote_cmd); @@ -304,7 +303,12 @@ void save_settings(char *section, int do_host, Config * cfg) *p = '\0'; write_setting_s(sesskey, "PortForwardings", buf); } - + write_setting_i(sesskey, "BugIgnore1", cfg->sshbug_ignore1); + write_setting_i(sesskey, "BugPlainPW1", cfg->sshbug_plainpw1); + write_setting_i(sesskey, "BugRSA1", cfg->sshbug_rsa1); + write_setting_i(sesskey, "BugHMAC2", cfg->sshbug_hmac2); + write_setting_i(sesskey, "BugDeriveKey2", cfg->sshbug_derivekey2); + write_setting_i(sesskey, "BugRSAPad2", cfg->sshbug_rsapad2); close_settings_w(sesskey); } @@ -400,7 +404,6 @@ void load_settings(char *section, int do_host, Config * cfg) gprefs(sesskey, "Cipher", "\0", ciphernames, CIPHER_MAX, cfg->ssh_cipherlist); gppi(sesskey, "SshProt", 1, &cfg->sshprot); - gppi(sesskey, "BuggyMAC", 0, &cfg->buggymac); gppi(sesskey, "SSH2DES", 0, &cfg->ssh2_des_cbc); gppi(sesskey, "AuthTIS", 0, &cfg->try_tis_auth); gppi(sesskey, "AuthKI", 1, &cfg->try_ki_auth); @@ -566,6 +569,20 @@ void load_settings(char *section, int do_host, Config * cfg) } *q = '\0'; } + gppi(sesskey, "BugIgnore1", BUG_AUTO, &cfg->sshbug_ignore1); + gppi(sesskey, "BugPlainPW1", BUG_AUTO, &cfg->sshbug_plainpw1); + gppi(sesskey, "BugRSA1", BUG_AUTO, &cfg->sshbug_rsa1); + { + int i; + gppi(sesskey, "BugHMAC2", BUG_AUTO, &cfg->sshbug_hmac2); + if (cfg->sshbug_hmac2 == BUG_AUTO) { + gppi(sesskey, "BuggyMAC", 0, &i); + if (i == 1) + cfg->sshbug_hmac2 = BUG_ON; + } + } + gppi(sesskey, "BugDeriveKey2", BUG_AUTO, &cfg->sshbug_derivekey2); + gppi(sesskey, "BugRSAPad2", BUG_AUTO, &cfg->sshbug_rsapad2); close_settings_r(sesskey); } diff --git a/ssh.c b/ssh.c index d998d08f..58b6b427 100644 --- a/ssh.c +++ b/ssh.c @@ -1660,9 +1660,11 @@ static void ssh_detect_bugs(char *vstring) ssh_remote_bugs = 0; - if (!strcmp(imp, "1.2.18") || !strcmp(imp, "1.2.19") || - !strcmp(imp, "1.2.20") || !strcmp(imp, "1.2.21") || - !strcmp(imp, "1.2.22") || !strcmp(imp, "Cisco-1.25")) { + if (cfg.sshbug_ignore1 == BUG_ON || + (cfg.sshbug_ignore1 == BUG_AUTO && + (!strcmp(imp, "1.2.18") || !strcmp(imp, "1.2.19") || + !strcmp(imp, "1.2.20") || !strcmp(imp, "1.2.21") || + !strcmp(imp, "1.2.22") || !strcmp(imp, "Cisco-1.25")))) { /* * These versions don't support SSH1_MSG_IGNORE, so we have * to use a different defence against password length @@ -1672,7 +1674,9 @@ static void ssh_detect_bugs(char *vstring) logevent("We believe remote version has SSH1 ignore bug"); } - if (!strcmp(imp, "Cisco-1.25")) { + if (cfg.sshbug_plainpw1 == BUG_ON || + (cfg.sshbug_plainpw1 == BUG_AUTO && + (!strcmp(imp, "Cisco-1.25")))) { /* * These versions need a plain password sent; they can't * handle having a null and a random length of data after @@ -1682,7 +1686,9 @@ static void ssh_detect_bugs(char *vstring) logevent("We believe remote version needs a plain SSH1 password"); } - if (!strcmp(imp, "Cisco-1.25")) { + if (cfg.sshbug_rsa1 == BUG_ON || + (cfg.sshbug_rsa1 == BUG_AUTO && + (!strcmp(imp, "Cisco-1.25")))) { /* * These versions apparently have no clue whatever about * RSA authentication and will panic and die if they see @@ -1692,9 +1698,11 @@ static void ssh_detect_bugs(char *vstring) logevent("We believe remote version can't handle RSA authentication"); } - if (!strncmp(imp, "2.1.0", 5) || !strncmp(imp, "2.0.", 4) || - !strncmp(imp, "2.2.0", 5) || !strncmp(imp, "2.3.0", 5) || - !strncmp(imp, "2.1 ", 4)) { + if (cfg.sshbug_hmac2 == BUG_ON || + (cfg.sshbug_hmac2 == BUG_AUTO && + (!strncmp(imp, "2.1.0", 5) || !strncmp(imp, "2.0.", 4) || + !strncmp(imp, "2.2.0", 5) || !strncmp(imp, "2.3.0", 5) || + !strncmp(imp, "2.1 ", 4)))) { /* * These versions have the HMAC bug. */ @@ -1702,7 +1710,9 @@ static void ssh_detect_bugs(char *vstring) logevent("We believe remote version has SSH2 HMAC bug"); } - if (!strncmp(imp, "2.0.", 4)) { + if (cfg.sshbug_derivekey2 == BUG_ON || + (cfg.sshbug_derivekey2 == BUG_AUTO && + (!strncmp(imp, "2.0.", 4)))) { /* * These versions have the key-derivation bug (failing to * include the literal shared secret in the hashes that @@ -1712,8 +1722,10 @@ static void ssh_detect_bugs(char *vstring) logevent("We believe remote version has SSH2 key-derivation bug"); } - if ((!strncmp(imp, "OpenSSH_2.", 10) && imp[10]>='5' && imp[10]<='9') || - (!strncmp(imp, "OpenSSH_3.", 10) && imp[10]>='0' && imp[10]<='2')) { + if (cfg.sshbug_rsapad2 == BUG_ON || + (cfg.sshbug_rsapad2 == BUG_AUTO && + ((!strncmp(imp, "OpenSSH_2.", 10) && imp[10]>='5' && imp[10]<='9') || + (!strncmp(imp, "OpenSSH_3.", 10) && imp[10]>='0' && imp[10]<='2')))){ /* * These versions have the SSH2 RSA padding bug. */ @@ -5787,7 +5799,8 @@ static void ssh_special(Telnet_Special code) if (ssh_state == SSH_STATE_CLOSED || ssh_state == SSH_STATE_PREPACKET) return; if (ssh_version == 1) { - send_packet(SSH1_MSG_IGNORE, PKT_STR, "", PKT_END); + if (!(ssh_remote_bugs & BUG_CHOKES_ON_SSH1_IGNORE)) + send_packet(SSH1_MSG_IGNORE, PKT_STR, "", PKT_END); } else { ssh2_pkt_init(SSH2_MSG_IGNORE); ssh2_pkt_addstring_start(); diff --git a/winctrls.c b/winctrls.c index df0edce7..f44a0be5 100644 --- a/winctrls.c +++ b/winctrls.c @@ -448,6 +448,40 @@ void staticpassedit(struct ctlpos *cp, char *stext, } /* + * A drop-down list box on the right hand side, with a static to + * its left. + */ +void staticddl(struct ctlpos *cp, char *stext, + int sid, int lid, int percentlist) +{ + const int height = (COMBOHEIGHT > STATICHEIGHT ? + COMBOHEIGHT : STATICHEIGHT); + RECT r; + int lwid, rwid, rpos; + + rpos = + GAPBETWEEN + (100 - percentlist) * (cp->width + GAPBETWEEN) / 100; + lwid = rpos - 2 * GAPBETWEEN; + rwid = cp->width + GAPBETWEEN - rpos; + + r.left = GAPBETWEEN; + r.top = cp->ypos + (height - STATICHEIGHT) / 2; + r.right = lwid; + r.bottom = STATICHEIGHT; + doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid); + + r.left = rpos; + r.top = cp->ypos + (height - EDITHEIGHT) / 2; + r.right = rwid; + r.bottom = COMBOHEIGHT*4; + doctl(cp, r, "COMBOBOX", + WS_CHILD | WS_VISIBLE | WS_TABSTOP | + CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_CLIENTEDGE, "", lid); + + cp->ypos += height + GAPBETWEEN; +} + +/* * A big multiline edit control with a static labelling it. */ void bigeditctrl(struct ctlpos *cp, char *stext, diff --git a/windlg.c b/windlg.c index 474a0547..76d4804f 100644 --- a/windlg.c +++ b/windlg.c @@ -509,7 +509,6 @@ enum { IDCX_ABOUT = IDC_CIPHERLIST, IDC_CIPHERUP, IDC_CIPHERDN, - IDC_BUGGYMAC, IDC_SSH2DES, IDC_SSHPROTSTATIC, IDC_SSHPROT1ONLY, @@ -534,6 +533,23 @@ enum { IDCX_ABOUT = IDC_AUTHKI, sshauthpanelend, + sshbugspanelstart, + IDC_TITLE_SSHBUGS, + IDC_BOX_SSHBUGS1, + IDC_BUGS_IGNORE1, + IDC_BUGD_IGNORE1, + IDC_BUGS_PLAINPW1, + IDC_BUGD_PLAINPW1, + IDC_BUGS_RSA1, + IDC_BUGD_RSA1, + IDC_BUGS_HMAC2, + IDC_BUGD_HMAC2, + IDC_BUGS_DERIVEKEY2, + IDC_BUGD_DERIVEKEY2, + IDC_BUGS_RSAPAD2, + IDC_BUGD_RSAPAD2, + sshbugspanelend, + selectionpanelstart, IDC_TITLE_SELECTION, IDC_BOX_SELECTION1, @@ -889,8 +905,6 @@ char *help_context_cmd(int id) case IDC_CIPHERDN: case IDC_SSH2DES: return "JI(`',`ssh.ciphers')"; - case IDC_BUGGYMAC: - return "JI(`',`ssh.buggymac')"; case IDC_SSHPROTSTATIC: case IDC_SSHPROT1ONLY: case IDC_SSHPROT1: @@ -985,6 +999,25 @@ char *help_context_cmd(int id) case IDC_RPORT_ALL: return "JI(`',`ssh.tunnels.portfwd.localhost')"; + case IDC_BUGS_IGNORE1: + case IDC_BUGD_IGNORE1: + return "JI(`',`ssh.bugs.ignore1')"; + case IDC_BUGS_PLAINPW1: + case IDC_BUGD_PLAINPW1: + return "JI(`',`ssh.bugs.plainpw1')"; + case IDC_BUGS_RSA1: + case IDC_BUGD_RSA1: + return "JI(`',`ssh.bugs.rsa1')"; + case IDC_BUGS_HMAC2: + case IDC_BUGD_HMAC2: + return "JI(`',`ssh.bugs.hmac2')"; + case IDC_BUGS_DERIVEKEY2: + case IDC_BUGD_DERIVEKEY2: + return "JI(`',`ssh.bugs.derivekey2')"; + case IDC_BUGS_RSAPAD2: + case IDC_BUGD_RSAPAD2: + return "JI(`',`ssh.bugs.rsapad2')"; + default: return NULL; } @@ -1149,7 +1182,6 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess) SetDlgItemText(hwnd, IDC_LOGEDIT, cfg.username); CheckDlgButton(hwnd, IDC_NOPTY, cfg.nopty); CheckDlgButton(hwnd, IDC_COMPRESS, cfg.compression); - CheckDlgButton(hwnd, IDC_BUGGYMAC, cfg.buggymac); CheckDlgButton(hwnd, IDC_SSH2DES, cfg.ssh2_des_cbc); CheckDlgButton(hwnd, IDC_AGENTFWD, cfg.agentfwd); CheckDlgButton(hwnd, IDC_CHANGEUSER, cfg.change_username); @@ -1288,6 +1320,50 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess) SetDlgItemText(hwnd, IDC_PROXYPASSEDIT, cfg.proxy_password); CheckRadioButton(hwnd, IDC_PROXYSOCKSVER5, IDC_PROXYSOCKSVER4, cfg.proxy_socks_version == 4 ? IDC_PROXYSOCKSVER4 : IDC_PROXYSOCKSVER5); + + /* SSH bugs config */ + SendDlgItemMessage(hwnd, IDC_BUGD_IGNORE1, CB_RESETCONTENT, 0, 0); + SendDlgItemMessage(hwnd, IDC_BUGD_IGNORE1, CB_ADDSTRING, 0, (LPARAM)"Auto"); + SendDlgItemMessage(hwnd, IDC_BUGD_IGNORE1, CB_ADDSTRING, 0, (LPARAM)"Off"); + SendDlgItemMessage(hwnd, IDC_BUGD_IGNORE1, CB_ADDSTRING, 0, (LPARAM)"On"); + SendDlgItemMessage(hwnd, IDC_BUGD_IGNORE1, CB_SETCURSEL, + cfg.sshbug_ignore1 == BUG_ON ? 2 : + cfg.sshbug_ignore1 == BUG_OFF ? 1 : 0, 0); + SendDlgItemMessage(hwnd, IDC_BUGD_PLAINPW1, CB_RESETCONTENT, 0, 0); + SendDlgItemMessage(hwnd, IDC_BUGD_PLAINPW1, CB_ADDSTRING, 0, (LPARAM)"Auto"); + SendDlgItemMessage(hwnd, IDC_BUGD_PLAINPW1, CB_ADDSTRING, 0, (LPARAM)"Off"); + SendDlgItemMessage(hwnd, IDC_BUGD_PLAINPW1, CB_ADDSTRING, 0, (LPARAM)"On"); + SendDlgItemMessage(hwnd, IDC_BUGD_PLAINPW1, CB_SETCURSEL, + cfg.sshbug_plainpw1 == BUG_ON ? 2 : + cfg.sshbug_plainpw1 == BUG_OFF ? 1 : 0, 0); + SendDlgItemMessage(hwnd, IDC_BUGD_RSA1, CB_RESETCONTENT, 0, 0); + SendDlgItemMessage(hwnd, IDC_BUGD_RSA1, CB_ADDSTRING, 0, (LPARAM)"Auto"); + SendDlgItemMessage(hwnd, IDC_BUGD_RSA1, CB_ADDSTRING, 0, (LPARAM)"Off"); + SendDlgItemMessage(hwnd, IDC_BUGD_RSA1, CB_ADDSTRING, 0, (LPARAM)"On"); + SendDlgItemMessage(hwnd, IDC_BUGD_RSA1, CB_SETCURSEL, + cfg.sshbug_rsa1 == BUG_ON ? 2 : + cfg.sshbug_rsa1 == BUG_OFF ? 1 : 0, 0); + SendDlgItemMessage(hwnd, IDC_BUGD_HMAC2, CB_RESETCONTENT, 0, 0); + SendDlgItemMessage(hwnd, IDC_BUGD_HMAC2, CB_ADDSTRING, 0, (LPARAM)"Auto"); + SendDlgItemMessage(hwnd, IDC_BUGD_HMAC2, CB_ADDSTRING, 0, (LPARAM)"Off"); + SendDlgItemMessage(hwnd, IDC_BUGD_HMAC2, CB_ADDSTRING, 0, (LPARAM)"On"); + SendDlgItemMessage(hwnd, IDC_BUGD_HMAC2, CB_SETCURSEL, + cfg.sshbug_hmac2 == BUG_ON ? 2 : + cfg.sshbug_hmac2 == BUG_OFF ? 1 : 0, 0); + SendDlgItemMessage(hwnd, IDC_BUGD_DERIVEKEY2, CB_RESETCONTENT, 0, 0); + SendDlgItemMessage(hwnd, IDC_BUGD_DERIVEKEY2, CB_ADDSTRING, 0, (LPARAM)"Auto"); + SendDlgItemMessage(hwnd, IDC_BUGD_DERIVEKEY2, CB_ADDSTRING, 0, (LPARAM)"Off"); + SendDlgItemMessage(hwnd, IDC_BUGD_DERIVEKEY2, CB_ADDSTRING, 0, (LPARAM)"On"); + SendDlgItemMessage(hwnd, IDC_BUGD_DERIVEKEY2, CB_SETCURSEL, + cfg.sshbug_derivekey2 == BUG_ON ? 2 : + cfg.sshbug_derivekey2 == BUG_OFF ? 1 : 0, 0); + SendDlgItemMessage(hwnd, IDC_BUGD_RSAPAD2, CB_RESETCONTENT, 0, 0); + SendDlgItemMessage(hwnd, IDC_BUGD_RSAPAD2, CB_ADDSTRING, 0, (LPARAM)"Auto"); + SendDlgItemMessage(hwnd, IDC_BUGD_RSAPAD2, CB_ADDSTRING, 0, (LPARAM)"Off"); + SendDlgItemMessage(hwnd, IDC_BUGD_RSAPAD2, CB_ADDSTRING, 0, (LPARAM)"On"); + SendDlgItemMessage(hwnd, IDC_BUGD_RSAPAD2, CB_SETCURSEL, + cfg.sshbug_rsapad2 == BUG_ON ? 2 : + cfg.sshbug_rsapad2 == BUG_OFF ? 1 : 0, 0); } struct treeview_faff { @@ -1833,8 +1909,6 @@ static void create_controls(HWND hwnd, int dlgtype, int panel) "1 on&ly", IDC_SSHPROT1ONLY, "&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, "2 o&nly", IDC_SSHPROT2ONLY, NULL); - checkbox(&cp, "&Imitate SSH 2 MAC bug in commercial <= v2.3.x", - IDC_BUGGYMAC); endbox(&cp); beginbox(&cp, "Encryption options", IDC_BOX_SSH3); prefslist(&cipherlist, &cp, "Encryption cipher &selection policy:", @@ -1872,6 +1946,31 @@ static void create_controls(HWND hwnd, int dlgtype, int panel) } } + if (panel == sshbugspanelstart) { + /* The SSH bugs panel. Accelerators used: [acgoh] isrmep */ + struct ctlpos cp; + ctlposinit(&cp, hwnd, 80, 3, 13); + if (dlgtype == 0) { + bartitle(&cp, "Workarounds for SSH server bugs", + IDC_TITLE_SSHBUGS); + beginbox(&cp, "Detection of known bugs in SSH servers", + IDC_BOX_SSHBUGS1); + staticddl(&cp, "Chokes on SSH1 &ignore messages", + IDC_BUGS_IGNORE1, IDC_BUGD_IGNORE1, 20); + staticddl(&cp, "Refuses all SSH1 pa&ssword camouflage", + IDC_BUGS_PLAINPW1, IDC_BUGD_PLAINPW1, 20); + staticddl(&cp, "Chokes on SSH1 &RSA authentication", + IDC_BUGS_RSA1, IDC_BUGD_RSA1, 20); + staticddl(&cp, "Miscomputes SSH2 H&MAC keys", + IDC_BUGS_HMAC2, IDC_BUGD_HMAC2, 20); + staticddl(&cp, "Miscomputes SSH2 &encryption keys", + IDC_BUGS_DERIVEKEY2, IDC_BUGD_DERIVEKEY2, 20); + staticddl(&cp, "Requires &padding on SSH2 RSA signatures", + IDC_BUGS_RSAPAD2, IDC_BUGD_RSAPAD2, 20); + endbox(&cp); + } + } + if (panel == tunnelspanelstart) { /* The Tunnels panel. Accelerators used: [acgoh] deilmrstxp */ struct ctlpos cp; @@ -2048,6 +2147,7 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg, /* XXX make it closed by default? */ treeview_insert(&tvfaff, 2, "Auth"); treeview_insert(&tvfaff, 2, "Tunnels"); + treeview_insert(&tvfaff, 2, "Bugs"); } } @@ -2133,6 +2233,8 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg, create_controls(hwnd, dlgtype, sshpanelstart); if (!strcmp(buffer, "Auth")) create_controls(hwnd, dlgtype, sshauthpanelstart); + if (!strcmp(buffer, "Bugs")) + create_controls(hwnd, dlgtype, sshbugspanelstart); if (!strcmp(buffer, "Selection")) create_controls(hwnd, dlgtype, selectionpanelstart); if (!strcmp(buffer, "Colours")) @@ -3063,12 +3165,6 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg, cfg.compression = IsDlgButtonChecked(hwnd, IDC_COMPRESS); break; - case IDC_BUGGYMAC: - if (HIWORD(wParam) == BN_CLICKED || - HIWORD(wParam) == BN_DOUBLECLICKED) - cfg.buggymac = - IsDlgButtonChecked(hwnd, IDC_BUGGYMAC); - break; case IDC_SSH2DES: if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == BN_DOUBLECLICKED) @@ -3441,6 +3537,54 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg, disaster2:; } break; + case IDC_BUGD_IGNORE1: + if (HIWORD(wParam) == CBN_SELCHANGE) { + int index = SendDlgItemMessage(hwnd, IDC_BUGD_IGNORE1, + CB_GETCURSEL, 0, 0); + cfg.sshbug_ignore1 = (index == 0 ? BUG_AUTO : + index == 1 ? BUG_OFF : BUG_ON); + } + break; + case IDC_BUGD_PLAINPW1: + if (HIWORD(wParam) == CBN_SELCHANGE) { + int index = SendDlgItemMessage(hwnd, IDC_BUGD_PLAINPW1, + CB_GETCURSEL, 0, 0); + cfg.sshbug_plainpw1 = (index == 0 ? BUG_AUTO : + index == 1 ? BUG_OFF : BUG_ON); + } + break; + case IDC_BUGD_RSA1: + if (HIWORD(wParam) == CBN_SELCHANGE) { + int index = SendDlgItemMessage(hwnd, IDC_BUGD_RSA1, + CB_GETCURSEL, 0, 0); + cfg.sshbug_rsa1 = (index == 0 ? BUG_AUTO : + index == 1 ? BUG_OFF : BUG_ON); + } + break; + case IDC_BUGD_HMAC2: + if (HIWORD(wParam) == CBN_SELCHANGE) { + int index = SendDlgItemMessage(hwnd, IDC_BUGD_HMAC2, + CB_GETCURSEL, 0, 0); + cfg.sshbug_hmac2 = (index == 0 ? BUG_AUTO : + index == 1 ? BUG_OFF : BUG_ON); + } + break; + case IDC_BUGD_DERIVEKEY2: + if (HIWORD(wParam) == CBN_SELCHANGE) { + int index = SendDlgItemMessage(hwnd, IDC_BUGD_DERIVEKEY2, + CB_GETCURSEL, 0, 0); + cfg.sshbug_derivekey2 = (index == 0 ? BUG_AUTO : + index == 1 ? BUG_OFF : BUG_ON); + } + break; + case IDC_BUGD_RSAPAD2: + if (HIWORD(wParam) == CBN_SELCHANGE) { + int index = SendDlgItemMessage(hwnd, IDC_BUGD_RSAPAD2, + CB_GETCURSEL, 0, 0); + cfg.sshbug_rsapad2 = (index == 0 ? BUG_AUTO : + index == 1 ? BUG_OFF : BUG_ON); + } + break; } return 0; case WM_HELP: diff --git a/winstuff.h b/winstuff.h index a2e48218..6f080b3b 100644 --- a/winstuff.h +++ b/winstuff.h @@ -64,6 +64,8 @@ void static2btn(struct ctlpos *cp, char *stext, int sid, char *btext1, int bid1, char *btext2, int bid2); void staticedit(struct ctlpos *cp, char *stext, int sid, int eid, int percentedit); +void staticddl(struct ctlpos *cp, char *stext, + int sid, int lid, int percentlist); void combobox(struct ctlpos *cp, char *text, int staticid, int listid); void staticpassedit(struct ctlpos *cp, char *stext, int sid, int eid, int percentedit); -- 2.11.0