From cb04d3cb6b3899b5386f940a385d08c66dcd0da1 Mon Sep 17 00:00:00 2001 From: mancha Date: Fri, 31 Jan 2014 Subject: Handle new crypt() behavior in glibc 2.17+ 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. Note: gdm 2.20.11 is the last version that support non-PAM authentication which is why it is the latest stable maintained for Slackware Linux via slackbuilds.org. --- daemon/verify-crypt.c | 13 ++++++++++--- daemon/verify-shadow.c | 13 ++++++++++--- 2 files changed, 20 insertions(+), 6 deletions(-) --- a/daemon/verify-crypt.c +++ b/daemon/verify-crypt.c @@ -104,7 +104,7 @@ gdm_verify_user (GdmDisplay *d, const char *username, gboolean allow_retry) { - gchar *login, *passwd, *ppasswd; + gchar *login, *passwd, *ppasswd, *cpasswd; struct passwd *pwent; #if defined (HAVE_PASSWDEXPIRED) && defined (HAVE_CHPASS) \ || defined (HAVE_LOGINRESTRICTIONS) @@ -190,8 +190,10 @@ gdm_verify_user (GdmDisplay *d, } /* Check whether password is valid */ - if (ppasswd == NULL || (ppasswd[0] != '\0' && - strcmp (crypt (passwd, ppasswd), ppasswd) != 0)) { + cpasswd = ppasswd ? g_strdup(crypt (passwd, ppasswd)) : NULL; + if (ppasswd == NULL || cpasswd == NULL || + (ppasswd[0] != '\0' && + strcmp (cpasswd, ppasswd) != 0)) { gdm_sleep_no_signal (gdm_daemon_config_get_value_int (GDM_KEY_RETRY_DELAY)); gdm_debug ("Couldn't authenticate user"); @@ -200,6 +202,7 @@ gdm_verify_user (GdmDisplay *d, g_free (login); g_free (passwd); g_free (ppasswd); + g_free (cpasswd); return NULL; } @@ -217,6 +220,7 @@ gdm_verify_user (GdmDisplay *d, g_free (login); g_free (passwd); g_free (ppasswd); + g_free (cpasswd); return NULL; } @@ -233,6 +237,7 @@ gdm_verify_user (GdmDisplay *d, g_free (login); g_free (passwd); g_free (ppasswd); + g_free (cpasswd); if (message != NULL) free (message); return NULL; @@ -259,6 +264,7 @@ gdm_verify_user (GdmDisplay *d, g_free (login); g_free (passwd); g_free (ppasswd); + g_free (cpasswd); return NULL; } @@ -266,6 +272,7 @@ gdm_verify_user (GdmDisplay *d, g_free (passwd); g_free (ppasswd); + g_free (cpasswd); if ( ! gdm_slave_check_user_wants_to_log_in (login)) { g_free (login); --- a/daemon/verify-shadow.c +++ b/daemon/verify-shadow.c @@ -105,7 +105,7 @@ gdm_verify_user (GdmDisplay *d, const char *username, gboolean allow_retry) { - gchar *login, *passwd, *ppasswd; + gchar *login, *passwd, *ppasswd, *cpasswd; struct passwd *pwent; struct spwd *sp; #if defined (HAVE_PASSWDEXPIRED) && defined (HAVE_CHPASS) \ @@ -211,8 +211,10 @@ gdm_verify_user (GdmDisplay *d, } /* Check whether password is valid */ - if (ppasswd == NULL || (ppasswd[0] != '\0' && - strcmp (crypt (passwd, ppasswd), ppasswd) != 0)) { + cpasswd = ppasswd ? g_strdup(crypt (passwd, ppasswd)) : NULL; + if (ppasswd == NULL || cpasswd == NULL || + (ppasswd[0] != '\0' && + strcmp (cpasswd, ppasswd) != 0)) { gdm_sleep_no_signal (gdm_daemon_config_get_value_int (GDM_KEY_RETRY_DELAY)); gdm_debug ("Couldn't authenticate user"); @@ -221,6 +223,7 @@ gdm_verify_user (GdmDisplay *d, g_free (login); g_free (passwd); g_free (ppasswd); + g_free (cpasswd); return NULL; } @@ -238,6 +241,7 @@ gdm_verify_user (GdmDisplay *d, g_free (login); g_free (passwd); g_free (ppasswd); + g_free (cpasswd); return NULL; } @@ -254,6 +258,7 @@ gdm_verify_user (GdmDisplay *d, g_free (login); g_free (passwd); g_free (ppasswd); + g_free (cpasswd); if (message != NULL) free (message); return NULL; @@ -280,6 +285,7 @@ gdm_verify_user (GdmDisplay *d, g_free (login); g_free (passwd); g_free (ppasswd); + g_free (cpasswd); return NULL; } @@ -287,6 +293,7 @@ gdm_verify_user (GdmDisplay *d, g_free (passwd); g_free (ppasswd); + g_free (cpasswd); if ( ! gdm_slave_check_user_wants_to_log_in (login)) { g_free (login);