Hello, On Wed, Jun 13, 2012 at 02:16:56PM +0300, Alexander Gattin wrote: > > Probably, we should use RAND_MAX on GNU (both > Linux and Hurd), and 0x7fffffff on all other > systems?
Lets just assume we cannot assume anything. random() is used to compute the size of salt and number of rounds for SHA encrypted passwords. I introduced a RANDOM_MAX set to 0x7FFFFFFF (this seems to be valid for all the mentioned systems anyway) If random() returns an higher value, I will use the biggest salt or max number of rounds. If random() has a lower max value, I will favor higher numbers by counting down from the max value instead of adding to the min value. This will be a flawed random, but will favor the biggest salt with the highest number of rounds (i.e. when the rainbow tables will be the most difficult to compute). I applied the attached patch. Does it sounds OK to both of you? Best Regards, -- Nekral
diff --git a/ChangeLog b/ChangeLog index 7d0cd6e..0b20387 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2013-08-05 Nicolas François <nicolas.franc...@centraliens.net> + + * libmisc/salt.c: random() max value is 2^31-1 (same as RAND_MAX + on GNU). As it is not clear whether on some systems the max value + can exceed this number and whether some systems have max values + which would be lower, we take this into account when defining the + salt size and number of rounds for SHA encrypted passwords. Higher + values are favored. + 2013-08-04 Nicolas François <nicolas.franc...@centraliens.net> * man/su.1.xml: With getopt, '-' does not need to be the last diff --git a/libmisc/salt.c b/libmisc/salt.c index 174f554..d88f998 100644 --- a/libmisc/salt.c +++ b/libmisc/salt.c @@ -23,7 +23,7 @@ static void seedRNG (void); static /*@observer@*/const char *gensalt (size_t salt_size); #ifdef USE_SHA_CRYPT -static size_t SHA_salt_size (void); +static size_t shadow_random (size_t min, size_t max); static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds); #endif /* USE_SHA_CRYPT */ @@ -81,17 +81,29 @@ static void seedRNG (void) #define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0' #ifdef USE_SHA_CRYPT +/* It is not clear what is the maximum value of random(). + * We assume 2^31-1.*/ +#define RANDOM_MAX 0x7FFFFFFF + /* - * Return the salt size. - * The size of the salt string is between 8 and 16 bytes for the SHA crypt - * methods. + * Return a random number between min and max (both included). + * + * It favors slightly the higher numbers. */ -static size_t SHA_salt_size (void) +static size_t shadow_random (size_t min, size_t max) { - double rand_size; + double drand; + size_t ret; seedRNG (); - rand_size = (double) 9.0 * random () / RAND_MAX; - return (size_t) (8 + rand_size); + drand = (double) (max - min + 1) * random () / RANDOM_MAX; + /* On systems were this is not random() range is lower, we favor + * higher numbers of salt. */ + ret = (size_t) (max + 1 - drand); + /* And we catch limits, and use the highest number */ + if ((ret < min) || (ret > max)) { + ret = max; + } + return ret; } /* Default number of rounds if not explicitly specified. */ @@ -130,10 +142,7 @@ static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds max_rounds = min_rounds; } - seedRNG (); - rand_rounds = (double) (max_rounds-min_rounds+1.0) * random (); - rand_rounds /= RAND_MAX; - rounds = min_rounds + rand_rounds; + rounds = shadow_random (min_rounds, max_rounds); } else if (0 == *prefered_rounds) { return ""; } else { @@ -226,11 +235,11 @@ static /*@observer@*/const char *gensalt (size_t salt_size) } else if (0 == strcmp (method, "SHA256")) { MAGNUM(result, '5'); strcat(result, SHA_salt_rounds((int *)arg)); - salt_len = SHA_salt_size(); + salt_len = shadow_random (8, 16); } else if (0 == strcmp (method, "SHA512")) { MAGNUM(result, '6'); strcat(result, SHA_salt_rounds((int *)arg)); - salt_len = SHA_salt_size(); + salt_len = shadow_random (8, 16); #endif /* USE_SHA_CRYPT */ } else if (0 != strcmp (method, "DES")) { fprintf (stderr,