diff --git a/auth-passwd.c b/auth-passwd.c index 63ccf3cab..530b5d4f7 100644 --- a/auth-passwd.c +++ b/auth-passwd.c @@ -193,7 +193,7 @@ int sys_auth_passwd(Authctxt *authctxt, const char *password) { struct passwd *pw = authctxt->pw; - char *encrypted_password; + char *encrypted_password, *salt = NULL; /* Just use the supplied fake password if authctxt is invalid */ char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd; @@ -202,9 +202,13 @@ sys_auth_passwd(Authctxt *authctxt, const char *password) if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0) return (1); - /* Encrypt the candidate password using the proper salt. */ - encrypted_password = xcrypt(password, - (pw_password[0] && pw_password[1]) ? pw_password : "xx"); + /* + * Encrypt the candidate password using the proper salt, or pass a + * NULL and let xcrypt pick one. + */ + if (authctxt->valid && pw_password[0] && pw_password[1]) + salt = pw_password; + encrypted_password = xcrypt(password, salt); /* * Authentication is accepted if the encrypted passwords diff --git a/openbsd-compat/xcrypt.c b/openbsd-compat/xcrypt.c index 8577cbd8a..8913bb81a 100644 --- a/openbsd-compat/xcrypt.c +++ b/openbsd-compat/xcrypt.c @@ -25,6 +25,7 @@ #include "includes.h" #include +#include #include #include @@ -62,11 +63,44 @@ # define crypt DES_crypt # endif +/* + * Pick an appropriate password encryption type and salt for the running + * system. + */ +static const char * +pick_salt(void) +{ + struct passwd *pw; + char *passwd, *p; + size_t typelen; + static char salt[32]; + + if (salt[0] != '\0') + return salt; + strlcpy(salt, "xx", sizeof(salt)); + if ((pw = getpwuid(0)) == NULL) + return salt; + passwd = shadow_pw(pw); + if (passwd[0] != '$' || (p = strrchr(passwd + 1, '$')) == NULL) + return salt; /* no $, DES */ + typelen = p - passwd + 1; + strlcpy(salt, passwd, MIN(typelen, sizeof(salt))); + explicit_bzero(passwd, strlen(passwd)); + return salt; +} + char * xcrypt(const char *password, const char *salt) { char *crypted; + /* + * If we don't have a salt we are encrypting a fake password for + * for timing purposes. Pick an appropriate salt. + */ + if (salt == NULL) + salt = pick_salt(); + # ifdef HAVE_MD5_PASSWORDS if (is_md5_salt(salt)) crypted = md5_crypt(password, salt);