[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/random_compat/ -> random.php (source)

   1  <?php
   2  /**
   3   * Random_* Compatibility Library
   4   * for using the new PHP 7 random_* API in PHP 5 projects
   5   *
   6   * @version 2.0.17
   7   * @released 2018-07-04
   8   *
   9   * The MIT License (MIT)
  10   *
  11   * Copyright (c) 2015 - 2018 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 = array_map('intval', 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  
  44  /**
  45   * PHP 7.0.0 and newer have these functions natively.
  46   */
  47  if (PHP_VERSION_ID >= 70000) {
  48      return;
  49  }
  50  
  51  if (!defined('RANDOM_COMPAT_READ_BUFFER')) {
  52      define('RANDOM_COMPAT_READ_BUFFER', 8);
  53  }
  54  
  55  $RandomCompatDIR = dirname(__FILE__);
  56  
  57  require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'byte_safe_strings.php';
  58  require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'cast_to_int.php';
  59  require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'error_polyfill.php';
  60  
  61  if (!is_callable('random_bytes')) {
  62      /**
  63       * PHP 5.2.0 - 5.6.x way to implement random_bytes()
  64       *
  65       * We use conditional statements here to define the function in accordance
  66       * to the operating environment. It's a micro-optimization.
  67       *
  68       * In order of preference:
  69       *   1. Use libsodium if available.
  70       *   2. fread() /dev/urandom if available (never on Windows)
  71       *   3. mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM)
  72       *   4. COM('CAPICOM.Utilities.1')->GetRandom()
  73       *
  74       * See RATIONALE.md for our reasoning behind this particular order
  75       */
  76      if (extension_loaded('libsodium')) {
  77          // See random_bytes_libsodium.php
  78          if (PHP_VERSION_ID >= 50300 && is_callable('\\Sodium\\randombytes_buf')) {
  79              require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_bytes_libsodium.php';
  80          } elseif (method_exists('Sodium', 'randombytes_buf')) {
  81              require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_bytes_libsodium_legacy.php';
  82          }
  83      }
  84  
  85      /**
  86       * Reading directly from /dev/urandom:
  87       */
  88      if (DIRECTORY_SEPARATOR === '/') {
  89          // DIRECTORY_SEPARATOR === '/' on Unix-like OSes -- this is a fast
  90          // way to exclude Windows.
  91          $RandomCompatUrandom = true;
  92          $RandomCompat_basedir = ini_get('open_basedir');
  93  
  94          if (!empty($RandomCompat_basedir)) {
  95              $RandomCompat_open_basedir = explode(
  96                  PATH_SEPARATOR,
  97                  strtolower($RandomCompat_basedir)
  98              );
  99              $RandomCompatUrandom = (array() !== array_intersect(
 100                  array('/dev', '/dev/', '/dev/urandom'),
 101                  $RandomCompat_open_basedir
 102              ));
 103              $RandomCompat_open_basedir = null;
 104          }
 105  
 106          if (
 107              !is_callable('random_bytes')
 108              &&
 109              $RandomCompatUrandom
 110              &&
 111              @is_readable('/dev/urandom')
 112          ) {
 113              // Error suppression on is_readable() in case of an open_basedir
 114              // or safe_mode failure. All we care about is whether or not we
 115              // can read it at this point. If the PHP environment is going to
 116              // panic over trying to see if the file can be read in the first
 117              // place, that is not helpful to us here.
 118  
 119              // See random_bytes_dev_urandom.php
 120              require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_bytes_dev_urandom.php';
 121          }
 122          // Unset variables after use
 123          $RandomCompat_basedir = null;
 124      } else {
 125          $RandomCompatUrandom = false;
 126      }
 127  
 128      /**
 129       * mcrypt_create_iv()
 130       *
 131       * We only want to use mcypt_create_iv() if:
 132       *
 133       * - random_bytes() hasn't already been defined
 134       * - the mcrypt extensions is loaded
 135       * - One of these two conditions is true:
 136       *   - We're on Windows (DIRECTORY_SEPARATOR !== '/')
 137       *   - We're not on Windows and /dev/urandom is readabale
 138       *     (i.e. we're not in a chroot jail)
 139       * - Special case:
 140       *   - If we're not on Windows, but the PHP version is between
 141       *     5.6.10 and 5.6.12, we don't want to use mcrypt. It will
 142       *     hang indefinitely. This is bad.
 143       *   - If we're on Windows, we want to use PHP >= 5.3.7 or else
 144       *     we get insufficient entropy errors.
 145       */
 146      if (
 147          !is_callable('random_bytes')
 148          &&
 149          // Windows on PHP < 5.3.7 is broken, but non-Windows is not known to be.
 150          (DIRECTORY_SEPARATOR === '/' || PHP_VERSION_ID >= 50307)
 151          &&
 152          // Prevent this code from hanging indefinitely on non-Windows;
 153          // see https://bugs.php.net/bug.php?id=69833
 154          (
 155              DIRECTORY_SEPARATOR !== '/' ||
 156              (PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613)
 157          )
 158          &&
 159          extension_loaded('mcrypt')
 160      ) {
 161          // See random_bytes_mcrypt.php
 162          require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_bytes_mcrypt.php';
 163      }
 164      $RandomCompatUrandom = null;
 165  
 166      /**
 167       * This is a Windows-specific fallback, for when the mcrypt extension
 168       * isn't loaded.
 169       */
 170      if (
 171          !is_callable('random_bytes')
 172          &&
 173          extension_loaded('com_dotnet')
 174          &&
 175          class_exists('COM')
 176      ) {
 177          $RandomCompat_disabled_classes = preg_split(
 178              '#\s*,\s*#',
 179              strtolower(ini_get('disable_classes'))
 180          );
 181  
 182          if (!in_array('com', $RandomCompat_disabled_classes)) {
 183              try {
 184                  $RandomCompatCOMtest = new COM('CAPICOM.Utilities.1');
 185                  /** @psalm-suppress TypeDoesNotContainType */
 186                  if (is_callable(array($RandomCompatCOMtest, 'GetRandom'))) {
 187                      // See random_bytes_com_dotnet.php
 188                      require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_bytes_com_dotnet.php';
 189                  }
 190              } catch (com_exception $e) {
 191                  // Don't try to use it.
 192              }
 193          }
 194          $RandomCompat_disabled_classes = null;
 195          $RandomCompatCOMtest = null;
 196      }
 197  
 198      /**
 199       * throw new Exception
 200       */
 201      if (!is_callable('random_bytes')) {
 202          /**
 203           * We don't have any more options, so let's throw an exception right now
 204           * and hope the developer won't let it fail silently.
 205           *
 206           * @param mixed $length
 207           * @psalm-suppress InvalidReturnType
 208           * @throws Exception
 209           * @return string
 210           */
 211          function random_bytes($length)
 212          {
 213              unset($length); // Suppress "variable not used" warnings.
 214              throw new Exception(
 215                  'There is no suitable CSPRNG installed on your system'
 216              );
 217              return '';
 218          }
 219      }
 220  }
 221  
 222  if (!is_callable('random_int')) {
 223      require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_int.php';
 224  }
 225  
 226  $RandomCompatDIR = null;


Generated: Sun Jul 9 01:00:02 2023 Cross-referenced by PHPXref 0.7.1