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).

[originally from svn r706]
This commit is contained in:
Simon Tatham 2000-10-12 12:39:44 +00:00
Родитель 421aafb4c0
Коммит 3e83d75154
5 изменённых файлов: 51 добавлений и 13 удалений

Просмотреть файл

@ -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];

Просмотреть файл

@ -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,

36
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;
}
}

Просмотреть файл

@ -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
};

Просмотреть файл

@ -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)