diff options
Diffstat (limited to 'lib/libcrypt/crypt.c')
-rw-r--r-- | lib/libcrypt/crypt.c | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/lib/libcrypt/crypt.c b/lib/libcrypt/crypt.c new file mode 100644 index 0000000..c3ca4c2 --- /dev/null +++ b/lib/libcrypt/crypt.c @@ -0,0 +1,120 @@ +/*- + * Copyright (c) 1999 Mark Murray + * Copyright (c) 2014 Dag-Erling Smørgrav + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY MARK MURRAY AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL MARK MURRAY OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> + +#include <libutil.h> +#include <string.h> +#include <unistd.h> + +#include "crypt.h" + +/* + * List of supported crypt(3) formats. The first element in the list will + * be the default. + */ +static const struct crypt_format { + const char *const name; + char *(*const func)(const char *, const char *); + const char *const magic; +} crypt_formats[] = { + /* default format */ + { "sha512", crypt_sha512, "$6$" }, + + /* other supported formats */ + { "md5", crypt_md5, "$1$" }, +#ifdef HAS_BLOWFISH + { "blf", crypt_blowfish, "$2" }, +#endif + { "nth", crypt_nthash, "$3$" }, + { "sha256", crypt_sha256, "$5$" }, +#ifdef HAS_DES + { "des", crypt_des, "_" }, +#endif + + /* sentinel */ + { NULL, NULL, NULL } +}; + +static const struct crypt_format *crypt_format = &crypt_formats[0]; + +#define DES_SALT_ALPHABET \ + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + +/* + * Returns the name of the currently selected format. + */ +const char * +crypt_get_format(void) +{ + + return (crypt_format->name); +} + +/* + * Selects the format to use for subsequent crypt(3) invocations. + */ +int +crypt_set_format(const char *format) +{ + const struct crypt_format *cf; + + for (cf = crypt_formats; cf->name != NULL; ++cf) { + if (strcasecmp(cf->name, format) == 0) { + crypt_format = cf; + return (1); + } + } + return (0); +} + +/* + * Hash the given password with the given salt. If the salt begins with a + * magic string (e.g. "$6$" for sha512), the corresponding format is used; + * otherwise, the currently selected format is used. + */ +char * +crypt(const char *passwd, const char *salt) +{ + const struct crypt_format *cf; +#ifdef HAS_DES + int len; +#endif + + for (cf = crypt_formats; cf->name != NULL; ++cf) + if (cf->magic != NULL && strstr(salt, cf->magic) == salt) + return (cf->func(passwd, salt)); +#ifdef HAS_DES + len = strlen(salt); + if ((len == 13 || len == 2) && strspn(salt, DES_SALT_ALPHABET) == len) + return (crypt_des(passwd, salt)); +#endif + return (crypt_format->func(passwd, salt)); +} |