Index: lib/libcrypt/crypt.h =================================================================== --- lib/libcrypt/crypt.h +++ lib/libcrypt/crypt.h @@ -34,12 +34,14 @@ #define MD4_SIZE 16 #define MD5_SIZE 16 +#define CRYPT_SALT_MAX_LEN 16 + int crypt_des(const char *pw, const char *salt, char *buf); int crypt_md5(const char *pw, const char *salt, char *buf); int crypt_nthash(const char *pw, const char *salt, char *buf); int crypt_blowfish(const char *pw, const char *salt, char *buf); -int crypt_sha256 (const char *pw, const char *salt, char *buf); -int crypt_sha512 (const char *pw, const char *salt, char *buf); +int crypt_sha256(const char *pw, const char *salt, char *buf); +int crypt_sha512(const char *pw, const char *salt, char *buf); extern void _crypt_to64(char *s, u_long v, int n); extern void b64_from_24bit(uint8_t B2, uint8_t B1, uint8_t B0, int n, char **cp); Index: lib/libcrypt/crypt.3 =================================================================== --- lib/libcrypt/crypt.3 +++ lib/libcrypt/crypt.3 @@ -221,8 +221,7 @@ .\" .\" NOTICE: Also make sure to update this .\" -DES -if it is available, or MD5 if not. +DES if it is available, or SHA-512 if not. .Pp How the salt is used will depend upon the algorithm for the hash. For Index: lib/libcrypt/crypt.c =================================================================== --- lib/libcrypt/crypt.c +++ lib/libcrypt/crypt.c @@ -34,10 +34,13 @@ #include #include +#include #include #include "crypt.h" +#define CRYPT_MAGIC_MAX_LEN 64 + /* * List of supported crypt(3) formats. * @@ -62,13 +65,13 @@ #ifdef HAS_DES { "des", crypt_des, "_" }, #endif - /* sentinel */ { NULL, NULL, NULL } }; -static const struct crypt_format *crypt_format = - &crypt_formats[(sizeof crypt_formats / sizeof *crypt_formats) - 2]; +static char crypt_default_magic[CRYPT_MAGIC_MAX_LEN] = ""; +static const struct crypt_format *crypt_default_format = + &crypt_formats[(sizeof crypt_formats / sizeof *crypt_formats) - 2]; #define DES_SALT_ALPHABET \ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" @@ -79,8 +82,7 @@ const char * crypt_get_format(void) { - - return (crypt_format->name); + return (crypt_default_format->name); } /* @@ -92,9 +94,18 @@ const struct crypt_format *cf; for (cf = crypt_formats; cf->name != NULL; ++cf) { - if (strcasecmp(cf->name, format) == 0) { - crypt_format = cf; - return (1); + if (format[0] == '$') { + if (strncmp(cf->magic, format, strlen(cf->magic)) == 0) { + strlcpy(crypt_default_magic, format, sizeof(crypt_default_magic)); + crypt_default_format = cf; + return (1); + } + } else { + if (strcasecmp(cf->name, format) == 0) { + crypt_default_magic[0] = '\0'; + crypt_default_format = cf; + return (1); + } } } return (0); @@ -113,6 +124,9 @@ #ifdef HAS_DES int len; #endif + char nsalt[CRYPT_MAGIC_MAX_LEN+CRYPT_SALT_MAX_LEN]; + + strlcpy(nsalt, salt, sizeof(nsalt)); for (cf = crypt_formats; cf->name != NULL; ++cf) if (cf->magic != NULL && strstr(salt, cf->magic) == salt) { @@ -126,9 +140,18 @@ goto match; } #endif - func = crypt_format->func; + /* + * New passwords come with an unprefixed salt, which we will prepend + * with the default magic (if available). Otherwise we fallback to the + * default function. + */ + if (strcmp(crypt_default_magic, "") != 0) { + strlcpy(nsalt, crypt_default_magic, sizeof(nsalt)); + strlcat(nsalt, salt, sizeof(nsalt)); + } + func = crypt_default_format->func; match: - if (func(passwd, salt, data->__buf) != 0) + if (func(passwd, nsalt, data->__buf) != 0) return (NULL); return (data->__buf); }