/wp-includes/random_compat/random.php

  1. <?php 
  2. /** 
  3. * Random_* Compatibility Library 
  4. * for using the new PHP 7 random_* API in PHP 5 projects 
  5. * 
  6. * @version 1.2.1 
  7. * @released 2016-02-29 
  8. * 
  9. * The MIT License (MIT) 
  10. * 
  11. * Copyright (c) 2015 Paragon Initiative Enterprises 
  12. * 
  13. * Permission is hereby granted, free of charge, to any person obtaining a copy 
  14. * of this software and associated documentation files (the "Software"), to deal 
  15. * in the Software without restriction, including without limitation the rights 
  16. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
  17. * copies of the Software, and to permit persons to whom the Software is 
  18. * furnished to do so, subject to the following conditions: 
  19. * 
  20. * The above copyright notice and this permission notice shall be included in 
  21. * all copies or substantial portions of the Software. 
  22. * 
  23. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
  24. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
  25. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
  26. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
  27. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  
  28. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
  29. * SOFTWARE. 
  30. */ 
  31.  
  32. if (!defined('PHP_VERSION_ID')) { 
  33. // This constant was introduced in PHP 5.2.7 
  34. $RandomCompatversion = explode('.', PHP_VERSION); 
  35. define( 
  36. 'PHP_VERSION_ID',  
  37. $RandomCompatversion[0] * 10000 
  38. + $RandomCompatversion[1] * 100 
  39. + $RandomCompatversion[2] 
  40. ); 
  41. $RandomCompatversion = null; 
  42.  
  43. if (PHP_VERSION_ID < 70000) { 
  44.  
  45. if (!defined('RANDOM_COMPAT_READ_BUFFER')) { 
  46. define('RANDOM_COMPAT_READ_BUFFER', 8); 
  47.  
  48. $RandomCompatDIR = dirname(__FILE__); 
  49.  
  50. require_once $RandomCompatDIR.'/byte_safe_strings.php'; 
  51. require_once $RandomCompatDIR.'/cast_to_int.php'; 
  52. require_once $RandomCompatDIR.'/error_polyfill.php'; 
  53.  
  54. if (!function_exists('random_bytes')) { 
  55. /** 
  56. * PHP 5.2.0 - 5.6.x way to implement random_bytes() 
  57. * 
  58. * We use conditional statements here to define the function in accordance 
  59. * to the operating environment. It's a micro-optimization. 
  60. * 
  61. * In order of preference: 
  62. * 1. Use libsodium if available. 
  63. * 2. fread() /dev/urandom if available (never on Windows) 
  64. * 3. mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM) 
  65. * 4. COM('CAPICOM.Utilities.1')->GetRandom() 
  66. * 5. openssl_random_pseudo_bytes() (absolute last resort) 
  67. * 
  68. * See ERRATA.md for our reasoning behind this particular order 
  69. */ 
  70. if (extension_loaded('libsodium')) { 
  71. // See random_bytes_libsodium.php 
  72. if (PHP_VERSION_ID >= 50300 && function_exists('\\Sodium\\randombytes_buf')) { 
  73. require_once $RandomCompatDIR.'/random_bytes_libsodium.php'; 
  74. } elseif (method_exists('Sodium', 'randombytes_buf')) { 
  75. require_once $RandomCompatDIR.'/random_bytes_libsodium_legacy.php'; 
  76.  
  77. /** 
  78. * Reading directly from /dev/urandom: 
  79. */ 
  80. if (DIRECTORY_SEPARATOR === '/') { 
  81. // DIRECTORY_SEPARATOR === '/' on Unix-like OSes -- this is a fast 
  82. // way to exclude Windows. 
  83. $RandomCompatUrandom = true; 
  84. $RandomCompat_basedir = ini_get('open_basedir'); 
  85.  
  86. if (!empty($RandomCompat_basedir)) { 
  87. $RandomCompat_open_basedir = explode( 
  88. PATH_SEPARATOR,  
  89. strtolower($RandomCompat_basedir) 
  90. ); 
  91. $RandomCompatUrandom = in_array( 
  92. '/dev',  
  93. $RandomCompat_open_basedir 
  94. ); 
  95. $RandomCompat_open_basedir = null; 
  96.  
  97. if ( 
  98. !function_exists('random_bytes') 
  99. && 
  100. $RandomCompatUrandom 
  101. && 
  102. @is_readable('/dev/urandom') 
  103. ) { 
  104. // Error suppression on is_readable() in case of an open_basedir 
  105. // or safe_mode failure. All we care about is whether or not we 
  106. // can read it at this point. If the PHP environment is going to 
  107. // panic over trying to see if the file can be read in the first 
  108. // place, that is not helpful to us here. 
  109.  
  110. // See random_bytes_dev_urandom.php 
  111. require_once $RandomCompatDIR.'/random_bytes_dev_urandom.php'; 
  112. // Unset variables after use 
  113. $RandomCompat_basedir = null; 
  114. $RandomCompatUrandom = null; 
  115.  
  116. /** 
  117. * mcrypt_create_iv() 
  118. */ 
  119. if ( 
  120. !function_exists('random_bytes') 
  121. && 
  122. PHP_VERSION_ID >= 50307 
  123. && 
  124. extension_loaded('mcrypt') 
  125. ) { 
  126. // Prevent this code from hanging indefinitely on non-Windows; 
  127. // see https://bugs.php.net/bug.php?id=69833 
  128. if ( 
  129. DIRECTORY_SEPARATOR !== '/' || 
  130. (PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613) 
  131. ) { 
  132. // See random_bytes_mcrypt.php 
  133. require_once $RandomCompatDIR.'/random_bytes_mcrypt.php'; 
  134.  
  135. if ( 
  136. !function_exists('random_bytes') 
  137. && 
  138. extension_loaded('com_dotnet') 
  139. && 
  140. class_exists('COM') 
  141. ) { 
  142. $RandomCompat_disabled_classes = preg_split( 
  143. '#\s*, \s*#',  
  144. strtolower(ini_get('disable_classes')) 
  145. ); 
  146.  
  147. if (!in_array('com', $RandomCompat_disabled_classes)) { 
  148. try { 
  149. $RandomCompatCOMtest = new COM('CAPICOM.Utilities.1'); 
  150. if (method_exists($RandomCompatCOMtest, 'GetRandom')) { 
  151. // See random_bytes_com_dotnet.php 
  152. require_once $RandomCompatDIR.'/random_bytes_com_dotnet.php'; 
  153. } catch (com_exception $e) { 
  154. // Don't try to use it. 
  155. $RandomCompat_disabled_classes = null; 
  156. $RandomCompatCOMtest = null; 
  157.  
  158. /** 
  159. * openssl_random_pseudo_bytes() 
  160. */ 
  161. if ( 
  162. // Unix-like with PHP >= 5.3.0 or 
  163. DIRECTORY_SEPARATOR === '/' 
  164. && 
  165. PHP_VERSION_ID >= 50300 
  166. || 
  167. // Windows with PHP >= 5.4.1 
  168. PHP_VERSION_ID >= 50401 
  169. && 
  170. !function_exists('random_bytes') 
  171. && 
  172. extension_loaded('openssl') 
  173. ) { 
  174. // See random_bytes_openssl.php 
  175. require_once $RandomCompatDIR.'/random_bytes_openssl.php'; 
  176.  
  177. /** 
  178. * throw new Exception 
  179. */ 
  180. if (!function_exists('random_bytes')) { 
  181. /** 
  182. * We don't have any more options, so let's throw an exception right now 
  183. * and hope the developer won't let it fail silently. 
  184. */ 
  185. function random_bytes($length) 
  186. throw new Exception( 
  187. 'There is no suitable CSPRNG installed on your system' 
  188. ); 
  189.  
  190. if (!function_exists('random_int')) { 
  191. require_once $RandomCompatDIR.'/random_int.php'; 
  192.  
  193. $RandomCompatDIR = null; 
.