1

I'm doing a PAM-type thing, and it needs to check a user's password in /etc/shadow.

Usually, this involves reading the password line for the encryption ID, the salt, and the password. Using the ID and salt, the user-provided password can be hashed using crypt(3) or m_crypt (on the same man page), and the result compared. This works fine on many systems, such as Ubuntu, but I'm having major problems on SUSE.

The system is using Blowfish, with the "correct handling of 8-bit chars". This has a hash ID of "2y". Unfortunately, whenever crypt(3) gets called on this, it segfaults. The same goes for ID "2a", which was the first code that identified Blowfish. All other hashing algorithms work.

The system must have a working crypt (or equivalent) that does Blowfish hashing, since the /etc/shadow file has examples of it, but I can't make this work. Can anyone point me in the right direction?

An example of the segfault:

#define _XOPEN_SOURCE
#include <unistd.h>
#include <stdio.h>

int main(int argc, char** argv) {
  char *pass = "tqbfjotld";
  char *salt = "$2y$10$";
  char *pp = NULL;
  pp = crypt(pass, salt);
  printf("%s\n", pp);
  return 0;
}

The salt $2a$10$ also shows the error.

It works on other systems, like Ubuntu, and other hashing algorithms work fine on SUSE.

Any ideas please?

PaulaG
  • 336
  • 1
  • 8
  • Never used myself, but `2a` is blowfish, what is `2y`? – Sourav Ghosh Jun 18 '15 at 17:08
  • the call to crypt is returning a value of NULL. It is the printf() that is causing the seg fault event because a string parameter is NULL. – user3629249 Jun 18 '15 at 17:36
  • per the documentation for crypt, the salt has to be a pointer to a 2 char string. When I used only a two char string for salt, it worked perfectly. Please read the man page for crypt – user3629249 Jun 18 '15 at 17:40
  • @user3629249: The manpage is misleading, further down you'll find "Glibc notes" where more complex values for "salt" are described. – lathspell Jun 19 '15 at 12:00
  • @SouravGhosh: See https://en.wikipedia.org/wiki/Crypt_%28C%29#Blowfish-based_scheme about "2y", it's a fairly recent addition. – lathspell Jun 19 '15 at 12:00
  • doh! I should have thought of the null. Too many years away from C. – PaulaG Jun 19 '15 at 16:45

2 Answers2

0

crypt() returning NULL means error, probably invalid salt as 2y is unknown. According to Wikipedia it seems to be a fairly recent addition: https://en.wikipedia.org/wiki/Crypt_%28C%29

"$2y$ - Post-2011 bug discovery, $2y$ may be used to unambiguously use the new, corrected algorithm. On an implementation suffering from the bug, $2y$ simply won't work. On a newer, fixed implementation, it will produce the same result as using $2a$."

Try this to get the error:

#include <errno.h>
printf("%p (errno=%d: %s)\n", pp, errno, strerror(errno));

glibc-2.19 does not support any of the Blowfish algorithms, I get a NULL pointer on a recent Debian 8.1 as well.

Maybe your SUSE system contains password entries that were migrated over the time and are not even usable any more. Or some other piece of software like a custom PAM module evaluates and checks the password entries using a custom library and not by using the standard libc crypt() function.

lathspell
  • 3,040
  • 1
  • 30
  • 49
  • I presumed 2y it would work on this system, because it's creating new user accounts using $2y$ (so passwd is picking it up correctly from somewhere). – PaulaG Jun 19 '15 at 16:51
  • The error number is 22. Unfortunately, that does not coming with a string (strerror returns NULL). – PaulaG Jun 19 '15 at 16:52
  • I did not know it was possible to run /lib/libc.so.6, but now that I do I see under available extensions: "crypt add-on version 2.1 by Michael Glad and others". That confuses me a little, because there's no "crypt" function in libc (there's common_crypt, among others). When I link I need to use -lcrypt. That's separate from libc, isn't it? – PaulaG Jun 19 '15 at 16:56
  • @PaulG: Error 22 is "Invalid Argument" according to /usr/include/asm-generic/errno-base.h: #define EINVAL 22 /* Invalid argument */ libcrypt ist part of the libc6 project, e.g. the Debian packet listing for libc has it: $ dpkg -L libc6 | grep crypt /lib/i386-linux-gnu/libcrypt-2.19.so /lib/i386-linux-gnu/libcrypt.so.1 You might want to check "grep password /etc/pam.d/*" maybe you have a pam_bsd_special_crypt.so anywhere :-) – lathspell Jun 22 '15 at 12:05
  • Used my brain, and ran ldd over passwd. Turns out that it uses the crypt (Actually, crypt_r) that comes from libxcrypt.so. Unfortunately, I'm still struggling to figure out how to link to that :) – PaulaG Jun 23 '15 at 17:13
  • Interesting, I didn't know libxcrypt. It's README says you can just symlink it to libcrypt.so as it is binary compatible (but make a backup!). Else you'd have to recompile your software and add "-lxcrypt" instead of "-lcrypt". – lathspell Jun 24 '15 at 13:27
  • It turns out that I need libxcrypt.so.3, and that's not available anywhere yet except on SUSE (where it was developed). Dynamic loading helped here. – PaulaG Jun 30 '15 at 17:40
-2

Use $2y$10$xxx as salt, xxx means 22 characters after $2y$10$. If you want to know why 22, just see: https://en.wikipedia.org/wiki/Bcrypt.

Mathieu
  • 8,840
  • 7
  • 32
  • 45