summaryrefslogtreecommitdiff
path: root/inc
diff options
context:
space:
mode:
authorMichael Hamann <michael@content-space.de>2013-07-30 18:46:02 +0200
committerChristopher Smith <chris@jalakai.co.uk>2013-08-01 11:11:51 +0200
commitb40098c3d8f4a41b62694ccd1e660c26301d6df0 (patch)
tree45e56c823124a73688f2061947469d1029079ad3 /inc
parentf2bbf30b71b15efa7a918944b4ffc74f8b1747a9 (diff)
downloadrpg-b40098c3d8f4a41b62694ccd1e660c26301d6df0.tar.gz
rpg-b40098c3d8f4a41b62694ccd1e660c26301d6df0.tar.bz2
Add truly random numbers and use them in places where randomness matters
Diffstat (limited to 'inc')
-rw-r--r--inc/PassHash.class.php2
-rw-r--r--inc/auth.php108
2 files changed, 103 insertions, 7 deletions
diff --git a/inc/PassHash.class.php b/inc/PassHash.class.php
index 61bd74939..607661a22 100644
--- a/inc/PassHash.class.php
+++ b/inc/PassHash.class.php
@@ -98,7 +98,7 @@ class PassHash {
$salt = '';
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
for($i = 0; $i < $len; $i++) {
- $salt .= $chars[mt_rand(0, 61)];
+ $salt .= $chars[auth_random(0, 61)];
}
return $salt;
}
diff --git a/inc/auth.php b/inc/auth.php
index 47b29eff7..e840ef6d7 100644
--- a/inc/auth.php
+++ b/inc/auth.php
@@ -294,7 +294,7 @@ function auth_validateToken($token) {
* @return string The auth token
*/
function auth_createToken() {
- $token = md5(mt_rand());
+ $token = md5(auth_randombytes(16));
@session_start(); // reopen the session if needed
$_SESSION[DOKU_COOKIE]['auth']['token'] = $token;
session_write_close();
@@ -350,6 +350,102 @@ function auth_cookiesalt($addsession = false) {
}
/**
+ * Return truly (pseudo) random bytes if available, otherwise fall back to mt_rand
+ *
+ * @author Mark Seecof
+ * @author Michael Hamann <michael@content-space.de>
+ * @link http://www.php.net/manual/de/function.mt-rand.php#83655
+ * @param int $length number of bytes to get
+ * @throws Exception when no usable random generator is found
+ * @return string binary random strings
+ */
+function auth_randombytes($length) {
+ $strong = false;
+ $rbytes = false;
+
+ if (function_exists('openssl_random_pseudo_bytes')
+ && (version_compare(PHP_VERSION, '5.3.4') >= 0
+ || strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')
+ ) {
+ $rbytes = openssl_random_pseudo_bytes($length, $strong);
+ }
+
+ if (!$strong && function_exists('mcrypt_create_iv')
+ && (version_compare(PHP_VERSION, '5.3.7') >= 0
+ || strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')
+ ) {
+ $rbytes = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
+ if ($rbytes !== false && strlen($rbytes) === $length) {
+ $strong = true;
+ }
+ }
+
+
+ // If no strong randoms available, try OS the specific ways
+ if(!$strong) {
+ // Unix/Linux platform
+ $fp = @fopen('/dev/urandom', 'rb');
+ if($fp !== false) {
+ $rbytes = fread($fp, $length);
+ fclose($fp);
+ }
+
+ // MS-Windows platform
+ if(class_exists('COM')) {
+ // http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx
+ try {
+ $CAPI_Util = new COM('CAPICOM.Utilities.1');
+ $rbytes = $CAPI_Util->GetRandom($length, 0);
+
+ // if we ask for binary data PHP munges it, so we
+ // request base64 return value.
+ if($rbytes) $rbytes = base64_decode($rbytes);
+ } catch(Exception $ex) {
+ // fail
+ }
+ }
+ }
+ if(strlen($rbytes) < $length) $rbytes = false;
+
+ // still no random bytes available - fall back to mt_rand()
+ if($rbytes === false) {
+ $rbytes = '';
+ for ($i = 0; $i < $length; ++$i) {
+ $rbytes .= chr(mt_rand(0, 255));
+ }
+ }
+
+ return $rbytes;
+}
+
+/**
+ * Random number generator using the best available source
+ *
+ * @author Michael Samuel
+ * @author Michael Hamann <michael@content-space.de>
+ * @param int $min
+ * @param int $max
+ * @return int
+ */
+function auth_random($min, $max) {
+ $abs_max = $max - $min;
+
+ $nbits = 0;
+ for ($n = $abs_max; $n > 0; $n >>= 1) {
+ ++$nbits;
+ }
+
+ $mask = (1 << $nbits) - 1;
+ do {
+ $bytes = auth_randombytes(PHP_INT_SIZE);
+ $integers = unpack('Inum', $bytes);
+ $integer = $integers["num"] & $mask;
+ } while ($integer > $abs_max);
+
+ return $min + $integer;
+}
+
+/**
* Log out the current user
*
* This clears all authentication data and thus log the user
@@ -703,12 +799,12 @@ function auth_pwgen($foruser = '') {
//use thre syllables...
for($i = 0; $i < 3; $i++) {
- $data['password'] .= $c[mt_rand(0, strlen($c) - 1)];
- $data['password'] .= $v[mt_rand(0, strlen($v) - 1)];
- $data['password'] .= $a[mt_rand(0, strlen($a) - 1)];
+ $data['password'] .= $c[auth_random(0, strlen($c) - 1)];
+ $data['password'] .= $v[auth_random(0, strlen($v) - 1)];
+ $data['password'] .= $a[auth_random(0, strlen($a) - 1)];
}
//... and add a nice number and special
- $data['password'] .= mt_rand(10, 99).$s[mt_rand(0, strlen($s) - 1)];
+ $data['password'] .= auth_random(10, 99).$s[auth_random(0, strlen($s) - 1)];
}
$evt->advise_after();
@@ -1007,7 +1103,7 @@ function act_resendpwd() {
}
// generate auth token
- $token = md5(uniqid(mt_rand(), true)); // random secret
+ $token = md5(auth_randombytes(16)); // random secret
$tfile = $conf['cachedir'].'/'.$token{0}.'/'.$token.'.pwauth';
$url = wl('', array('do'=> 'resendpwd', 'pwauth'=> $token), true, '&');