Starting with glibc 2.17 (eglibc 2.17), crypt() fails with EINVAL (w/ NULL return) if the salt violates specifications. Additionally, on FIPS-140 enabled Linux systems, DES/MD5-encrypted passwords passed to crypt() fail with EPERM (w/ NULL return). If using glibc's crypt(), check return value to avoid a possible NULL pointer dereference. Author: mancha ==== --- yp-tools-2.14/src/yppasswd.c.orig 2010-04-21 +++ yp-tools-2.14/src/yppasswd.c 2013-05-22 @@ -423,6 +423,7 @@ static int /* return values: 0 = not ok, verifypassword (struct passwd *pwd, char *pwdstr, uid_t uid) { char *p, *q; + char *crypted_pass; int ucase, lcase, other, r; int passwdlen; @@ -448,12 +449,19 @@ verifypassword (struct passwd *pwd, char } passwdlen = get_passwd_len (pwd->pw_passwd); - if (pwd->pw_passwd[0] - && !strncmp (pwd->pw_passwd, crypt (pwdstr, pwd->pw_passwd), passwdlen) - && uid) + if (pwd->pw_passwd[0] && uid) { - fputs (_("You cannot reuse the old password.\n"), stderr); - return 0; + crypted_pass = crypt (pwdstr, pwd->pw_passwd); + if (crypted_pass == NULL) + { + fputs (_("crypt() call failed.\n"), stderr); + return 0; + } + if (!strncmp (pwd->pw_passwd, crypted_pass, passwdlen)) + { + fputs (_("You cannot reuse the old password.\n"), stderr); + return 0; + } } r = 0; @@ -517,6 +525,7 @@ int main (int argc, char **argv) { char *s, *progname, *domainname = NULL, *user = NULL, *master = NULL; + char *crypted_pass; int f_flag = 0, l_flag = 0, p_flag = 0, error, status; int hash_id = DES; char rounds[11] = "\0"; /* max length is '999999999$' */ @@ -738,7 +747,13 @@ main (int argc, char **argv) char *sane_passwd = alloca (passwdlen + 1); strncpy (sane_passwd, pwd->pw_passwd, passwdlen); sane_passwd[passwdlen] = 0; - if (strcmp (crypt (s, sane_passwd), sane_passwd)) + crypted_pass = crypt (s, sane_passwd); + if (crypted_pass == NULL) + { + fprintf (stderr, _("crypt() call failed.\n")); + return 1; + } + if (strcmp (crypted_pass, sane_passwd)) { fprintf (stderr, _("Sorry.\n")); return 1; @@ -833,7 +848,14 @@ main (int argc, char **argv) break; } - yppwd.newpw.pw_passwd = strdup (crypt (buf, salt)); + crypted_pass = crypt (buf, salt); + if (crypted_pass == NULL) + { + printf (_("crypt() call failed - password unchanged.\n")); + return 1; + } + + yppwd.newpw.pw_passwd = strdup (crypted_pass); } if (f_flag)