Patched pw_encrypt() to fix “crypt: Invalid argument” and immediate login
failure when a non-existent user tries to log in. This was caused by a
change in the behavior of glibc's crypt() function. When a user that does
not exist tries to log in, the code in shadow calls crypt() with an invalid
salt. The old version of crypt() used the provided bad salt (always “!”)
to produce a DES hash with “!!” at the beginning, while the new one just
returns NULL which isn't well-handled by the shadow code. To fix this
shadow bug, if the salt is invalid, we'll call crypt() using a good SHA512
salt, prepend “!!” to the hash that we get back, and have pw_encrypt()
return this as the result. The effect is identical to the previous
behavior – unless the exact same malformed hash happens to be the hash in
/etc/shadow (it won't be), the login will fail. While I see no way that
these 6 lines of code could be less secure than the original code, I
welcome additional review. Also, if anyone spots anything else that was
adversely affected by the change to crypt()'s behavior, please let me know.
Thanks to Michael L. Semon for informing me of the /bin/login problem.