1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-25 01:02:24 +00:00

Update to password length traffic analysis: one Cisco router can

apparently not deal with SSH1_MSG_IGNORE _or_ padded passwords, so
we must fall back to sending an undefended password.

[originally from svn r1332]
This commit is contained in:
Simon Tatham 2001-10-27 10:39:54 +00:00
parent 3dfaf08a0a
commit 6c9cdbe29f

84
ssh.c
View File

@ -159,6 +159,8 @@ static const char *const ssh2_disconnect_reasons[] = {
*/
#define BUG_CHOKES_ON_SSH1_IGNORE 1
#define BUG_SSH2_HMAC 2
#define BUG_NEEDS_SSH1_PLAIN_PASSWORD 4
#define GET_32BIT(cp) \
(((unsigned long)(unsigned char)(cp)[0] << 24) | \
@ -1418,17 +1420,15 @@ static void ssh_detect_bugs(char *vstring)
char *imp; /* pointer to implementation part */
imp = vstring;
imp += strcspn(imp, "-");
if (*imp)
imp++;
if (*imp) imp++;
imp += strcspn(imp, "-");
if (*imp)
imp++;
if (*imp) imp++;
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, "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
@ -1438,6 +1438,16 @@ static void ssh_detect_bugs(char *vstring)
logevent("We believe remote version has SSH1 ignore bug");
}
if (!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
* the password.
*/
ssh_remote_bugs |= BUG_NEEDS_SSH1_PLAIN_PASSWORD;
logevent("We believe remote version needs a plain SSH1 password");
}
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)) {
@ -1479,8 +1489,8 @@ static int do_ssh_init(unsigned char c)
crReturn(1); /* get another character */
}
vstring = smalloc(16);
vstrsize = 16;
vstring = smalloc(vstrsize);
strcpy(vstring, "SSH-");
vslen = 4;
i = 0;
@ -1506,10 +1516,10 @@ static int do_ssh_init(unsigned char c)
vstring[vslen] = 0;
vlog = smalloc(20 + vslen);
vstring[strcspn (vstring, "\r\n")] = '\0'; /* remove end-of-line chars */
sprintf(vlog, "Server version: %s", vstring);
ssh_detect_bugs(vstring);
vlog[strcspn(vlog, "\r\n")] = '\0';
logevent(vlog);
ssh_detect_bugs(vstring);
sfree(vlog);
/*
@ -2405,26 +2415,13 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
* use of the fact that the password is interpreted
* as a C string: so we can append a NUL, then some
* random data.
*
* One server (a Cisco one) can deal with neither
* SSH1_MSG_IGNORE _nor_ a padded password string.
* For this server we are left with no defences
* against password length sniffing.
*/
if (ssh_remote_bugs & BUG_CHOKES_ON_SSH1_IGNORE) {
char string[64];
char *s;
int len;
len = strlen(password);
if (len < sizeof(string)) {
s = string;
strcpy(string, password);
len++; /* cover the zero byte */
while (len < sizeof(string)) {
string[len++] = (char) random_byte();
}
} else {
s = password;
}
send_packet(pwpkt_type, PKT_INT, len,
PKT_DATA, s, len, PKT_END);
} else {
if (!(ssh_remote_bugs & BUG_CHOKES_ON_SSH1_IGNORE)) {
int bottom, top, pwlen, i;
char *randomstr;
@ -2456,7 +2453,40 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
PKT_STR, randomstr, PKT_END);
}
}
logevent("Sending password with camouflage packets");
ssh_pkt_defersend();
}
else if (!(ssh_remote_bugs & BUG_NEEDS_SSH1_PLAIN_PASSWORD)) {
char string[64];
char *s;
int len;
len = strlen(password);
if (len < sizeof(string)) {
s = string;
strcpy(string, password);
len++; /* cover the zero byte */
while (len < sizeof(string)) {
string[len++] = (char) random_byte();
}
} else {
s = password;
}
logevent("Sending length-padded password");
send_packet(pwpkt_type, PKT_INT, len,
PKT_DATA, s, len, PKT_END);
} else {
/*
* The server has _both_
* BUG_CHOKES_ON_SSH1_IGNORE and
* BUG_NEEDS_SSH1_PLAIN_PASSWORD. There is
* therefore nothing we can do.
*/
int len;
len = strlen(password);
logevent("Sending unpadded password");
send_packet(pwpkt_type, PKT_INT, len,
PKT_DATA, password, len, PKT_END);
}
} else {
send_packet(pwpkt_type, PKT_STR, password, PKT_END);