From a616a72160c17fa193ad6ad95eb2c869633f4fe9 Mon Sep 17 00:00:00 2001 From: mancha Date: Fri, 4 Oct 2013 11:25:43 Subject: [PATCH] Improve handling of NULL returns from crypt(). Signed-off-by: mancha --- ChangeLog | 15 +++++++++++++++ lib/encrypt.c | 7 +++---- lib/pwauth.c | 7 ++++++- libmisc/valid.c | 1 + src/chgpasswd.c | 4 ++++ src/chpasswd.c | 4 ++++ src/gpasswd.c | 4 ++++ src/newgrp.c | 3 ++- src/newusers.c | 26 +++++++++++++++++++++----- src/passwd.c | 15 +++++++++++++++ 10 files changed, 75 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index aab00ae..1416a38 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2013-05-06 mancha + + * lib/encrypt.c: crypt() in glibc/eglibc 2.17 now fails if passed + a salt that violates specs. On Linux, crypt() also fails with + DES/MD5 salts in FIPS140 mode. Rather than exit() on NULL returns + we send them back to the caller for appropriate handling. + * lib/pwauth.c: Handle NULL return from crypt(). + * libmisc/valid.c: Likewise. + * src/chgpasswd.c: Likewise. + * src/chpasswd.c: Likewise. + * src/gpasswd.c: Likewise. + * src/newgrp.c: Likewise. + * src/newusers.c: Likewise. + * src/passwd.c: Likewise. + 2012-05-25 Nicolas François * NEWS: Set release date. diff --git a/lib/encrypt.c b/lib/encrypt.c index 7daa8da..49cb691 100644 --- a/lib/encrypt.c +++ b/lib/encrypt.c @@ -49,11 +49,10 @@ if (!cp) { /* * Single Unix Spec: crypt() may return a null pointer, - * and set errno to indicate an error. The caller doesn't - * expect us to return NULL, so... + * and set errno to indicate an error. In this case return + * the NULL so the caller can handle appropriately. */ - perror ("crypt"); - exit (EXIT_FAILURE); + return cp; } /* The GNU crypt does not return NULL if the algorithm is not diff --git a/lib/pwauth.c b/lib/pwauth.c index 4b26daa..086a72e 100644 --- a/lib/pwauth.c +++ b/lib/pwauth.c @@ -73,6 +73,7 @@ int pw_auth (const char *cipher, char prompt[1024]; char *clear = NULL; const char *cp; + const char *encrypted; int retval; #ifdef SKEY @@ -177,7 +178,11 @@ int pw_auth (const char *cipher, * the results there as well. */ - retval = strcmp (pw_encrypt (input, cipher), cipher); + encrypted = pw_encrypt (input, cipher); + if (encrypted!=NULL) + retval = strcmp (encrypted, cipher); + else + retval = -1; #ifdef SKEY /* diff --git a/libmisc/valid.c b/libmisc/valid.c index aa0390a..4b85d67 100644 --- a/libmisc/valid.c +++ b/libmisc/valid.c @@ -95,6 +95,7 @@ bool valid (const char *password, const struct passwd *ent) */ if ( (NULL != ent->pw_name) + && (NULL != encrypted) && (strcmp (encrypted, ent->pw_passwd) == 0)) { return true; } else { diff --git a/src/chgpasswd.c b/src/chgpasswd.c index 0f41d0b..6c42a09 100644 --- a/src/chgpasswd.c +++ b/src/chgpasswd.c @@ -469,6 +469,10 @@ int main (int argc, char **argv) #endif cp = pw_encrypt (newpwd, crypt_make_salt (crypt_method, arg)); + if (cp == NULL) { + perror ("crypt"); + exit (EXIT_FAILURE); + } } /* diff --git a/src/chpasswd.c b/src/chpasswd.c index 928e2d7..4968b0d 100644 --- a/src/chpasswd.c +++ b/src/chpasswd.c @@ -492,6 +492,10 @@ int main (int argc, char **argv) #endif cp = pw_encrypt (newpwd, crypt_make_salt(crypt_method, arg)); + if (cp == NULL) { + perror ("crypt"); + exit (EXIT_FAILURE); + } } /* diff --git a/src/gpasswd.c b/src/gpasswd.c index df8d714..0043610 100644 --- a/src/gpasswd.c +++ b/src/gpasswd.c @@ -939,6 +939,10 @@ static void change_passwd (struct group *gr) } cp = pw_encrypt (pass, crypt_make_salt (NULL, NULL)); + if (cp==NULL) { + perror ("crypt"); + exit (EXIT_FAILURE); + } memzero (pass, sizeof pass); #ifdef SHADOWGRP if (is_shadowgrp) { diff --git a/src/newgrp.c b/src/newgrp.c index 9330c72..6b87761 100644 --- a/src/newgrp.c +++ b/src/newgrp.c @@ -184,7 +184,8 @@ static void check_perms (const struct group *grp, cpasswd = pw_encrypt (cp, grp->gr_passwd); strzero (cp); - if (grp->gr_passwd[0] == '\0' || + if (cpasswd == NULL || + grp->gr_passwd[0] == '\0' || strcmp (cpasswd, grp->gr_passwd) != 0) { #ifdef WITH_AUDIT snprintf (audit_buf, sizeof(audit_buf), diff --git a/src/newusers.c b/src/newusers.c index 994898e..5f83a6a 100644 --- a/src/newusers.c +++ b/src/newusers.c @@ -387,6 +387,7 @@ static int add_user (const char *name, uid_t uid, gid_t gid) static void update_passwd (struct passwd *pwd, const char *password) { void *crypt_arg = NULL; + char *cp; if (crypt_method != NULL) { #ifdef USE_SHA_CRYPT if (sflg) { @@ -398,9 +399,13 @@ static void update_passwd (struct passwd *pwd, const char *password) if ((crypt_method != NULL) && (0 == strcmp(crypt_method, "NONE"))) { pwd->pw_passwd = (char *)password; } else { - pwd->pw_passwd = pw_encrypt (password, - crypt_make_salt (crypt_method, - crypt_arg)); + cp=pw_encrypt (password, crypt_make_salt (crypt_method, + crypt_arg)); + if (cp == NULL) { + perror ("crypt"); + exit (EXIT_FAILURE); + } + pwd->pw_passwd = cp; } } #endif /* !USE_PAM */ @@ -412,6 +417,7 @@ static int add_passwd (struct passwd *pwd, const char *password) { const struct spwd *sp; struct spwd spent; + char *cp; #ifndef USE_PAM void *crypt_arg = NULL; @@ -448,7 +454,12 @@ static int add_passwd (struct passwd *pwd, const char *password) } else { const char *salt = crypt_make_salt (crypt_method, crypt_arg); - spent.sp_pwdp = pw_encrypt (password, salt); + cp = pw_encrypt (password, salt); + if (cp == NULL) { + perror ("crypt"); + exit (EXIT_FAILURE); + } + spent.sp_pwdp = cp; } spent.sp_lstchg = (long) time ((time_t *) 0) / SCALE; if (0 == spent.sp_lstchg) { @@ -492,7 +503,12 @@ static int add_passwd (struct passwd *pwd, const char *password) spent.sp_pwdp = (char *)password; } else { const char *salt = crypt_make_salt (crypt_method, crypt_arg); - spent.sp_pwdp = pw_encrypt (password, salt); + cp = pw_encrypt (password, salt); + if (cp == NULL) { + perror ("crypt"); + exit (EXIT_FAILURE); + } + spent.sp_pwdp = cp; } #else /* diff --git a/src/passwd.c b/src/passwd.c index ac90aa3..ae26666 100644 --- a/src/passwd.c +++ b/src/passwd.c @@ -242,6 +242,17 @@ static int new_password (const struct pa } cipher = pw_encrypt (clear, crypt_passwd); + if (cipher == NULL) { + strzero (clear); + (void) fprintf (stderr, + _("Failed to crypt password for %s.\n"), + pw->pw_name); + SYSLOG ((LOG_INFO, + "failed to crypt password for %s", + pw->pw_name)); + return -1; + } + if (strcmp (cipher, crypt_passwd) != 0) { strzero (clear); strzero (cipher); @@ -349,6 +360,10 @@ static int new_password (const struct pa * Encrypt the password, then wipe the cleartext password. */ cp = pw_encrypt (pass, crypt_make_salt (NULL, NULL)); + if (cp == NULL) { + perror ("crypt"); + exit (EXIT_FAILURE); + } memzero (pass, sizeof pass); #ifdef HAVE_LIBCRACK_HIST -- 1.7.11.4