From 33feceb1573cbb6ba7fb326bb7872de75bca6b9e Mon Sep 17 00:00:00 2001 From: mancha Date: Wed, 18 Feb 2015 Subject: Fix account validation with glibc crypt Starting with glibc 2.17, crypt() can return NULL which can cause xrdp-sesman to segfault. This patch backports upstream's fix for this as well as changes auth_userpass so it can validate SHA-256 and SHA-512 hashed passwords. --- sesman/verify_user.c | 87 ++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 52 deletions(-) --- a/sesman/verify_user.c +++ b/sesman/verify_user.c @@ -51,64 +51,47 @@ auth_account_disabled(struct spwd* stp); long DEFAULT_CC auth_userpass(char* user, char* pass) { - char salt[13] = "$1$"; - char hash[35] = ""; - char* encr = 0; - struct passwd* spw; - struct spwd* stp; - int saltcnt = 0; - - spw = getpwnam(user); - if (spw == 0) - { - return 0; - } - if (g_strncmp(spw->pw_passwd, "x", 3) == 0) - { - /* the system is using shadow */ - stp = getspnam(user); - if (stp == 0) + const char *encr; + const char *epass; + struct passwd *spw; + struct spwd *stp; + + spw = getpwnam(user); + + if (spw == 0) + { + return 0; + } + + if (g_strncmp(spw->pw_passwd, "x", 3) == 0) { - return 0; + /* the system is using shadow */ + stp = getspnam(user); + + if (stp == 0) + { + return 0; + } + + if (1 == auth_account_disabled(stp)) + { + log_message(&(g_cfg->log), LOG_LEVEL_INFO, "account %s is disabled", user); + return 0; + } + + encr = stp->sp_pwdp; } - if (1==auth_account_disabled(stp)) + else { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "account %s is disabled", user); - return 0; + /* old system with only passwd */ + encr = spw->pw_passwd; } - g_strncpy(hash, stp->sp_pwdp, 34); - } - else - { - /* old system with only passwd */ - g_strncpy(hash, spw->pw_passwd, 34); - } - hash[34] = '\0'; - if (g_strncmp(hash, "$1$", 3) == 0) - { - /* gnu style crypt(); */ - saltcnt = 3; - while ((hash[saltcnt] != '$') && (saltcnt < 11)) + epass = crypt(pass, encr); + if (epass == 0) { - salt[saltcnt] = hash[saltcnt]; - saltcnt++; + return 0; } - salt[saltcnt] = '$'; - salt[saltcnt + 1] = '\0'; - } - else - { - /* classic two char salt */ - salt[0] = hash[0]; - salt[1] = hash[1]; - salt[2] = '\0'; - } - encr = crypt(pass,salt); - if (g_strncmp(encr, hash, 34) != 0) - { - return 0; - } - return 1; + return (strcmp(encr, epass) == 0); } /******************************************************************************/