Hi Stefan, Thanks for r3esponding so quickly.
On 2013-12-04 11:56, Stefan Bühler wrote:
If the characters are not from this limited set, especially if the first character is '$', then the Glibc crypt() expects '$' + id + '$' + real-salt + '$'. Glibc shouldn't require NUL-termination as long as there is a 3rd '$'.
I was concerned that if the stored password is malformed, crypt() could scan arbitrarily far away beyond the end of the string. Granted, a malicious user shouldn't ever be able to cause the stored password to be malformed.
The Glibc API limits real-salt to 16 bytes, and id is so far at most 2 bytes long, so the NUL-terminated salt should fit into 22 bytes (making it 32 shouldn't hurt).
For what it's worth, I used the following patch before I came across your bug report. I guess the 256 is overkill considering your comments about the maximum salt size of 22.
If you or the maintainer feel that making a copy of the string is not worth it and would prefer to use your patch, I'm ok with that.
-kv
diff --git a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c index 37af682..04a17d6 100644 --- a/modules/pam_userdb/pam_userdb.c +++ b/modules/pam_userdb/pam_userdb.c @@ -214,15 +214,16 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, /* crypt(3) password storage */ char *cryptpw; - char salt[2]; + char salt[256]; + int salt_len; - if (data.dsize != 13) { - compare = -2; - } else if (ctrl & PAM_ICASE_ARG) { + if (ctrl & PAM_ICASE_ARG) { compare = -2; } else { - salt[0] = *data.dptr; - salt[1] = *(data.dptr + 1); + salt_len = sizeof(salt)-1; + if (data.dsize < salt_len) salt_len = data.dsize; + memcpy(salt, data.dptr, salt_len); + salt[salt_len] = 0; cryptpw = crypt (pass, salt);