WordPress 4.5
[autoinstalls/wordpress.git] / 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
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 }