wp/wp-includes/random_compat/random.php
changeset 7 cf61fcea0001
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
       
     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 
       
    44 if (PHP_VERSION_ID < 70000) {
       
    45 
       
    46     if (!defined('RANDOM_COMPAT_READ_BUFFER')) {
       
    47         define('RANDOM_COMPAT_READ_BUFFER', 8);
       
    48     }
       
    49 
       
    50     $RandomCompatDIR = dirname(__FILE__);
       
    51 
       
    52     require_once $RandomCompatDIR.'/byte_safe_strings.php';
       
    53     require_once $RandomCompatDIR.'/cast_to_int.php';
       
    54     require_once $RandomCompatDIR.'/error_polyfill.php';
       
    55 
       
    56     if (!function_exists('random_bytes')) {
       
    57         /**
       
    58          * PHP 5.2.0 - 5.6.x way to implement random_bytes()
       
    59          *
       
    60          * We use conditional statements here to define the function in accordance
       
    61          * to the operating environment. It's a micro-optimization.
       
    62          *
       
    63          * In order of preference:
       
    64          *   1. Use libsodium if available.
       
    65          *   2. fread() /dev/urandom if available (never on Windows)
       
    66          *   3. mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM)
       
    67          *   4. COM('CAPICOM.Utilities.1')->GetRandom()
       
    68          *   5. openssl_random_pseudo_bytes() (absolute last resort)
       
    69          *
       
    70          * See ERRATA.md for our reasoning behind this particular order
       
    71          */
       
    72         if (extension_loaded('libsodium')) {
       
    73             // See random_bytes_libsodium.php
       
    74             if (PHP_VERSION_ID >= 50300 && function_exists('\\Sodium\\randombytes_buf')) {
       
    75                 require_once $RandomCompatDIR.'/random_bytes_libsodium.php';
       
    76             } elseif (method_exists('Sodium', 'randombytes_buf')) {
       
    77                 require_once $RandomCompatDIR.'/random_bytes_libsodium_legacy.php';
       
    78             }
       
    79         }
       
    80 
       
    81         /**
       
    82          * Reading directly from /dev/urandom:
       
    83          */
       
    84         if (DIRECTORY_SEPARATOR === '/') {
       
    85             // DIRECTORY_SEPARATOR === '/' on Unix-like OSes -- this is a fast
       
    86             // way to exclude Windows.
       
    87             $RandomCompatUrandom = true;
       
    88             $RandomCompat_basedir = ini_get('open_basedir');
       
    89 
       
    90             if (!empty($RandomCompat_basedir)) {
       
    91                 $RandomCompat_open_basedir = explode(
       
    92                     PATH_SEPARATOR,
       
    93                     strtolower($RandomCompat_basedir)
       
    94                 );
       
    95                 $RandomCompatUrandom = in_array(
       
    96                     '/dev',
       
    97                     $RandomCompat_open_basedir
       
    98                 );
       
    99                 $RandomCompat_open_basedir = null;
       
   100             }
       
   101 
       
   102             if (
       
   103                 !function_exists('random_bytes')
       
   104                 &&
       
   105                 $RandomCompatUrandom
       
   106                 &&
       
   107                 @is_readable('/dev/urandom')
       
   108             ) {
       
   109                 // Error suppression on is_readable() in case of an open_basedir
       
   110                 // or safe_mode failure. All we care about is whether or not we
       
   111                 // can read it at this point. If the PHP environment is going to
       
   112                 // panic over trying to see if the file can be read in the first
       
   113                 // place, that is not helpful to us here.
       
   114 
       
   115                 // See random_bytes_dev_urandom.php
       
   116                 require_once $RandomCompatDIR.'/random_bytes_dev_urandom.php';
       
   117             }
       
   118             // Unset variables after use
       
   119             $RandomCompat_basedir = null;
       
   120             $RandomCompatUrandom = null;
       
   121         }
       
   122 
       
   123         /**
       
   124          * mcrypt_create_iv()
       
   125          */
       
   126         if (
       
   127             !function_exists('random_bytes')
       
   128             &&
       
   129             PHP_VERSION_ID >= 50307
       
   130             &&
       
   131             extension_loaded('mcrypt')
       
   132         ) {
       
   133             // Prevent this code from hanging indefinitely on non-Windows;
       
   134             // see https://bugs.php.net/bug.php?id=69833
       
   135             if (
       
   136                 DIRECTORY_SEPARATOR !== '/' ||
       
   137                 (PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613)
       
   138             ) {
       
   139                 // See random_bytes_mcrypt.php
       
   140                 require_once $RandomCompatDIR.'/random_bytes_mcrypt.php';
       
   141             }
       
   142         }
       
   143 
       
   144         if (
       
   145             !function_exists('random_bytes')
       
   146             &&
       
   147             extension_loaded('com_dotnet')
       
   148             &&
       
   149             class_exists('COM')
       
   150         ) {
       
   151             $RandomCompat_disabled_classes = preg_split(
       
   152                 '#\s*,\s*#',
       
   153                 strtolower(ini_get('disable_classes'))
       
   154             );
       
   155 
       
   156             if (!in_array('com', $RandomCompat_disabled_classes)) {
       
   157                 try {
       
   158                     $RandomCompatCOMtest = new COM('CAPICOM.Utilities.1');
       
   159                     if (method_exists($RandomCompatCOMtest, 'GetRandom')) {
       
   160                         // See random_bytes_com_dotnet.php
       
   161                         require_once $RandomCompatDIR.'/random_bytes_com_dotnet.php';
       
   162                     }
       
   163                 } catch (com_exception $e) {
       
   164                     // Don't try to use it.
       
   165                 }
       
   166             }
       
   167             $RandomCompat_disabled_classes = null;
       
   168             $RandomCompatCOMtest = null;
       
   169         }
       
   170 
       
   171         /**
       
   172          * openssl_random_pseudo_bytes()
       
   173          */
       
   174         if (
       
   175             (
       
   176                 // Unix-like with PHP >= 5.3.0 or
       
   177                 (
       
   178                     DIRECTORY_SEPARATOR === '/'
       
   179                     &&
       
   180                     PHP_VERSION_ID >= 50300
       
   181                 )
       
   182                 ||
       
   183                 // Windows with PHP >= 5.4.1
       
   184                 PHP_VERSION_ID >= 50401
       
   185             )
       
   186             &&
       
   187             !function_exists('random_bytes')
       
   188             &&
       
   189             extension_loaded('openssl')
       
   190         ) {
       
   191             // See random_bytes_openssl.php
       
   192             require_once $RandomCompatDIR.'/random_bytes_openssl.php';
       
   193         }
       
   194 
       
   195         /**
       
   196          * throw new Exception
       
   197          */
       
   198         if (!function_exists('random_bytes')) {
       
   199             /**
       
   200              * We don't have any more options, so let's throw an exception right now
       
   201              * and hope the developer won't let it fail silently.
       
   202              */
       
   203             function random_bytes($length)
       
   204             {
       
   205                 throw new Exception(
       
   206                     'There is no suitable CSPRNG installed on your system'
       
   207                 );
       
   208             }
       
   209         }
       
   210     }
       
   211 
       
   212     if (!function_exists('random_int')) {
       
   213         require_once $RandomCompatDIR.'/random_int.php';
       
   214     }
       
   215 
       
   216     $RandomCompatDIR = null;
       
   217 }