From 7591b9ff09c8700ce2f8c03ed33d3801668bae02 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 12 Oct 2000 12:39:44 +0000 Subject: [PATCH] Add a config option to emulate the HMAC bug in commercial SSH v2.3.x and earlier (namely, it uses only 16 bytes of key rather than 20). git-svn-id: svn://svn.tartarus.org/sgt/putty@706 cda61777-01e9-0310-a592-d414129be87e --- putty.h | 1 + settings.c | 2 ++ ssh.c | 36 +++++++++++++++++++++++------------- sshsha.c | 16 ++++++++++++++++ windlg.c | 9 +++++++++ 5 files changed, 51 insertions(+), 13 deletions(-) diff --git a/putty.h b/putty.h index 4f9151b9..af5b7555 100644 --- a/putty.h +++ b/putty.h @@ -147,6 +147,7 @@ typedef struct { enum { CIPHER_3DES, CIPHER_BLOWFISH, CIPHER_DES } cipher; char keyfile[FILENAME_MAX]; int sshprot; /* use v1 or v2 when both available */ + int buggymac; /* MAC bug commmercial <=v2.3.x SSH2 */ int try_tis_auth; /* Telnet options */ char termtype[32]; diff --git a/settings.c b/settings.c index 181708e3..66128a45 100644 --- a/settings.c +++ b/settings.c @@ -78,6 +78,7 @@ void save_settings (char *section, int do_host, Config *cfg) { cfg->cipher == CIPHER_DES ? "des" : "3des"); write_setting_i (sesskey, "AuthTIS", cfg->try_tis_auth); write_setting_i (sesskey, "SshProt", cfg->sshprot); + write_setting_i (sesskey, "BuggyMAC", cfg->buggymac); write_setting_s (sesskey, "PublicKeyFile", cfg->keyfile); write_setting_s (sesskey, "RemoteCommand", cfg->remote_cmd); write_setting_i (sesskey, "RFCEnviron", cfg->rfc_environ); @@ -198,6 +199,7 @@ void load_settings (char *section, int do_host, Config *cfg) { cfg->cipher = CIPHER_3DES; } gppi (sesskey, "SshProt", 1, &cfg->sshprot); + gppi (sesskey, "BuggyMAC", 0, &cfg->buggymac); gppi (sesskey, "AuthTIS", 0, &cfg->try_tis_auth); gpps (sesskey, "PublicKeyFile", "", cfg->keyfile, sizeof(cfg->keyfile)); gpps (sesskey, "RemoteCommand", "", cfg->remote_cmd, diff --git a/ssh.c b/ssh.c index 509ea3ab..7d1ce260 100644 --- a/ssh.c +++ b/ssh.c @@ -167,7 +167,7 @@ const static struct ssh_kex *kex_algs[] = { &ssh_diffiehellman }; extern const struct ssh_hostkey ssh_dss; const static struct ssh_hostkey *hostkey_algs[] = { &ssh_dss }; -extern const struct ssh_mac ssh_sha1; +extern const struct ssh_mac ssh_sha1, ssh_sha1_buggy; static void nullmac_key(unsigned char *key) { } static void nullmac_generate(unsigned char *blk, int len, unsigned long seq) { } @@ -176,6 +176,7 @@ const static struct ssh_mac ssh_mac_none = { nullmac_key, nullmac_key, nullmac_generate, nullmac_verify, "none", 0 }; const static struct ssh_mac *macs[] = { &ssh_sha1, &ssh_mac_none }; +const static struct ssh_mac *buggymacs[] = { &ssh_sha1_buggy, &ssh_mac_none }; const static struct ssh_compress ssh_comp_none = { "none" @@ -1828,6 +1829,7 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt) static int i, len; static char *str; static Bignum e, f, K; + static const struct ssh_mac **maclist; static const struct ssh_cipher *cscipher_tobe = NULL; static const struct ssh_cipher *sccipher_tobe = NULL; static const struct ssh_mac *csmac_tobe = NULL; @@ -1858,6 +1860,14 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt) preferred_cipher = &ssh_3des_ssh2; } + /* + * Be prepared to work around the buggy MAC problem. + */ + if (cfg.buggymac) + maclist = buggymacs; + else + maclist = macs; + begin_key_exchange: /* * Construct and send our key exchange packet. @@ -1897,16 +1907,16 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt) } /* List client->server MAC algorithms. */ ssh2_pkt_addstring_start(); - for (i = 0; i < lenof(macs); i++) { - ssh2_pkt_addstring_str(macs[i]->name); - if (i < lenof(macs)-1) + for (i = 0; i < lenof(maclist); i++) { + ssh2_pkt_addstring_str(maclist[i]->name); + if (i < lenof(maclist)-1) ssh2_pkt_addstring_str(","); } /* List server->client MAC algorithms. */ ssh2_pkt_addstring_start(); - for (i = 0; i < lenof(macs); i++) { - ssh2_pkt_addstring_str(macs[i]->name); - if (i < lenof(macs)-1) + for (i = 0; i < lenof(maclist); i++) { + ssh2_pkt_addstring_str(maclist[i]->name); + if (i < lenof(maclist)-1) ssh2_pkt_addstring_str(","); } /* List client->server compression algorithms. */ @@ -1979,16 +1989,16 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt) } } ssh2_pkt_getstring(&str, &len); /* client->server mac */ - for (i = 0; i < lenof(macs); i++) { - if (in_commasep_string(macs[i]->name, str, len)) { - csmac_tobe = macs[i]; + for (i = 0; i < lenof(maclist); i++) { + if (in_commasep_string(maclist[i]->name, str, len)) { + csmac_tobe = maclist[i]; break; } } ssh2_pkt_getstring(&str, &len); /* server->client mac */ - for (i = 0; i < lenof(macs); i++) { - if (in_commasep_string(macs[i]->name, str, len)) { - scmac_tobe = macs[i]; + for (i = 0; i < lenof(maclist); i++) { + if (in_commasep_string(maclist[i]->name, str, len)) { + scmac_tobe = maclist[i]; break; } } diff --git a/sshsha.c b/sshsha.c index 95d5259e..48cabb5c 100644 --- a/sshsha.c +++ b/sshsha.c @@ -199,6 +199,14 @@ static void sha1_sckey(unsigned char *key) { sha1_key(&sha1_sc_mac_s1, &sha1_sc_mac_s2, key, 20); } +static void sha1_cskey_buggy(unsigned char *key) { + sha1_key(&sha1_cs_mac_s1, &sha1_cs_mac_s2, key, 16); +} + +static void sha1_sckey_buggy(unsigned char *key) { + sha1_key(&sha1_sc_mac_s1, &sha1_sc_mac_s2, key, 16); +} + static void sha1_do_hmac(SHA_State *s1, SHA_State *s2, unsigned char *blk, int len, unsigned long seq, unsigned char *hmac) { @@ -236,3 +244,11 @@ struct ssh_mac ssh_sha1 = { "hmac-sha1", 20 }; + +struct ssh_mac ssh_sha1_buggy = { + sha1_cskey_buggy, sha1_sckey_buggy, + sha1_generate, + sha1_verify, + "hmac-sha1", + 20 +}; diff --git a/windlg.c b/windlg.c index c9e130b7..e012b3d0 100644 --- a/windlg.c +++ b/windlg.c @@ -945,6 +945,7 @@ enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue, IDC_CIPHER3DES, IDC_CIPHERBLOWF, IDC_CIPHERDES, + IDC_BUGGYMAC, IDC_AUTHTIS, IDC_PKSTATIC, IDC_PKEDIT, @@ -1109,6 +1110,7 @@ static void init_dlg_ctrls(HWND hwnd) { SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype); SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username); CheckDlgButton (hwnd, IDC_NOPTY, cfg.nopty); + CheckDlgButton (hwnd, IDC_BUGGYMAC, cfg.buggymac); CheckDlgButton (hwnd, IDC_AGENTFWD, cfg.agentfwd); CheckRadioButton (hwnd, IDC_CIPHER3DES, IDC_CIPHERDES, cfg.cipher == CIPHER_BLOWFISH ? IDC_CIPHERBLOWF : @@ -1575,6 +1577,8 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg, "&3DES", IDC_CIPHER3DES, "&Blowfish", IDC_CIPHERBLOWF, "&DES", IDC_CIPHERDES, NULL); + checkbox(&cp, "Imitate SSH 2 MAC bug in commercial <= v2.3.x", + IDC_BUGGYMAC); endbox(&cp); treeview_insert(&tvfaff, 1, "SSH"); @@ -2059,6 +2063,11 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg, HIWORD(wParam) == BN_DOUBLECLICKED) cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY); break; + case IDC_BUGGYMAC: + if (HIWORD(wParam) == BN_CLICKED || + HIWORD(wParam) == BN_DOUBLECLICKED) + cfg.buggymac = IsDlgButtonChecked (hwnd, IDC_BUGGYMAC); + break; case IDC_AGENTFWD: if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == BN_DOUBLECLICKED) -- 2.11.0