2007-10-07 17:14:02 +05:30
|
|
|
/*
|
|
|
|
* salt.c - generate a random salt string for crypt()
|
|
|
|
*
|
|
|
|
* Written by Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>,
|
2008-04-27 06:10:09 +05:30
|
|
|
* it is in the public domain.
|
2007-11-16 18:06:21 +05:30
|
|
|
*
|
|
|
|
* l64a was Written by J.T. Conklin <jtc@netbsd.org>. Public domain.
|
2007-10-07 17:14:02 +05:30
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2007-11-11 05:16:11 +05:30
|
|
|
#ident "$Id$"
|
2007-10-07 17:17:01 +05:30
|
|
|
|
2007-11-24 02:21:43 +05:30
|
|
|
#include <assert.h>
|
2021-06-23 19:36:47 +05:30
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2007-10-07 17:14:02 +05:30
|
|
|
#include "prototypes.h"
|
|
|
|
#include "defines.h"
|
|
|
|
#include "getdef.h"
|
2007-11-16 18:06:21 +05:30
|
|
|
|
2021-06-15 02:58:28 +05:30
|
|
|
/* Add the salt prefix. */
|
|
|
|
#define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0'
|
|
|
|
|
|
|
|
#ifdef USE_BCRYPT
|
|
|
|
/* Use $2b$ as prefix for compatibility with OpenBSD's bcrypt. */
|
|
|
|
#define BCRYPTMAGNUM(array) (array)[0]=(array)[3]='$',(array)[1]='2',(array)[2]='b',(array)[4]='\0'
|
|
|
|
#define BCRYPT_SALT_SIZE 22
|
|
|
|
/* Default number of rounds if not explicitly specified. */
|
|
|
|
#define B_ROUNDS_DEFAULT 13
|
|
|
|
/* Minimum number of rounds. */
|
|
|
|
#define B_ROUNDS_MIN 4
|
|
|
|
/* Maximum number of rounds. */
|
|
|
|
#define B_ROUNDS_MAX 31
|
|
|
|
#endif /* USE_BCRYPT */
|
|
|
|
|
|
|
|
#ifdef USE_SHA_CRYPT
|
|
|
|
/* Fixed salt len for sha{256,512}crypt. */
|
|
|
|
#define SHA_CRYPT_SALT_SIZE 16
|
|
|
|
/* Default number of rounds if not explicitly specified. */
|
|
|
|
#define SHA_ROUNDS_DEFAULT 5000
|
|
|
|
/* Minimum number of rounds. */
|
|
|
|
#define SHA_ROUNDS_MIN 1000
|
|
|
|
/* Maximum number of rounds. */
|
|
|
|
#define SHA_ROUNDS_MAX 999999999
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef USE_YESCRYPT
|
|
|
|
/*
|
|
|
|
* Default number of base64 characters used for the salt.
|
|
|
|
* 24 characters gives a 144 bits (18 bytes) salt. Unlike the more
|
|
|
|
* traditional 128 bits (16 bytes) salt, this 144 bits salt is always
|
|
|
|
* represented by the same number of base64 characters without padding
|
|
|
|
* issue, even with a non-standard base64 encoding scheme.
|
|
|
|
*/
|
|
|
|
#define YESCRYPT_SALT_SIZE 24
|
|
|
|
/* Default cost if not explicitly specified. */
|
|
|
|
#define Y_COST_DEFAULT 5
|
|
|
|
/* Minimum cost. */
|
|
|
|
#define Y_COST_MIN 1
|
|
|
|
/* Maximum cost. */
|
|
|
|
#define Y_COST_MAX 11
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Fixed salt len for md5crypt. */
|
|
|
|
#define MD5_CRYPT_SALT_SIZE 8
|
|
|
|
|
|
|
|
/* Generate salt of size salt_size. */
|
|
|
|
#define MAX_SALT_SIZE 44
|
|
|
|
#define MIN_SALT_SIZE 8
|
|
|
|
|
|
|
|
/* Maximum size of the generated salt string. */
|
|
|
|
#define GENSALT_SETTING_SIZE 100
|
|
|
|
|
2008-01-06 20:20:26 +05:30
|
|
|
/* local function prototypes */
|
2021-06-23 19:36:47 +05:30
|
|
|
static long read_random_bytes (void);
|
* libmisc/xgetXXbyYY.c, libmisc/myname.c, libmisc/getgr_nam_gid.c,
libmisc/salt.c, libmisc/list.c, libmisc/cleanup.c, src/login.c,
lib/getdef.h, lib/groupio.c, lib/getlong.c, lib/gshadow_.h,
lib/sgroupio.c, lib/shadowio.c, lib/pwio.c, lib/commonio.h,
lib/fputsx.c, lib/prototypes.h: Added splint annotations.
* lib/groupio.c: Avoid implicit conversion of pointers to
booleans.
* lib/groupio.c: Free allocated buffers in case of failure.
2009-04-23 15:27:03 +05:30
|
|
|
static /*@observer@*/const char *gensalt (size_t salt_size);
|
2019-09-17 00:24:56 +05:30
|
|
|
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
2013-08-13 22:46:24 +05:30
|
|
|
static long shadow_random (long min, long max);
|
2019-09-17 00:24:56 +05:30
|
|
|
#endif /* USE_SHA_CRYPT || USE_BCRYPT */
|
|
|
|
#ifdef USE_SHA_CRYPT
|
2021-06-15 02:58:28 +05:30
|
|
|
static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds);
|
2008-05-20 02:26:48 +05:30
|
|
|
#endif /* USE_SHA_CRYPT */
|
2019-09-17 00:24:56 +05:30
|
|
|
#ifdef USE_BCRYPT
|
2021-06-15 02:58:28 +05:30
|
|
|
static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds);
|
2019-09-17 00:24:56 +05:30
|
|
|
#endif /* USE_BCRYPT */
|
2020-12-28 01:39:25 +05:30
|
|
|
#ifdef USE_YESCRYPT
|
2021-06-15 02:58:28 +05:30
|
|
|
static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, /*@null@*/int *prefered_cost);
|
2020-12-28 01:39:25 +05:30
|
|
|
#endif /* USE_YESCRYPT */
|
2008-01-06 20:20:26 +05:30
|
|
|
|
|
|
|
#ifndef HAVE_L64A
|
2021-06-15 02:58:28 +05:30
|
|
|
static /*@observer@*/char *l64a (long value)
|
2007-11-16 18:06:21 +05:30
|
|
|
{
|
|
|
|
static char buf[8];
|
|
|
|
char *s = buf;
|
|
|
|
int digit;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (value < 0) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; value != 0 && i < 6; i++) {
|
|
|
|
digit = value & 0x3f;
|
|
|
|
|
2008-06-14 01:07:15 +05:30
|
|
|
if (digit < 2) {
|
2007-11-16 18:06:21 +05:30
|
|
|
*s = digit + '.';
|
2008-06-14 01:07:15 +05:30
|
|
|
} else if (digit < 12) {
|
2007-11-16 18:06:21 +05:30
|
|
|
*s = digit + '0' - 2;
|
2008-06-14 01:07:15 +05:30
|
|
|
} else if (digit < 38) {
|
2007-11-16 18:06:21 +05:30
|
|
|
*s = digit + 'A' - 12;
|
2008-06-14 01:07:15 +05:30
|
|
|
} else {
|
2007-11-16 18:06:21 +05:30
|
|
|
*s = digit + 'a' - 38;
|
2008-06-14 01:07:15 +05:30
|
|
|
}
|
2007-11-16 18:06:21 +05:30
|
|
|
|
|
|
|
value >>= 6;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*s = '\0';
|
|
|
|
|
2021-06-15 02:58:28 +05:30
|
|
|
return buf;
|
2007-11-16 18:06:21 +05:30
|
|
|
}
|
|
|
|
#endif /* !HAVE_L64A */
|
|
|
|
|
2021-06-23 19:36:47 +05:30
|
|
|
/* Read sizeof (long) random bytes from /dev/urandom. */
|
|
|
|
static long read_random_bytes (void)
|
2008-02-03 22:53:58 +05:30
|
|
|
{
|
2021-06-23 19:36:47 +05:30
|
|
|
long randval = 0;
|
|
|
|
FILE *f = fopen ("/dev/urandom", "r");
|
2008-02-03 22:53:58 +05:30
|
|
|
|
2021-06-23 19:36:47 +05:30
|
|
|
if (fread (&randval, sizeof (randval), 1, f) != sizeof (randval))
|
|
|
|
{
|
|
|
|
fprintf (shadow_logfd,
|
|
|
|
_("Unable to read from /dev/urandom.\n"));
|
|
|
|
|
|
|
|
fclose(f);
|
|
|
|
exit (1);
|
2008-02-03 22:53:58 +05:30
|
|
|
}
|
2021-06-23 19:36:47 +05:30
|
|
|
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
return randval;
|
2008-02-03 22:53:58 +05:30
|
|
|
}
|
|
|
|
|
2019-09-17 00:24:56 +05:30
|
|
|
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
|
2007-11-20 05:35:54 +05:30
|
|
|
/*
|
2013-08-05 17:49:23 +05:30
|
|
|
* Return a random number between min and max (both included).
|
|
|
|
*
|
|
|
|
* It favors slightly the higher numbers.
|
2007-11-20 05:35:54 +05:30
|
|
|
*/
|
2013-08-13 22:46:24 +05:30
|
|
|
static long shadow_random (long min, long max)
|
2007-11-20 05:35:54 +05:30
|
|
|
{
|
2013-08-05 17:49:23 +05:30
|
|
|
double drand;
|
2013-08-13 22:46:24 +05:30
|
|
|
long ret;
|
2021-06-23 19:36:47 +05:30
|
|
|
|
|
|
|
drand = (double) (read_random_bytes () & RAND_MAX) / (double) RAND_MAX;
|
|
|
|
drand *= (double) (max - min + 1);
|
2013-08-05 17:49:23 +05:30
|
|
|
/* On systems were this is not random() range is lower, we favor
|
|
|
|
* higher numbers of salt. */
|
2013-08-13 22:46:24 +05:30
|
|
|
ret = (long) (max + 1 - drand);
|
2013-08-05 17:49:23 +05:30
|
|
|
/* And we catch limits, and use the highest number */
|
|
|
|
if ((ret < min) || (ret > max)) {
|
|
|
|
ret = max;
|
|
|
|
}
|
|
|
|
return ret;
|
2007-11-20 05:35:54 +05:30
|
|
|
}
|
2019-09-17 00:24:56 +05:30
|
|
|
#endif /* USE_SHA_CRYPT || USE_BCRYPT */
|
2007-11-20 05:35:54 +05:30
|
|
|
|
2019-09-17 00:24:56 +05:30
|
|
|
#ifdef USE_SHA_CRYPT
|
2007-11-20 05:35:54 +05:30
|
|
|
/*
|
2021-06-15 02:58:28 +05:30
|
|
|
* Fill a salt prefix specifying the rounds number for the SHA crypt methods
|
|
|
|
* to a buffer.
|
2007-11-20 05:35:54 +05:30
|
|
|
*/
|
2021-06-15 02:58:28 +05:30
|
|
|
static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds)
|
2007-11-20 05:35:54 +05:30
|
|
|
{
|
2021-06-15 02:58:28 +05:30
|
|
|
unsigned long rounds;
|
|
|
|
const size_t buf_begin = strlen (buf);
|
2007-11-20 05:35:54 +05:30
|
|
|
|
2007-11-20 15:03:52 +05:30
|
|
|
if (NULL == prefered_rounds) {
|
|
|
|
long min_rounds = getdef_long ("SHA_CRYPT_MIN_ROUNDS", -1);
|
|
|
|
long max_rounds = getdef_long ("SHA_CRYPT_MAX_ROUNDS", -1);
|
2007-11-20 05:35:54 +05:30
|
|
|
|
2008-06-14 01:07:15 +05:30
|
|
|
if ((-1 == min_rounds) && (-1 == max_rounds)) {
|
2021-06-15 02:58:28 +05:30
|
|
|
rounds = SHA_ROUNDS_DEFAULT;
|
2008-06-14 01:07:15 +05:30
|
|
|
}
|
2007-11-20 05:35:54 +05:30
|
|
|
|
2008-06-14 01:07:15 +05:30
|
|
|
if (-1 == min_rounds) {
|
2007-11-20 15:03:52 +05:30
|
|
|
min_rounds = max_rounds;
|
2008-06-14 01:07:15 +05:30
|
|
|
}
|
2007-11-20 05:35:54 +05:30
|
|
|
|
2008-06-14 01:07:15 +05:30
|
|
|
if (-1 == max_rounds) {
|
2007-11-20 15:03:52 +05:30
|
|
|
max_rounds = min_rounds;
|
2008-06-14 01:07:15 +05:30
|
|
|
}
|
2007-11-20 05:35:54 +05:30
|
|
|
|
2008-06-14 01:07:15 +05:30
|
|
|
if (min_rounds > max_rounds) {
|
2007-11-20 15:03:52 +05:30
|
|
|
max_rounds = min_rounds;
|
2008-06-14 01:07:15 +05:30
|
|
|
}
|
2007-11-20 15:03:52 +05:30
|
|
|
|
2021-06-15 02:58:28 +05:30
|
|
|
rounds = (unsigned long) shadow_random (min_rounds, max_rounds);
|
2008-06-14 01:07:15 +05:30
|
|
|
} else if (0 == *prefered_rounds) {
|
2021-06-15 02:58:28 +05:30
|
|
|
rounds = SHA_ROUNDS_DEFAULT;
|
2008-06-14 01:07:15 +05:30
|
|
|
} else {
|
2021-06-15 02:58:28 +05:30
|
|
|
rounds = (unsigned long) *prefered_rounds;
|
2008-06-14 01:07:15 +05:30
|
|
|
}
|
2007-11-20 05:35:54 +05:30
|
|
|
|
|
|
|
/* Sanity checks. The libc should also check this, but this
|
|
|
|
* protects against a rounds_prefix overflow. */
|
2021-06-15 02:58:28 +05:30
|
|
|
if (rounds < SHA_ROUNDS_MIN) {
|
|
|
|
rounds = SHA_ROUNDS_MIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rounds > SHA_ROUNDS_MAX) {
|
|
|
|
rounds = SHA_ROUNDS_MAX;
|
2008-06-14 01:07:15 +05:30
|
|
|
}
|
2007-11-20 05:35:54 +05:30
|
|
|
|
2021-06-15 02:58:28 +05:30
|
|
|
/* Nothing to do here if SHA_ROUNDS_DEFAULT is used. */
|
|
|
|
if (rounds == SHA_ROUNDS_DEFAULT) {
|
|
|
|
return;
|
2008-06-14 01:07:15 +05:30
|
|
|
}
|
2007-11-20 05:35:54 +05:30
|
|
|
|
2021-06-15 02:58:28 +05:30
|
|
|
/*
|
|
|
|
* Check if the result buffer is long enough.
|
|
|
|
* We are going to write a maximum of 17 bytes,
|
|
|
|
* plus one byte for the terminator.
|
|
|
|
* rounds=XXXXXXXXX$
|
|
|
|
* 00000000011111111
|
|
|
|
* 12345678901234567
|
|
|
|
*/
|
2021-06-15 02:58:28 +05:30
|
|
|
assert (GENSALT_SETTING_SIZE > buf_begin + 17);
|
2007-11-20 05:35:54 +05:30
|
|
|
|
2021-06-15 02:58:28 +05:30
|
|
|
(void) snprintf (buf + buf_begin, 18, "rounds=%lu$", rounds);
|
2007-11-20 05:35:54 +05:30
|
|
|
}
|
2008-05-20 02:26:48 +05:30
|
|
|
#endif /* USE_SHA_CRYPT */
|
2007-11-20 05:35:54 +05:30
|
|
|
|
2019-09-17 00:24:56 +05:30
|
|
|
#ifdef USE_BCRYPT
|
|
|
|
/*
|
2021-06-15 02:58:28 +05:30
|
|
|
* Fill a salt prefix specifying the rounds number for the BCRYPT method
|
|
|
|
* to a buffer.
|
2019-09-17 00:24:56 +05:30
|
|
|
*/
|
2021-06-15 02:58:28 +05:30
|
|
|
static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds)
|
2019-09-17 00:24:56 +05:30
|
|
|
{
|
2021-06-15 02:58:28 +05:30
|
|
|
unsigned long rounds;
|
|
|
|
const size_t buf_begin = strlen (buf);
|
2019-09-17 00:24:56 +05:30
|
|
|
|
|
|
|
if (NULL == prefered_rounds) {
|
|
|
|
long min_rounds = getdef_long ("BCRYPT_MIN_ROUNDS", -1);
|
|
|
|
long max_rounds = getdef_long ("BCRYPT_MAX_ROUNDS", -1);
|
|
|
|
|
2021-06-15 02:58:28 +05:30
|
|
|
if ((-1 == min_rounds) && (-1 == max_rounds)) {
|
2019-09-17 00:24:56 +05:30
|
|
|
rounds = B_ROUNDS_DEFAULT;
|
2021-06-15 02:58:28 +05:30
|
|
|
} else {
|
2019-09-17 00:24:56 +05:30
|
|
|
if (-1 == min_rounds) {
|
|
|
|
min_rounds = max_rounds;
|
|
|
|
}
|
2021-06-15 02:58:28 +05:30
|
|
|
|
2019-09-17 00:24:56 +05:30
|
|
|
if (-1 == max_rounds) {
|
|
|
|
max_rounds = min_rounds;
|
|
|
|
}
|
2021-06-15 02:58:28 +05:30
|
|
|
|
2019-09-17 00:24:56 +05:30
|
|
|
if (min_rounds > max_rounds) {
|
|
|
|
max_rounds = min_rounds;
|
|
|
|
}
|
2021-06-15 02:58:28 +05:30
|
|
|
|
|
|
|
rounds = (unsigned long) shadow_random (min_rounds, max_rounds);
|
2019-09-17 00:24:56 +05:30
|
|
|
}
|
2021-06-15 02:58:28 +05:30
|
|
|
} else if (0 == *prefered_rounds) {
|
|
|
|
rounds = B_ROUNDS_DEFAULT;
|
2019-09-17 00:24:56 +05:30
|
|
|
} else {
|
2021-06-15 02:58:28 +05:30
|
|
|
rounds = (unsigned long) *prefered_rounds;
|
2019-09-17 00:24:56 +05:30
|
|
|
}
|
|
|
|
|
2021-06-15 02:58:28 +05:30
|
|
|
/* Sanity checks. */
|
2019-09-17 00:24:56 +05:30
|
|
|
if (rounds < B_ROUNDS_MIN) {
|
|
|
|
rounds = B_ROUNDS_MIN;
|
|
|
|
}
|
|
|
|
|
2021-06-15 02:58:28 +05:30
|
|
|
/*
|
|
|
|
* Use 19 as an upper bound for now,
|
|
|
|
* because musl doesn't allow rounds >= 20.
|
|
|
|
*/
|
2019-09-17 00:24:56 +05:30
|
|
|
if (rounds > 19) {
|
|
|
|
/* rounds = B_ROUNDS_MAX; */
|
|
|
|
rounds = 19;
|
|
|
|
}
|
|
|
|
|
2021-06-15 02:58:28 +05:30
|
|
|
/*
|
|
|
|
* Check if the result buffer is long enough.
|
|
|
|
* We are going to write three bytes,
|
|
|
|
* plus one byte for the terminator.
|
|
|
|
* XX$
|
|
|
|
* 000
|
|
|
|
* 123
|
|
|
|
*/
|
2021-06-15 02:58:28 +05:30
|
|
|
assert (GENSALT_SETTING_SIZE > buf_begin + 3);
|
2019-09-17 00:24:56 +05:30
|
|
|
|
2021-06-15 02:58:28 +05:30
|
|
|
(void) snprintf (buf + buf_begin, 4, "%2.2lu$", rounds);
|
2019-09-17 00:24:56 +05:30
|
|
|
}
|
|
|
|
#endif /* USE_BCRYPT */
|
|
|
|
|
2020-12-28 01:39:25 +05:30
|
|
|
#ifdef USE_YESCRYPT
|
|
|
|
/*
|
2021-06-15 02:58:28 +05:30
|
|
|
* Fill a salt prefix specifying the cost for the YESCRYPT method
|
|
|
|
* to a buffer.
|
2020-12-28 01:39:25 +05:30
|
|
|
*/
|
2021-06-15 02:58:28 +05:30
|
|
|
static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, /*@null@*/int *prefered_cost)
|
2020-12-28 01:39:25 +05:30
|
|
|
{
|
2021-06-15 02:58:28 +05:30
|
|
|
unsigned long cost;
|
|
|
|
const size_t buf_begin = strlen (buf);
|
2020-12-28 01:39:25 +05:30
|
|
|
|
|
|
|
if (NULL == prefered_cost) {
|
|
|
|
cost = getdef_num ("YESCRYPT_COST_FACTOR", Y_COST_DEFAULT);
|
2021-06-15 02:58:28 +05:30
|
|
|
} else if (0 == *prefered_cost) {
|
|
|
|
cost = Y_COST_DEFAULT;
|
2020-12-28 01:39:25 +05:30
|
|
|
} else {
|
2021-06-15 02:58:28 +05:30
|
|
|
cost = (unsigned long) *prefered_cost;
|
2020-12-28 01:39:25 +05:30
|
|
|
}
|
|
|
|
|
2021-06-15 02:58:28 +05:30
|
|
|
/* Sanity checks. */
|
2020-12-28 01:39:25 +05:30
|
|
|
if (cost < Y_COST_MIN) {
|
|
|
|
cost = Y_COST_MIN;
|
|
|
|
}
|
2021-06-15 02:58:28 +05:30
|
|
|
|
2020-12-28 01:39:25 +05:30
|
|
|
if (cost > Y_COST_MAX) {
|
|
|
|
cost = Y_COST_MAX;
|
|
|
|
}
|
|
|
|
|
2021-06-15 02:58:28 +05:30
|
|
|
/*
|
|
|
|
* Check if the result buffer is long enough.
|
|
|
|
* We are going to write four bytes,
|
|
|
|
* plus one byte for the terminator.
|
|
|
|
* jXX$
|
|
|
|
* 0000
|
|
|
|
* 1234
|
|
|
|
*/
|
|
|
|
assert (GENSALT_SETTING_SIZE > buf_begin + 4);
|
2021-06-15 02:58:28 +05:30
|
|
|
|
|
|
|
buf[buf_begin + 0] = 'j';
|
2020-12-28 01:39:25 +05:30
|
|
|
if (cost < 3) {
|
2021-06-15 02:58:28 +05:30
|
|
|
buf[buf_begin + 1] = 0x36 + cost;
|
2020-12-28 01:39:25 +05:30
|
|
|
} else if (cost < 6) {
|
2021-06-15 02:58:28 +05:30
|
|
|
buf[buf_begin + 1] = 0x34 + cost;
|
2020-12-28 01:39:25 +05:30
|
|
|
} else {
|
2021-06-15 02:58:28 +05:30
|
|
|
buf[buf_begin + 1] = 0x3b + cost;
|
2020-12-28 01:39:25 +05:30
|
|
|
}
|
2021-06-15 02:58:28 +05:30
|
|
|
buf[buf_begin + 2] = cost >= 3 ? 'T' : '5';
|
|
|
|
buf[buf_begin + 3] = '$';
|
|
|
|
buf[buf_begin + 4] = '\0';
|
2020-12-28 01:39:25 +05:30
|
|
|
}
|
|
|
|
#endif /* USE_YESCRYPT */
|
|
|
|
|
* libmisc/xgetXXbyYY.c, libmisc/myname.c, libmisc/getgr_nam_gid.c,
libmisc/salt.c, libmisc/list.c, libmisc/cleanup.c, src/login.c,
lib/getdef.h, lib/groupio.c, lib/getlong.c, lib/gshadow_.h,
lib/sgroupio.c, lib/shadowio.c, lib/pwio.c, lib/commonio.h,
lib/fputsx.c, lib/prototypes.h: Added splint annotations.
* lib/groupio.c: Avoid implicit conversion of pointers to
booleans.
* lib/groupio.c: Free allocated buffers in case of failure.
2009-04-23 15:27:03 +05:30
|
|
|
static /*@observer@*/const char *gensalt (size_t salt_size)
|
2008-01-06 20:20:26 +05:30
|
|
|
{
|
2021-06-15 02:58:28 +05:30
|
|
|
static char salt[MAX_SALT_SIZE + 6];
|
2007-11-24 05:30:12 +05:30
|
|
|
|
2021-06-15 02:58:28 +05:30
|
|
|
memset (salt, '\0', MAX_SALT_SIZE + 6);
|
2007-11-24 05:30:12 +05:30
|
|
|
|
2007-11-24 02:34:43 +05:30
|
|
|
assert (salt_size >= MIN_SALT_SIZE &&
|
|
|
|
salt_size <= MAX_SALT_SIZE);
|
2021-06-23 19:36:47 +05:30
|
|
|
strcat (salt, l64a (read_random_bytes ()));
|
2007-11-24 05:30:12 +05:30
|
|
|
do {
|
2021-06-23 19:36:47 +05:30
|
|
|
strcat (salt, l64a (read_random_bytes ()));
|
2007-11-24 05:30:12 +05:30
|
|
|
} while (strlen (salt) < salt_size);
|
2008-06-14 01:07:15 +05:30
|
|
|
|
2007-11-24 05:30:12 +05:30
|
|
|
salt[salt_size] = '\0';
|
|
|
|
|
|
|
|
return salt;
|
2007-11-24 02:21:43 +05:30
|
|
|
}
|
|
|
|
|
2007-11-20 05:35:54 +05:30
|
|
|
/*
|
|
|
|
* Generate 8 base64 ASCII characters of random salt. If MD5_CRYPT_ENAB
|
|
|
|
* in /etc/login.defs is "yes", the salt string will be prefixed by "$1$"
|
|
|
|
* (magic) and pw_encrypt() will execute the MD5-based FreeBSD-compatible
|
|
|
|
* version of crypt() instead of the standard one.
|
|
|
|
* Other methods can be set with ENCRYPT_METHOD
|
2007-11-20 15:03:52 +05:30
|
|
|
*
|
|
|
|
* The method can be forced with the meth parameter.
|
2021-06-15 02:58:28 +05:30
|
|
|
* If NULL, the method will be defined according to the ENCRYPT_METHOD
|
|
|
|
* variable, and if not set according to the MD5_CRYPT_ENAB variable,
|
|
|
|
* which can both be set inside the login.defs file.
|
2007-11-20 15:03:52 +05:30
|
|
|
*
|
|
|
|
* If meth is specified, an additional parameter can be provided.
|
|
|
|
* * For the SHA256 and SHA512 method, this specifies the number of rounds
|
|
|
|
* (if not NULL).
|
2020-12-28 01:39:25 +05:30
|
|
|
* * For the YESCRYPT method, this specifies the cost factor (if not NULL).
|
2007-11-20 05:35:54 +05:30
|
|
|
*/
|
2011-08-14 20:07:17 +05:30
|
|
|
/*@observer@*/const char *crypt_make_salt (/*@null@*//*@observer@*/const char *meth, /*@null@*/void *arg)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2021-06-15 02:58:28 +05:30
|
|
|
static char result[GENSALT_SETTING_SIZE];
|
|
|
|
size_t salt_len = MAX_SALT_SIZE;
|
2008-01-06 20:20:26 +05:30
|
|
|
const char *method;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2021-06-15 02:58:28 +05:30
|
|
|
memset (result, '\0', GENSALT_SETTING_SIZE);
|
2007-11-20 04:04:48 +05:30
|
|
|
|
2007-11-20 15:03:52 +05:30
|
|
|
if (NULL != meth)
|
|
|
|
method = meth;
|
2007-11-24 05:27:47 +05:30
|
|
|
else {
|
2008-06-14 01:07:15 +05:30
|
|
|
method = getdef_str ("ENCRYPT_METHOD");
|
|
|
|
if (NULL == method) {
|
|
|
|
method = getdef_bool ("MD5_CRYPT_ENAB") ? "MD5" : "DES";
|
|
|
|
}
|
2007-11-24 05:27:47 +05:30
|
|
|
}
|
2007-11-20 15:03:52 +05:30
|
|
|
|
2008-05-24 18:38:58 +05:30
|
|
|
if (0 == strcmp (method, "MD5")) {
|
2007-11-20 15:03:52 +05:30
|
|
|
MAGNUM(result, '1');
|
2021-06-15 02:58:28 +05:30
|
|
|
salt_len = MD5_CRYPT_SALT_SIZE;
|
2019-09-17 00:24:56 +05:30
|
|
|
#ifdef USE_BCRYPT
|
|
|
|
} else if (0 == strcmp (method, "BCRYPT")) {
|
|
|
|
BCRYPTMAGNUM(result);
|
2021-06-15 02:58:28 +05:30
|
|
|
salt_len = BCRYPT_SALT_SIZE;
|
|
|
|
BCRYPT_salt_rounds_to_buf (result, (int *) arg);
|
2019-09-17 00:24:56 +05:30
|
|
|
#endif /* USE_BCRYPT */
|
2020-12-28 01:39:25 +05:30
|
|
|
#ifdef USE_YESCRYPT
|
|
|
|
} else if (0 == strcmp (method, "YESCRYPT")) {
|
|
|
|
MAGNUM(result, 'y');
|
2021-06-15 02:58:28 +05:30
|
|
|
salt_len = YESCRYPT_SALT_SIZE;
|
|
|
|
YESCRYPT_salt_cost_to_buf (result, (int *) arg);
|
2020-12-28 01:39:25 +05:30
|
|
|
#endif /* USE_YESCRYPT */
|
* configure.in: New configure option: --with-sha-crypt enabled by
default. Keeping the feature enabled is safe. Disabling it permits
to disable the references to the SHA256 and SHA512 password
encryption algorithms from the usage help and manuals (in addition
to the support for these algorithms in the code).
* libmisc/obscure.c, libmisc/salt.c, src/newusers.c,
src/chpasswd.c, src/chgpasswd.c, src/passwd.c: ENCRYPT_METHOD is
always supported in login.defs. Remove the ENCRYPTMETHOD_SELECT
preprocessor condition.
* libmisc/obscure.c, libmisc/salt.c, src/newusers.c,
src/chpasswd.c, src/chgpasswd.c, src/passwd.c: Disable SHA256 and
SHA512 if USE_SHA_CRYPT is not defined (this corresponds to a
subset of the ENCRYPTMETHOD_SELECT sections).
2007-11-24 18:38:08 +05:30
|
|
|
#ifdef USE_SHA_CRYPT
|
2008-05-24 18:38:58 +05:30
|
|
|
} else if (0 == strcmp (method, "SHA256")) {
|
2007-11-20 15:03:52 +05:30
|
|
|
MAGNUM(result, '5');
|
2021-06-15 02:58:28 +05:30
|
|
|
salt_len = SHA_CRYPT_SALT_SIZE;
|
|
|
|
SHA_salt_rounds_to_buf (result, (int *) arg);
|
2008-05-24 18:38:58 +05:30
|
|
|
} else if (0 == strcmp (method, "SHA512")) {
|
2007-11-20 15:03:52 +05:30
|
|
|
MAGNUM(result, '6');
|
2021-06-15 02:58:28 +05:30
|
|
|
salt_len = SHA_CRYPT_SALT_SIZE;
|
|
|
|
SHA_salt_rounds_to_buf (result, (int *) arg);
|
2008-05-20 02:26:48 +05:30
|
|
|
#endif /* USE_SHA_CRYPT */
|
2007-11-21 01:30:16 +05:30
|
|
|
} else if (0 != strcmp (method, "DES")) {
|
2021-05-09 04:12:14 +05:30
|
|
|
fprintf (shadow_logfd,
|
2007-11-20 15:03:52 +05:30
|
|
|
_("Invalid ENCRYPT_METHOD value: '%s'.\n"
|
|
|
|
"Defaulting to DES.\n"),
|
|
|
|
method);
|
2021-06-15 02:58:28 +05:30
|
|
|
salt_len = MAX_SALT_SIZE;
|
|
|
|
memset (result, '\0', GENSALT_SETTING_SIZE);
|
2007-11-20 03:44:19 +05:30
|
|
|
}
|
2007-11-20 05:35:54 +05:30
|
|
|
|
2021-06-15 02:58:28 +05:30
|
|
|
/* Check if the result buffer is long enough. */
|
|
|
|
assert (GENSALT_SETTING_SIZE > strlen (result) + salt_len);
|
|
|
|
|
|
|
|
/* Concatenate a pseudo random salt. */
|
|
|
|
strncat (result, gensalt (salt_len),
|
|
|
|
GENSALT_SETTING_SIZE - strlen (result) - 1);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|