Commit 89d73b20 authored by Côme Chilliet's avatar Côme Chilliet

🚑 fix(core) Use only random_int for pseudo-random int generation

For PHP<7.0, we fall back on openssl_random_pseudo_bytes from openssl module.

issue #5843
parent bcb10352
......@@ -228,9 +228,8 @@ class standAlonePage {
$base = 'ABCDEFGHKLMNOPQRSTWXYZabcdefghjkmnpqrstwxyz123456789';
$max = strlen($base) - 1;
$randomhash = '';
mt_srand((double) microtime() * 1000000);
while (strlen($randomhash) < $len + 1) {
$randomhash .= $base{mt_rand(0, $max)};
$randomhash .= $base{random_int(0, $max)};
}
return $randomhash;
}
......
......@@ -312,7 +312,7 @@ class templateHandling
$length = 8;
$chars = 'b';
if (count($args) >= 2) {
$length = mt_rand($args[0], $args[1]);
$length = random_int($args[0], $args[1]);
if (count($args) >= 3) {
$chars = $args[2];
}
......@@ -324,11 +324,11 @@ class templateHandling
switch ($chars) {
case 'd':
/* digits */
$res .= (string)rand(0, 9);
$res .= (string)random_int(0, 9);
break;
case 'l':
/* letters */
$nb = mt_rand(65, 116);
$nb = random_int(65, 116);
if ($nb > 90) {
/* lowercase */
$nb += 6;
......@@ -338,7 +338,7 @@ class templateHandling
case 'b':
/* both */
default:
$nb = mt_rand(65, 126);
$nb = random_int(65, 126);
if ($nb > 116) {
/* digit */
$nb = (string)($nb - 117);
......
......@@ -175,25 +175,6 @@ function load_plist ($ldap_available = TRUE)
return session::global_get('plist');
}
/*!
* \brief Create seed with microseconds
*
* Example:
* \code
* srand(make_seed());
* $random = rand();
* \endcode
*
* \return float a floating point number which can be used to feed srand() with it
*/
function make_seed()
{
list($usec, $sec) = explode(' ', microtime());
return (float) $sec + ((float) $usec * 100000);
}
/*!
* \brief Debug level action
*
......@@ -1440,8 +1421,7 @@ function gen_uids($rule, array $attributes)
$size = preg_replace('/^.*{id#(\d+)}.*$/', '\\1', $uid);
while (TRUE) {
mt_srand((double)microtime() * 1000000);
$number = sprintf("%0".$size."d", mt_rand(0, (10 ** $size) - 1));
$number = sprintf("%0".$size."d", random_int(0, (10 ** $size) - 1));
$res = preg_replace('/{id#(\d+)}/', $number, $uid);
$ldap->search('(uid='.ldap_escape_f(preg_replace('/[{}]/', '', $res)).')', array('dn'));
if ($ldap->count() == 0) {
......@@ -2324,6 +2304,35 @@ function load_all_classes()
}
}
if (!function_exists('random_int')) {
// PHP<7, we fallback on openssl_random_pseudo_bytes
function random_int($min, $max)
{
$range = $max - $min;
if ($range <= 0) {
return $min;
Please register or sign in to reply
}
$log = log($range, 2);
// length in bytes
$nbBytes = (int) ($log / 8) + 1;
// length in bits
$nbBits = (int) $log + 1;
// set all lower bits to 1
$filter = (int) (1 << $nbBits) - 1;
do {
$randomBytes = openssl_random_pseudo_bytes($nbBytes, $strong);
if (!$strong || ($randomBytes === FALSE)) {
throw new Exception('Failed to get random bytes');
  • Define and throw a dedicated exception instead of using a generic one. 📘

Please register or sign in to reply
}
$rnd = unpack('C', $randomBytes)[1];
  • C returns only 1 Byte, so this random_int() implementation always returns an int between 0 and 255. You should do an unpack('Q', $randomBytes)[1].

  • Thanks

Please register or sign in to reply
// discard irrelevant bits
$rnd = $rnd & $filter;
} while ($rnd >= $range);
return $min + $rnd;
}
}
function ldap_escape_f($str, $ignore = '')
{
return ldap_escape($str, $ignore, LDAP_ESCAPE_FILTER);
......
......@@ -55,8 +55,7 @@ class passwordMethodsmd5 extends passwordMethod
*/
function generate_hash($pwd)
{
mt_srand(microtime() * 10000000);
$salt0 = substr(pack('h*', md5(mt_rand())), 0, 8);
$salt0 = substr(pack('h*', md5(random_int(0, PHP_INT_MAX))), 0, 8);
$salt = substr(pack('H*', md5($salt0 . $pwd)), 0, 4);
return '{SMD5}'.base64_encode(pack('H*', md5($pwd . $salt)) . $salt);
}
......
......@@ -56,11 +56,11 @@ class passwordMethodssha extends passwordMethod
function generate_hash($pwd)
{
if (function_exists('sha1')) {
$salt = substr(pack('h*', md5(mt_rand())), 0, 8);
$salt = substr(pack('h*', md5(random_int(0, PHP_INT_MAX))), 0, 8);
$salt = substr(pack('H*', sha1($salt.$pwd)), 0, 4);
$pwd = '{SSHA}'.base64_encode(pack('H*', sha1($pwd.$salt)).$salt);
} elseif (function_exists('mhash')) {
$salt = mhash_keygen_s2k(MHASH_SHA1, $pwd, substr(pack('h*', md5(mt_rand())), 0, 8), 4);
$salt = mhash_keygen_s2k(MHASH_SHA1, $pwd, substr(pack('h*', md5(random_int(0, PHP_INT_MAX))), 0, 8), 4);
$pwd = '{SSHA}'.base64_encode(mhash(MHASH_SHA1, $pwd.$salt).$salt);
} else {
msg_dialog::display(_('Configuration error'), msgPool::missingext('mhash'), ERROR_DIALOG);
......
......@@ -352,8 +352,7 @@ class ImageAttribute extends FileAttribute
$this->setValue($this->inputValue($this->getValue()));
$id = $this->getHtmlId();
// Just to be sure the image is not cached
srand((double)microtime() * 1000000);
$key = $this->getLdapName().rand(0, 10000);
$key = $this->getLdapName().random_int(0, 10000);
$display = '<img id="'.$id.'_img"'.
($this->disabled ? 'disabled="disabled"' : '').
' src="getbin.php?key='.$key.'"'.
......
......@@ -95,6 +95,14 @@ class setupStepChecks extends setupStep
$M = TRUE;
$basic_checks[] = array('NAME' => $N , 'DESC' => $D , 'RESULT' => $R , 'SOLUTION' => $S , 'MUST' => $M );
/* Pseudo-random check */
$N = _('Checking cryptographically secure pseudo-random integers');
$D = _('You must use PHP>=7 or have openssl module activated so that FusionDirectory can generate cryptographically secure pseudo-random integers.');
$S = _('Please upgrade to PHP7 or activate openssl module.');
$R = (is_callable('random_int') || is_callable('openssl_random_pseudo_bytes'));
$M = TRUE;
$basic_checks[] = array('NAME' => $N , 'DESC' => $D , 'RESULT' => $R , 'SOLUTION' => $S , 'MUST' => $M );
/* Check for json support */
$N = msgPool::checkingFor('json');
$D = _('FusionDirectory requires this module to encode variables for javascript use.');
......
......@@ -471,7 +471,7 @@ class setupStepMigrate extends setupStep
$ldap = $config->get_ldap_link();
/* Create dummy entry */
$name = 'GOsa_setup_text_entry_'.session_id().rand(0, 999999);
$name = 'GOsa_setup_text_entry_'.session_id().random_int(0, 999999);
$dn = 'ou='.$name.','.$config->current['BASE'];
$testEntry = array();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment