* libmisc/salt.c: The salt has a random size (between 8 and 16

bytes).
* lib/getdef.c, etc/login.defs: Add definitions for
  SHA_CRYPT_MIN_ROUNDS and SHA_CRYPT_MAX_ROUNDS.
* libmisc/salt.c: Use SHA_CRYPT_MIN_ROUNDS and SHA_CRYPT_MAX_ROUNDS
  to add a random number of rounds if needed.
This commit is contained in:
nekral-guest 2007-11-20 00:05:54 +00:00
parent c214b26ee6
commit e406b7fe4a
4 changed files with 113 additions and 10 deletions

View File

@ -1,3 +1,12 @@
2007-11-19 Nicolas François <nicolas.francois@centraliens.net>
* libmisc/salt.c: The salt has a random size (between 8 and 16
bytes).
* lib/getdef.c, etc/login.defs: Add definitions for
SHA_CRYPT_MIN_ROUNDS and SHA_CRYPT_MAX_ROUNDS.
* libmisc/salt.c: Use SHA_CRYPT_MIN_ROUNDS and SHA_CRYPT_MAX_ROUNDS
to add a random number of rounds if needed.
2007-11-19 Nicolas François <nicolas.francois@centraliens.net>
* libmisc/salt.c (MAGNUM): Terminate the array with nul (the array

View File

@ -288,6 +288,22 @@ CHFN_RESTRICT rwh
#
#ENCRYPT_METHOD DES
#
# Only works if ENCRYPT_METHOD is set to SHA256 or SHA512.
#
# Define the number of SHA rounds.
# With a lot of rounds, it is more difficult to brute forcing the password.
# But note also that it more CPU resources will be needed to authenticate
# users.
#
# If not specified, the libc will choose the default number of rounds (5000).
# The values must be inside the 1000-999999999 range.
# If only one of the MIN or MAX values is set, then this value will be used.
# If MIN > MAX, the highest value will be used.
#
# SHA_CRYPT_MIN_ROUNDS 5000
# SHA_CRYPT_MAX_ROUNDS 5000
#
# List of groups to add to the user's supplementary group set
# when logging in on the console (as determined by the CONSOLE

View File

@ -104,6 +104,8 @@ static struct itemdef def_table[] = {
{"PASS_MIN_LEN", NULL},
{"PORTTIME_CHECKS_ENAB", NULL},
{"QUOTAS_ENAB", NULL},
{"SHA_CRYPT_MAX_ROUNDS", NULL},
{"SHA_CRYPT_MIN_ROUNDS", NULL},
{"SU_WHEEL_ONLY", NULL},
{"ULIMIT", NULL},
#endif

View File

@ -53,19 +53,91 @@ char *l64a(long value)
#endif /* !HAVE_L64A */
/*
* 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.
* Add the salt prefix.
*/
#define MAGNUM(array,ch) (array)[0]= (array)[2] = '$',\
(array)[1]=(ch),\
(array)[2]='\0'
/*
* Return the salt size.
* The size of the salt string is between 8 and 16 bytes for the SHA crypt
* methods.
*/
static unsigned int SHA_salt_size (void)
{
return 8 + 8*rand ()/(RAND_MAX+1);
}
/* ! Arguments evaluated twice ! */
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define MIN(x,y) ((x) < (y) ? (x) : (y))
/* Default number of rounds if not explicitly specified. */
#define ROUNDS_DEFAULT 5000
/* Minimum number of rounds. */
#define ROUNDS_MIN 1000
/* Maximum number of rounds. */
#define ROUNDS_MAX 999999999
/*
* Return a salt prefix specifying the rounds number for the SHA crypt methods.
*/
static char *SHA_salt_rounds (void)
{
static char *rounds_prefix[18];
long min_rounds = getdef_long ("SHA_CRYPT_MIN_ROUNDS", -1);
long max_rounds = getdef_long ("SHA_CRYPT_MAX_ROUNDS", -1);
long rounds;
if (-1 == min_rounds && -1 == max_rounds)
return "";
if (-1 == min_rounds)
min_rounds = max_rounds;
if (-1 == max_rounds)
max_rounds = min_rounds;
if (min_rounds > max_rounds)
max_rounds = min_rounds;
rounds = min_rounds + (max_rounds - min_rounds)*rand ()/(RAND_MAX+1);
/* Sanity checks. The libc should also check this, but this
* protects against a rounds_prefix overflow. */
if (rounds < ROUNDS_MIN)
rounds = ROUNDS_MIN;
if (rounds > ROUNDS_MAX)
rounds = ROUNDS_MAX;
snprintf (rounds_prefix, 18, "rounds=%ld$", rounds);
/* Sanity checks. That should not be necessary. */
rounds_prefix[17] = '\0';
if ('$' != rounds_prefix[16])
rounds_prefix[17] = '$';
return rounds_prefix;
}
/*
* 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
*/
char *crypt_make_salt (void)
{
struct timeval tv;
/* Max result size for the SHA methods:
* +3 $5$
* +17 rounds=999999999$
* +16 salt
* +1 \0
*/
static char result[40];
int max_salt_len = 8;
char *method;
@ -87,10 +159,12 @@ char *crypt_make_salt (void)
max_salt_len = 11;
} else if (!strncmp (method, "SHA256", 6)) {
MAGNUM(result, '5');
max_salt_len = 11; /* XXX: should not be fixed */
strcat(result, SHA_salt_rounds());
max_salt_len = strlen(result) + SHA_salt_size();
} else if (!strncmp (method, "SHA512", 6)) {
MAGNUM(result, '6');
max_salt_len = 11; /* XXX: should not be fixed */
strcat(result, SHA_salt_rounds());
max_salt_len = strlen(result) + SHA_salt_size();
} else if (0 != strncmp (method, "DES", 3)) {
fprintf (stderr,
_("Invalid ENCRYPT_METHOD value: '%s'.\n"
@ -101,12 +175,14 @@ char *crypt_make_salt (void)
}
#endif /* ENCRYPTMETHOD_SELECT */
#endif /* USE_PAM */
/*
* Generate 8 chars of salt, the old crypt() will use only first 2.
* Concatenate a pseudo random salt.
*/
gettimeofday (&tv, (struct timezone *) 0);
strcat (result, l64a (tv.tv_usec));
strcat (result, l64a (tv.tv_sec + getpid () + clock ()));
strncat (result, sizeof(result), l64a (tv.tv_usec));
strncat (result, sizeof(result),
l64a (tv.tv_sec + getpid () + clock ()));
if (strlen (result) > max_salt_len) /* magic+salt */
result[max_salt_len] = '\0';