--- src/consoles.h +++ src/consoles.h 2011-07-27 11:10:26.620613503 +0000 @@ -39,6 +39,7 @@ struct console { int fd, id; #define CON_SERIAL 0x0001 #define CON_NOTTY 0x0002 +#define CON_EIGHTBIT 0x1000 pid_t pid; struct chardata cp; struct termios tio; --- src/sulogin.c +++ src/sulogin.c 2011-07-27 13:10:16.791925602 +0000 @@ -635,6 +635,7 @@ char *getpasswd(struct console *con) ptr = &pass[0]; cp->eol = *ptr = '\0'; + con->flags &= ~CON_EIGHTBIT; eightbit = ((con->flags & CON_SERIAL) == 0 || (tty.c_cflag & (PARODD|PARENB)) == 0); while (cp->eol == '\0') { if (read(fd, &c, 1) < 1) { @@ -697,6 +698,8 @@ char *getpasswd(struct console *con) goto quit; } *ptr++ = ascval; + if (((unsigned char)ascval) & 0x80) + con->flags |= CON_EIGHTBIT; break; } } @@ -839,6 +842,30 @@ void usage(void) fprintf(stderr, "Usage: sulogin [-e] [-p] [-t timeout] [tty device]\n\r"); } +/* + * Wrapper for blowfish signedness bug (CVE-2011-2483) + */ + +static +int checkpw(const char *answer, const char *passwd, const struct console *con) +{ + char buf[64]; + + if (strcmp(crypt(answer, passwd), passwd) == 0) + return 1; + if (strncmp(passwd, "$2a$", 4) != 0) + return 0; + if ((con->flags & CON_EIGHTBIT) == 0) + return 0; + if (strlen(passwd) >= 64) + return 0; + + strncpy(buf, passwd, 64); + buf[2] = 'x'; + + return (strcmp(crypt(answer, buf), buf) == 0); +} + int main(int argc, char **argv) { char *tty = NULL; @@ -967,8 +994,7 @@ int main(int argc, char **argv) if ((answer = getpasswd(con)) == NULL) break; - if (passwd[0] == '\0' || - strcmp(crypt(answer, passwd), passwd) == 0) { + if (passwd[0] == '\0' || checkpw(answer, passwd, con)) { *usemask |= (1<id); sushell(pwd); *usemask &= ~(1<id);