diff -pruN a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c --- a/modules/pam_userdb/pam_userdb.c 2011-06-21 16:04:56.000000000 +0700 +++ b/modules/pam_userdb/pam_userdb.c 2014-08-28 17:41:35.243954732 +0700 @@ -214,24 +214,23 @@ user_lookup (pam_handle_t *pamh, const c /* crypt(3) password storage */ char *cryptpw; - char salt[2]; - if (data.dsize != 13) { + if (data.dsize < 13) { compare = -2; } else if (ctrl & PAM_ICASE_ARG) { compare = -2; } else { - salt[0] = *data.dptr; - salt[1] = *(data.dptr + 1); + cryptpw = crypt (pass, data.dptr); - cryptpw = crypt (pass, salt); - - if (cryptpw) { - compare = strncasecmp (data.dptr, cryptpw, data.dsize); + if (cryptpw && strlen(cryptpw) == (size_t)data.dsize) { + compare = memcmp(data.dptr, cryptpw, data.dsize); } else { compare = -2; if (ctrl & PAM_DEBUG_ARG) { - pam_syslog(pamh, LOG_INFO, "crypt() returned NULL"); + if (cryptpw) + pam_syslog(pamh, LOG_INFO, "lengths of computed and stored hashes differ"); + else + pam_syslog(pamh, LOG_INFO, "crypt() returned NULL"); } };