Package: release.debian.org Severity: normal Tags: jessie User: release.debian.org@packages.debian.org Usertags: pu Hi, As agreed with the security team, we’d like to fix CVE-2016-1902 via p-u. The patch is “a bit” bigger than usual (homemade implementation replaced by a proper embedded one), sorry about that. Thanks in advance for considering it. symfony (2.3.21+dfsg-4+deb8u3) jessie; urgency=medium [ Daniel Beyer ] * Backport a security fix from 2.3.37 - SecureRandom's fallback not secure when OpenSSL fails [CVE-2016-1902] [ David Prévot ] * Add copyright entry for embeded paragonie/random_compat Please note that the only component touch by this fix (php-symfony-security) has no (external) reverse dependencies in Jessie. Regards David
diff --git a/debian/changelog b/debian/changelog index f5a2743..5092e50 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,14 @@ +symfony (2.3.21+dfsg-4+deb8u3) jessie; urgency=medium + + [ Daniel Beyer ] + * Backport a security fix from 2.3.37 + - SecureRandom's fallback not secure when OpenSSL fails [CVE-2016-1902] + + [ David Prévot ] + * Add copyright entry for embeded paragonie/random_compat + + -- David Prévot <taffit@debian.org> Wed, 03 Feb 2016 19:44:47 -0400 + symfony (2.3.21+dfsg-4+deb8u2) jessie-security; urgency=high * Backport security fixes from 2.3.35 diff --git a/debian/copyright b/debian/copyright index 1bc9817..e71be14 100644 --- a/debian/copyright +++ b/debian/copyright @@ -6,6 +6,7 @@ Files-Excluded: src/Symfony/Component/Console/Resources/bin/hiddeninput.exe Files: * Copyright: 2004-2014 Fabien Potencier + 2015 Paragon Initiative Enterprises License: Expat Files: debian/licensing/bin/* diff --git a/debian/patches/0012-Fix-possibly-weak-random-number-generator.patch b/debian/patches/0012-Fix-possibly-weak-random-number-generator.patch new file mode 100644 index 0000000..6943d76 --- /dev/null +++ b/debian/patches/0012-Fix-possibly-weak-random-number-generator.patch @@ -0,0 +1,1379 @@ +From: Daniel Beyer <dabe@deb.ymc.ch> +Date: Thu, 14 Jan 2016 18:11:12 +0100 +Subject: Fix possibly weak random number generator + +Bug: https://github.com/symfony/symfony/issues/17359 +Origin: https://github.com/symfony/symfony/commit/fcd3160a0f77931b1b2fd066bbb0bb0907d80fee + +This embeds paragonie/random_compat into the security component, since +upstream's patch requires it. + +paragonie/random_compat is licensed under the MIT License (MIT) and +copyright (c) 2015 Paragon Initiative Enterprises +--- + .../Component/Security/Core/Util/SecureRandom.php | 86 +--------- + .../vendor/paragonie/random_compat/LICENSE | 22 +++ + .../random_compat/lib/byte_safe_strings.php | 160 ++++++++++++++++++ + .../paragonie/random_compat/lib/cast_to_int.php | 64 +++++++ + .../paragonie/random_compat/lib/error_polyfill.php | 42 +++++ + .../vendor/paragonie/random_compat/lib/random.php | 149 +++++++++++++++++ + .../random_compat/lib/random_bytes_com_dotnet.php | 77 +++++++++ + .../random_compat/lib/random_bytes_dev_urandom.php | 142 ++++++++++++++++ + .../random_compat/lib/random_bytes_libsodium.php | 84 ++++++++++ + .../lib/random_bytes_libsodium_legacy.php | 84 ++++++++++ + .../random_compat/lib/random_bytes_mcrypt.php | 72 ++++++++ + .../random_compat/lib/random_bytes_openssl.php | 76 +++++++++ + .../paragonie/random_compat/lib/random_int.php | 185 +++++++++++++++++++++ + 13 files changed, 1159 insertions(+), 84 deletions(-) + create mode 100644 src/Symfony/Component/Security/vendor/paragonie/random_compat/LICENSE + create mode 100644 src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/byte_safe_strings.php + create mode 100644 src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/cast_to_int.php + create mode 100644 src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/error_polyfill.php + create mode 100644 src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random.php + create mode 100644 src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php + create mode 100644 src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php + create mode 100644 src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php + create mode 100644 src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php + create mode 100644 src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php + create mode 100644 src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_openssl.php + create mode 100644 src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_int.php + +diff --git a/src/Symfony/Component/Security/Core/Util/SecureRandom.php b/src/Symfony/Component/Security/Core/Util/SecureRandom.php +index 841b9af..baaae82 100644 +--- a/src/Symfony/Component/Security/Core/Util/SecureRandom.php ++++ b/src/Symfony/Component/Security/Core/Util/SecureRandom.php +@@ -11,8 +11,6 @@ + + namespace Symfony\Component\Security\Core\Util; + +-use Psr\Log\LoggerInterface; +- + /** + * A secure random number generator implementation. + * +@@ -21,94 +19,14 @@ use Psr\Log\LoggerInterface; + */ + final class SecureRandom implements SecureRandomInterface + { +- private $logger; + private $useOpenSsl; +- private $seed; +- private $seedUpdated; +- private $seedLastUpdatedAt; +- private $seedFile; +- +- /** +- * Constructor. +- * +- * Be aware that a guessable seed will severely compromise the PRNG +- * algorithm that is employed. +- * +- * @param string $seedFile +- * @param LoggerInterface $logger +- */ +- public function __construct($seedFile = null, LoggerInterface $logger = null) +- { +- $this->seedFile = $seedFile; +- $this->logger = $logger; +- +- // determine whether to use OpenSSL +- if (defined('PHP_WINDOWS_VERSION_BUILD') && version_compare(PHP_VERSION, '5.3.4', '<')) { +- $this->useOpenSsl = false; +- } elseif (!function_exists('openssl_random_pseudo_bytes')) { +- if (null !== $this->logger) { +- $this->logger->notice('It is recommended that you enable the "openssl" extension for random number generation.'); +- } +- $this->useOpenSsl = false; +- } else { +- $this->useOpenSsl = true; +- } +- } + + /** + * {@inheritdoc} + */ + public function nextBytes($nbBytes) + { +- // try OpenSSL +- if ($this->useOpenSsl) { +- $bytes = openssl_random_pseudo_bytes($nbBytes, $strong); +- +- if (false !== $bytes && true === $strong) { +- return $bytes; +- } +- +- if (null !== $this->logger) { +- $this->logger->info('OpenSSL did not produce a secure random number.'); +- } +- } +- +- // initialize seed +- if (null === $this->seed) { +- if (null === $this->seedFile) { +- throw new \RuntimeException('You need to specify a file path to store the seed.'); +- } +- +- if (is_file($this->seedFile)) { +- list($this->seed, $this->seedLastUpdatedAt) = $this->readSeed(); +- } else { +- $this->seed = uniqid(mt_rand(), true); +- $this->updateSeed(); +- } +- } +- +- $bytes = ''; +- while (strlen($bytes) < $nbBytes) { +- static $incr = 1; +- $bytes .= hash('sha512', $incr++.$this->seed.uniqid(mt_rand(), true).$nbBytes, true); +- $this->seed = base64_encode(hash('sha512', $this->seed.$bytes.$nbBytes, true)); +- $this->updateSeed(); +- } +- +- return substr($bytes, 0, $nbBytes); +- } +- +- private function readSeed() +- { +- return json_decode(file_get_contents($this->seedFile)); +- } +- +- private function updateSeed() +- { +- if (!$this->seedUpdated && $this->seedLastUpdatedAt < time() - mt_rand(1, 10)) { +- file_put_contents($this->seedFile, json_encode(array($this->seed, microtime(true)))); +- } +- +- $this->seedUpdated = true; ++ include_once 'Symfony/Component/Security/vendor/paragonie/random_compat/lib/random.php'; ++ return random_bytes($nbBytes); + } + } +diff --git a/src/Symfony/Component/Security/vendor/paragonie/random_compat/LICENSE b/src/Symfony/Component/Security/vendor/paragonie/random_compat/LICENSE +new file mode 100644 +index 0000000..45c7017 +--- /dev/null ++++ b/src/Symfony/Component/Security/vendor/paragonie/random_compat/LICENSE +@@ -0,0 +1,22 @@ ++The MIT License (MIT) ++ ++Copyright (c) 2015 Paragon Initiative Enterprises ++ ++Permission is hereby granted, free of charge, to any person obtaining a copy ++of this software and associated documentation files (the "Software"), to deal ++in the Software without restriction, including without limitation the rights ++to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++copies of the Software, and to permit persons to whom the Software is ++furnished to do so, subject to the following conditions: ++ ++The above copyright notice and this permission notice shall be included in all ++copies or substantial portions of the Software. ++ ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++SOFTWARE. ++ +diff --git a/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/byte_safe_strings.php b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/byte_safe_strings.php +new file mode 100644 +index 0000000..a3cc90b +--- /dev/null ++++ b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/byte_safe_strings.php +@@ -0,0 +1,160 @@ ++<?php ++/** ++ * Random_* Compatibility Library ++ * for using the new PHP 7 random_* API in PHP 5 projects ++ * ++ * The MIT License (MIT) ++ * ++ * Copyright (c) 2015 Paragon Initiative Enterprises ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++if (!function_exists('RandomCompat_strlen')) { ++ if ( ++ defined('MB_OVERLOAD_STRING') && ++ ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING ++ ) { ++ /** ++ * strlen() implementation that isn't brittle to mbstring.func_overload ++ * ++ * This version uses mb_strlen() in '8bit' mode to treat strings as raw ++ * binary rather than UTF-8, ISO-8859-1, etc ++ * ++ * @param string $binary_string ++ * ++ * @throws TypeError ++ * ++ * @return int ++ */ ++ function RandomCompat_strlen($binary_string) ++ { ++ if (!is_string($binary_string)) { ++ throw new TypeError( ++ 'RandomCompat_strlen() expects a string' ++ ); ++ } ++ return mb_strlen($binary_string, '8bit'); ++ } ++ } else { ++ /** ++ * strlen() implementation that isn't brittle to mbstring.func_overload ++ * ++ * This version just used the default strlen() ++ * ++ * @param string $binary_string ++ * ++ * @throws TypeError ++ * ++ * @return int ++ */ ++ function RandomCompat_strlen($binary_string) ++ { ++ if (!is_string($binary_string)) { ++ throw new TypeError( ++ 'RandomCompat_strlen() expects a string' ++ ); ++ } ++ return strlen($binary_string); ++ } ++ } ++} ++ ++if (!function_exists('RandomCompat_substr')) { ++ if ( ++ defined('MB_OVERLOAD_STRING') && ++ ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING ++ ) { ++ /** ++ * substr() implementation that isn't brittle to mbstring.func_overload ++ * ++ * This version uses mb_substr() in '8bit' mode to treat strings as raw ++ * binary rather than UTF-8, ISO-8859-1, etc ++ * ++ * @param string $binary_string ++ * @param int $start ++ * @param int $length (optional) ++ * ++ * @throws TypeError ++ * ++ * @return string ++ */ ++ function RandomCompat_substr($binary_string, $start, $length = null) ++ { ++ if (!is_string($binary_string)) { ++ throw new TypeError( ++ 'RandomCompat_substr(): First argument should be a string' ++ ); ++ } ++ if (!is_int($start)) { ++ throw new TypeError( ++ 'RandomCompat_substr(): Second argument should be an integer' ++ ); ++ } ++ if ($length === null) { ++ /** ++ * mb_substr($str, 0, NULL, '8bit') returns an empty string on ++ * PHP 5.3, so we have to find the length ourselves. ++ */ ++ $length = RandomCompat_strlen($length) - $start; ++ } elseif (!is_int($length)) { ++ throw new TypeError( ++ 'RandomCompat_substr(): Third argument should be an integer, or omitted' ++ ); ++ } ++ return mb_substr($binary_string, $start, $length, '8bit'); ++ } ++ } else { ++ /** ++ * substr() implementation that isn't brittle to mbstring.func_overload ++ * ++ * This version just uses the default substr() ++ * ++ * @param string $binary_string ++ * @param int $start ++ * @param int $length (optional) ++ * ++ * @throws TypeError ++ * ++ * @return string ++ */ ++ function RandomCompat_substr($binary_string, $start, $length = null) ++ { ++ if (!is_string($binary_string)) { ++ throw new TypeError( ++ 'RandomCompat_substr(): First argument should be a string' ++ ); ++ } ++ if (!is_int($start)) { ++ throw new TypeError( ++ 'RandomCompat_substr(): Second argument should be an integer' ++ ); ++ } ++ if ($length !== null) { ++ if (!is_int($length)) { ++ throw new TypeError( ++ 'RandomCompat_substr(): Third argument should be an integer, or omitted' ++ ); ++ } ++ return substr($binary_string, $start, $length); ++ } ++ return substr($binary_string, $start); ++ } ++ } ++} +diff --git a/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/cast_to_int.php b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/cast_to_int.php +new file mode 100644 +index 0000000..474ce64 +--- /dev/null ++++ b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/cast_to_int.php +@@ -0,0 +1,64 @@ ++<?php ++/** ++ * Random_* Compatibility Library ++ * for using the new PHP 7 random_* API in PHP 5 projects ++ * ++ * The MIT License (MIT) ++ * ++ * Copyright (c) 2015 Paragon Initiative Enterprises ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++if (!function_exists('RandomCompat_intval')) { ++ ++ /** ++ * Cast to an integer if we can, safely. ++ * ++ * If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX) ++ * (non-inclusive), it will sanely cast it to an int. If you it's equal to ++ * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats ++ * lose precision, so the <= and => operators might accidentally let a float ++ * through. ++ * ++ * @param numeric $number The number we want to convert to an int ++ * @param boolean $fail_open Set to true to not throw an exception ++ * ++ * @return int (or float if $fail_open) ++ */ ++ function RandomCompat_intval($number, $fail_open = false) ++ { ++ if (is_numeric($number)) { ++ $number += 0; ++ } ++ if ( ++ is_float($number) && ++ $number > ~PHP_INT_MAX && ++ $number < PHP_INT_MAX ++ ) { ++ $number = (int) $number; ++ } ++ if (is_int($number) || $fail_open) { ++ return $number; ++ } ++ throw new TypeError( ++ 'Expected an integer.' ++ ); ++ } ++} +diff --git a/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/error_polyfill.php b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/error_polyfill.php +new file mode 100644 +index 0000000..57cfefd +--- /dev/null ++++ b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/error_polyfill.php +@@ -0,0 +1,42 @@ ++<?php ++/** ++ * Random_* Compatibility Library ++ * for using the new PHP 7 random_* API in PHP 5 projects ++ * ++ * The MIT License (MIT) ++ * ++ * Copyright (c) 2015 Paragon Initiative Enterprises ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++if (!class_exists('Error', false)) { ++ // We can't really avoid making this extend Exception in PHP 5. ++ class Error extends Exception ++ { ++ ++ } ++} ++ ++if (!class_exists('TypeError', false)) { ++ class TypeError extends Error ++ { ++ ++ } ++} +diff --git a/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random.php b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random.php +new file mode 100644 +index 0000000..fb21ef2 +--- /dev/null ++++ b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random.php +@@ -0,0 +1,149 @@ ++<?php ++/** ++ * Random_* Compatibility Library ++ * for using the new PHP 7 random_* API in PHP 5 projects ++ * ++ * The MIT License (MIT) ++ * ++ * Copyright (c) 2015 Paragon Initiative Enterprises ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++if (!defined('PHP_VERSION_ID')) { ++ // This constant was introduced in PHP 5.2.7 ++ $RandomCompatversion = explode('.', PHP_VERSION); ++ define('PHP_VERSION_ID', ($RandomCompatversion[0] * 10000 + $RandomCompatversion[1] * 100 + $RandomCompatversion[2])); ++ $RandomCompatversion = null; ++} ++if (PHP_VERSION_ID < 70000) { ++ if (!defined('RANDOM_COMPAT_READ_BUFFER')) { ++ define('RANDOM_COMPAT_READ_BUFFER', 8); ++ } ++ $RandomCompatDIR = dirname(__FILE__); ++ require_once $RandomCompatDIR.'/byte_safe_strings.php'; ++ require_once $RandomCompatDIR.'/cast_to_int.php'; ++ require_once $RandomCompatDIR.'/error_polyfill.php'; ++ if (!function_exists('random_bytes')) { ++ /** ++ * PHP 5.2.0 - 5.6.x way to implement random_bytes() ++ * ++ * We use conditional statements here to define the function in accordance ++ * to the operating environment. It's a micro-optimization. ++ * ++ * In order of preference: ++ * 1. Use libsodium if available. ++ * 2. fread() /dev/urandom if available (never on Windows) ++ * 3. mcrypt_create_iv($bytes, MCRYPT_CREATE_IV) ++ * 4. COM('CAPICOM.Utilities.1')->GetRandom() ++ * 5. openssl_random_pseudo_bytes() (absolute last resort) ++ * ++ * See ERRATA.md for our reasoning behind this particular order ++ */ ++ if (extension_loaded('libsodium')) { ++ // See random_bytes_libsodium.php ++ if (PHP_VERSION_ID >= 50300 && function_exists('\\Sodium\\randombytes_buf')) { ++ require_once $RandomCompatDIR.'/random_bytes_libsodium.php'; ++ } elseif (method_exists('Sodium', 'randombytes_buf')) { ++ require_once $RandomCompatDIR.'/random_bytes_libsodium_legacy.php'; ++ } ++ } ++ if ( ++ !function_exists('random_bytes') && ++ DIRECTORY_SEPARATOR === '/' && ++ @is_readable('/dev/urandom') ++ ) { ++ // DIRECTORY_SEPARATOR === '/' on Unix-like OSes -- this is a fast ++ // way to exclude Windows. ++ // ++ // Error suppression on is_readable() in case of an open_basedir or ++ // safe_mode failure. All we care about is whether or not we can ++ // read it at this point. If the PHP environment is going to panic ++ // over trying to see if the file can be read in the first place, ++ // that is not helpful to us here. ++ ++ // See random_bytes_dev_urandom.php ++ require_once $RandomCompatDIR.'/random_bytes_dev_urandom.php'; ++ } ++ if ( ++ !function_exists('random_bytes') && ++ PHP_VERSION_ID >= 50307 && ++ extension_loaded('mcrypt') ++ ) { ++ // See random_bytes_mcrypt.php ++ require_once $RandomCompatDIR.'/random_bytes_mcrypt.php'; ++ } ++ if ( ++ !function_exists('random_bytes') && ++ extension_loaded('com_dotnet') && ++ class_exists('COM') ++ ) { ++ $RandomCompat_disabled_classes = preg_split( ++ '#\s*,\s*#', ++ strtolower(ini_get('disable_classes')) ++ ); ++ ++ if (!in_array('com', $RandomCompat_disabled_classes)) { ++ try { ++ $RandomCompatCOMtest = new COM('CAPICOM.Utilities.1'); ++ if (method_exists($RandomCompatCOMtest, 'GetRandom')) { ++ // See random_bytes_com_dotnet.php ++ require_once $RandomCompatDIR.'/random_bytes_com_dotnet.php'; ++ } ++ } catch (com_exception $e) { ++ // Don't try to use it. ++ } ++ } ++ $RandomCompat_disabled_classes = null; ++ $RandomCompatCOMtest = null; ++ } ++ if ( ++ !function_exists('random_bytes') && ++ extension_loaded('openssl') && ++ ( ++ // Unix-like with PHP >= 5.3.0 or ++ ( ++ DIRECTORY_SEPARATOR === '/' && ++ PHP_VERSION_ID >= 50300 ++ ) || ++ // Windows with PHP >= 5.4.1 ++ PHP_VERSION_ID >= 50401 ++ ) ++ ) { ++ // See random_bytes_openssl.php ++ require_once $RandomCompatDIR.'/random_bytes_openssl.php'; ++ } ++ if (!function_exists('random_bytes')) { ++ /** ++ * We don't have any more options, so let's throw an exception right now ++ * and hope the developer won't let it fail silently. ++ */ ++ function random_bytes() ++ { ++ throw new Exception( ++ 'There is no suitable CSPRNG installed on your system' ++ ); ++ } ++ } ++ } ++ if (!function_exists('random_int')) { ++ require_once $RandomCompatDIR.'/random_int.php'; ++ } ++ $RandomCompatDIR = null; ++} +diff --git a/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php +new file mode 100644 +index 0000000..0a781f4 +--- /dev/null ++++ b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php +@@ -0,0 +1,77 @@ ++<?php ++/** ++ * Random_* Compatibility Library ++ * for using the new PHP 7 random_* API in PHP 5 projects ++ * ++ * The MIT License (MIT) ++ * ++ * Copyright (c) 2015 Paragon Initiative Enterprises ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++/** ++ * Windows with PHP < 5.3.0 will not have the function ++ * openssl_random_pseudo_bytes() available, so let's use ++ * CAPICOM to work around this deficiency. ++ * ++ * @param int $bytes ++ * ++ * @throws Exception ++ * ++ * @return string ++ */ ++function random_bytes($bytes) ++{ ++ try { ++ $bytes = RandomCompat_intval($bytes); ++ } catch (TypeError $ex) { ++ throw new TypeError( ++ 'random_bytes(): $bytes must be an integer' ++ ); ++ } ++ if ($bytes < 1) { ++ throw new Error( ++ 'Length must be greater than 0' ++ ); ++ } ++ $buf = ''; ++ $util = new COM('CAPICOM.Utilities.1'); ++ $execCount = 0; ++ /** ++ * Let's not let it loop forever. If we run N times and fail to ++ * get N bytes of random data, then CAPICOM has failed us. ++ */ ++ do { ++ $buf .= base64_decode($util->GetRandom($bytes, 0)); ++ if (RandomCompat_strlen($buf) >= $bytes) { ++ /** ++ * Return our random entropy buffer here: ++ */ ++ return RandomCompat_substr($buf, 0, $bytes); ++ } ++ ++$execCount; ++ } while ($execCount < $bytes); ++ /** ++ * If we reach here, PHP has failed us. ++ */ ++ throw new Exception( ++ 'Could not gather sufficient random data' ++ ); ++} +diff --git a/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php +new file mode 100644 +index 0000000..5d07104 +--- /dev/null ++++ b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php +@@ -0,0 +1,142 @@ ++<?php ++/** ++ * Random_* Compatibility Library ++ * for using the new PHP 7 random_* API in PHP 5 projects ++ * ++ * The MIT License (MIT) ++ * ++ * Copyright (c) 2015 Paragon Initiative Enterprises ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++if (!defined('RANDOM_COMPAT_READ_BUFFER')) { ++ define('RANDOM_COMPAT_READ_BUFFER', 8); ++} ++ ++/** ++ * Unless open_basedir is enabled, use /dev/urandom for ++ * random numbers in accordance with best practices ++ * ++ * Why we use /dev/urandom and not /dev/random ++ * @ref http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers ++ * ++ * @param int $bytes ++ * ++ * @throws Exception ++ * ++ * @return string ++ */ ++function random_bytes($bytes) ++{ ++ static $fp = null; ++ /** ++ * This block should only be run once ++ */ ++ if (empty($fp)) { ++ /** ++ * We use /dev/urandom if it is a char device. ++ * We never fall back to /dev/random ++ */ ++ $fp = fopen('/dev/urandom', 'rb'); ++ if (!empty($fp)) { ++ $st = fstat($fp); ++ if (($st['mode'] & 0170000) !== 020000) { ++ fclose($fp); ++ $fp = false; ++ } ++ } ++ if (!empty($fp)) { ++ /** ++ * stream_set_read_buffer() does not exist in HHVM ++ * ++ * If we don't set the stream's read buffer to 0, PHP will ++ * internally buffer 8192 bytes, which can waste entropy ++ * ++ * stream_set_read_buffer returns 0 on success ++ */ ++ if (function_exists('stream_set_read_buffer')) { ++ stream_set_read_buffer($fp, RANDOM_COMPAT_READ_BUFFER); ++ } ++ if (function_exists('stream_set_chunk_size')) { ++ stream_set_chunk_size($fp, RANDOM_COMPAT_READ_BUFFER); ++ } ++ } ++ } ++ try { ++ $bytes = RandomCompat_intval($bytes); ++ } catch (TypeError $ex) { ++ throw new TypeError( ++ 'random_bytes(): $bytes must be an integer' ++ ); ++ } ++ if ($bytes < 1) { ++ throw new Error( ++ 'Length must be greater than 0' ++ ); ++ } ++ /** ++ * This if() block only runs if we managed to open a file handle ++ * ++ * It does not belong in an else {} block, because the above ++ * if (empty($fp)) line is logic that should only be run once per ++ * page load. ++ */ ++ if (!empty($fp)) { ++ $remaining = $bytes; ++ $buf = ''; ++ /** ++ * We use fread() in a loop to protect against partial reads ++ */ ++ do { ++ $read = fread($fp, $remaining); ++ if ($read === false) { ++ /** ++ * We cannot safely read from the file. Exit the ++ * do-while loop and trigger the exception condition ++ */ ++ $buf = false; ++ break; ++ } ++ /** ++ * Decrease the number of bytes returned from remaining ++ */ ++ $remaining -= RandomCompat_strlen($read); ++ $buf .= $read; ++ } while ($remaining > 0); ++ ++ /** ++ * Is our result valid? ++ */ ++ if ($buf !== false) { ++ if (RandomCompat_strlen($buf) === $bytes) { ++ /** ++ * Return our random entropy buffer here: ++ */ ++ return $buf; ++ } ++ } ++ } ++ /** ++ * If we reach here, PHP has failed us. ++ */ ++ throw new Exception( ++ 'Error reading from source device' ++ ); ++} +diff --git a/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php +new file mode 100644 +index 0000000..938cac9 +--- /dev/null ++++ b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php +@@ -0,0 +1,84 @@ ++<?php ++/** ++ * Random_* Compatibility Library ++ * for using the new PHP 7 random_* API in PHP 5 projects ++ * ++ * The MIT License (MIT) ++ * ++ * Copyright (c) 2015 Paragon Initiative Enterprises ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++/** ++ * If the libsodium PHP extension is loaded, we'll use it above any other ++ * solution. ++ * ++ * libsodium-php project: ++ * @ref https://github.com/jedisct1/libsodium-php ++ * ++ * @param int $bytes ++ * ++ * @throws Exception ++ * ++ * @return string ++ */ ++function random_bytes($bytes) ++{ ++ try { ++ $bytes = RandomCompat_intval($bytes); ++ } catch (TypeError $ex) { ++ throw new TypeError( ++ 'random_bytes(): $bytes must be an integer' ++ ); ++ } ++ if ($bytes < 1) { ++ throw new Error( ++ 'Length must be greater than 0' ++ ); ++ } ++ /** ++ * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be ++ * generated in one invocation. ++ */ ++ if ($bytes > 2147483647) { ++ $buf = ''; ++ for ($i = 0; $i < $bytes; $i += 1073741824) { ++ $n = ($bytes - $i) > 1073741824 ++ ? 1073741824 ++ : $bytes - $i; ++ $buf .= \Sodium\randombytes_buf($n); ++ } ++ } else { ++ $buf = \Sodium\randombytes_buf($bytes); ++ } ++ ++ if ($buf !== false) { ++ if (RandomCompat_strlen($buf) === $bytes) { ++ return $buf; ++ } ++ } ++ ++ /** ++ * If we reach here, PHP has failed us. ++ */ ++ throw new Exception( ++ 'Could not gather sufficient random data' ++ ); ++} +diff --git a/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php +new file mode 100644 +index 0000000..4c76ff9 +--- /dev/null ++++ b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php +@@ -0,0 +1,84 @@ ++<?php ++/** ++ * Random_* Compatibility Library ++ * for using the new PHP 7 random_* API in PHP 5 projects ++ * ++ * The MIT License (MIT) ++ * ++ * Copyright (c) 2015 Paragon Initiative Enterprises ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++/** ++ * If the libsodium PHP extension is loaded, we'll use it above any other ++ * solution. ++ * ++ * libsodium-php project: ++ * @ref https://github.com/jedisct1/libsodium-php ++ * ++ * @param int $bytes ++ * ++ * @throws Exception ++ * ++ * @return string ++ */ ++function random_bytes($bytes) ++{ ++ try { ++ $bytes = RandomCompat_intval($bytes); ++ } catch (TypeError $ex) { ++ throw new TypeError( ++ 'random_bytes(): $bytes must be an integer' ++ ); ++ } ++ if ($bytes < 1) { ++ throw new Error( ++ 'Length must be greater than 0' ++ ); ++ } ++ /** ++ * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be ++ * generated in one invocation. ++ */ ++ if ($bytes > 2147483647) { ++ $buf = ''; ++ for ($i = 0; $i < $bytes; $i += 1073741824) { ++ $n = ($bytes - $i) > 1073741824 ++ ? 1073741824 ++ : $bytes - $i; ++ $buf .= Sodium::randombytes_buf($n); ++ } ++ } else { ++ $buf = Sodium::randombytes_buf($bytes); ++ } ++ ++ if ($buf !== false) { ++ if (RandomCompat_strlen($buf) === $bytes) { ++ return $buf; ++ } ++ } ++ ++ /** ++ * If we reach here, PHP has failed us. ++ */ ++ throw new Exception( ++ 'Could not gather sufficient random data' ++ ); ++} +diff --git a/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php +new file mode 100644 +index 0000000..5a1b688 +--- /dev/null ++++ b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php +@@ -0,0 +1,72 @@ ++<?php ++/** ++ * Random_* Compatibility Library ++ * for using the new PHP 7 random_* API in PHP 5 projects ++ * ++ * The MIT License (MIT) ++ * ++ * Copyright (c) 2015 Paragon Initiative Enterprises ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++ ++/** ++ * Powered by ext/mcrypt (and thankfully NOT libmcrypt) ++ * ++ * @ref https://bugs.php.net/bug.php?id=55169 ++ * @ref https://github.com/php/php-src/blob/c568ffe5171d942161fc8dda066bce844bdef676/ext/mcrypt/mcrypt.c#L1321-L1386 ++ * ++ * @param int $bytes ++ * ++ * @throws Exception ++ * ++ * @return string ++ */ ++function random_bytes($bytes) ++{ ++ try { ++ $bytes = RandomCompat_intval($bytes); ++ } catch (TypeError $ex) { ++ throw new TypeError( ++ 'random_bytes(): $bytes must be an integer' ++ ); ++ } ++ if ($bytes < 1) { ++ throw new Error( ++ 'Length must be greater than 0' ++ ); ++ } ++ ++ $buf = @mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM); ++ if ($buf !== false) { ++ if (RandomCompat_strlen($buf) === $bytes) { ++ /** ++ * Return our random entropy buffer here: ++ */ ++ return $buf; ++ } ++ } ++ /** ++ * If we reach here, PHP has failed us. ++ */ ++ throw new Exception( ++ 'Could not gather sufficient random data' ++ ); ++} +diff --git a/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_openssl.php b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_openssl.php +new file mode 100644 +index 0000000..3e12d3d +--- /dev/null ++++ b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_bytes_openssl.php +@@ -0,0 +1,76 @@ ++<?php ++/** ++ * Random_* Compatibility Library ++ * for using the new PHP 7 random_* API in PHP 5 projects ++ * ++ * The MIT License (MIT) ++ * ++ * Copyright (c) 2015 Paragon Initiative Enterprises ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++/** ++ * Since openssl_random_pseudo_bytes() uses openssl's ++ * RAND_pseudo_bytes() API, which has been marked as deprecated by the ++ * OpenSSL team, this is our last resort before failure. ++ * ++ * @ref https://www.openssl.org/docs/crypto/RAND_bytes.html ++ * ++ * @param int $bytes ++ * ++ * @throws Exception ++ * ++ * @return string ++ */ ++function random_bytes($bytes) ++{ ++ try { ++ $bytes = RandomCompat_intval($bytes); ++ } catch (TypeError $ex) { ++ throw new TypeError( ++ 'random_bytes(): $bytes must be an integer' ++ ); ++ } ++ if ($bytes < 1) { ++ throw new Error( ++ 'Length must be greater than 0' ++ ); ++ } ++ $secure = true; ++ /** ++ * $secure is passed by reference. If it's set to false, fail. Note ++ * that this will only return false if this function fails to return ++ * any data. ++ * ++ * @ref https://github.com/paragonie/random_compat/issues/6#issuecomment-119564973 ++ */ ++ $buf = openssl_random_pseudo_bytes($bytes, $secure); ++ if ($buf !== false && $secure) { ++ if (RandomCompat_strlen($buf) === $bytes) { ++ return $buf; ++ } ++ } ++ /** ++ * If we reach here, PHP has failed us. ++ */ ++ throw new Exception( ++ 'Could not gather sufficient random data' ++ ); ++} +diff --git a/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_int.php b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_int.php +new file mode 100644 +index 0000000..6c91dbc +--- /dev/null ++++ b/src/Symfony/Component/Security/vendor/paragonie/random_compat/lib/random_int.php +@@ -0,0 +1,185 @@ ++<?php ++/** ++ * Random_* Compatibility Library ++ * for using the new PHP 7 random_* API in PHP 5 projects ++ * ++ * The MIT License (MIT) ++ * ++ * Copyright (c) 2015 Paragon Initiative Enterprises ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++/** ++ * Fetch a random integer between $min and $max inclusive ++ * ++ * @param int $min ++ * @param int $max ++ * ++ * @throws Exception ++ * ++ * @return int ++ */ ++function random_int($min, $max) ++{ ++ /** ++ * Type and input logic checks ++ * ++ * If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX) ++ * (non-inclusive), it will sanely cast it to an int. If you it's equal to ++ * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats ++ * lose precision, so the <= and => operators might accidentally let a float ++ * through. ++ */ ++ ++ try { ++ $min = RandomCompat_intval($min); ++ } catch (TypeError $ex) { ++ throw new TypeError( ++ 'random_int(): $min must be an integer' ++ ); ++ } ++ try { ++ $max = RandomCompat_intval($max); ++ } catch (TypeError $ex) { ++ throw new TypeError( ++ 'random_int(): $max must be an integer' ++ ); ++ } ++ ++ /** ++ * Now that we've verified our weak typing system has given us an integer, ++ * let's validate the logic then we can move forward with generating random ++ * integers along a given range. ++ */ ++ if ($min > $max) { ++ throw new Error( ++ 'Minimum value must be less than or equal to the maximum value' ++ ); ++ } ++ if ($max === $min) { ++ return $min; ++ } ++ ++ /** ++ * Initialize variables to 0 ++ * ++ * We want to store: ++ * $bytes => the number of random bytes we need ++ * $mask => an integer bitmask (for use with the &) operator ++ * so we can minimize the number of discards ++ */ ++ $attempts = $bits = $bytes = $mask = $valueShift = 0; ++ ++ /** ++ * At this point, $range is a positive number greater than 0. It might ++ * overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to ++ * a float and we will lose some precision. ++ */ ++ $range = $max - $min; ++ ++ /** ++ * Test for integer overflow: ++ */ ++ if (!is_int($range)) { ++ /** ++ * Still safely calculate wider ranges. ++ * Provided by @CodesInChaos, @oittaa ++ * ++ * @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435 ++ * ++ * We use ~0 as a mask in this case because it generates all 1s ++ * ++ * @ref https://eval.in/400356 (32-bit) ++ * @ref http://3v4l.org/XX9r5 (64-bit) ++ */ ++ $bytes = PHP_INT_SIZE; ++ $mask = ~0; ++ } else { ++ /** ++ * $bits is effectively ceil(log($range, 2)) without dealing with ++ * type juggling ++ */ ++ while ($range > 0) { ++ if ($bits % 8 === 0) { ++ ++$bytes; ++ } ++ ++$bits; ++ $range >>= 1; ++ $mask = $mask << 1 | 1; ++ } ++ $valueShift = $min; ++ } ++ ++ /** ++ * Now that we have our parameters set up, let's begin generating ++ * random integers until one falls between $min and $max ++ */ ++ do { ++ /** ++ * The rejection probability is at most 0.5, so this corresponds ++ * to a failure probability of 2^-128 for a working RNG ++ */ ++ if ($attempts > 128) { ++ throw new Exception( ++ 'random_int: RNG is broken - too many rejections' ++ ); ++ } ++ ++ /** ++ * Let's grab the necessary number of random bytes ++ */ ++ $randomByteString = random_bytes($bytes); ++ if ($randomByteString === false) { ++ throw new Exception( ++ 'Random number generator failure' ++ ); ++ } ++ ++ /** ++ * Let's turn $randomByteString into an integer ++ * ++ * This uses bitwise operators (<< and |) to build an integer ++ * out of the values extracted from ord() ++ * ++ * Example: [9F] | [6D] | [32] | [0C] => ++ * 159 + 27904 + 3276800 + 201326592 => ++ * 204631455 ++ */ ++ $val = 0; ++ for ($i = 0; $i < $bytes; ++$i) { ++ $val |= ord($randomByteString[$i]) << ($i * 8); ++ } ++ ++ /** ++ * Apply mask ++ */ ++ $val &= $mask; ++ $val += $valueShift; ++ ++ ++$attempts; ++ /** ++ * If $val overflows to a floating point number, ++ * ... or is larger than $max, ++ * ... or smaller than $min, ++ * then try again. ++ */ ++ } while (!is_int($val) || $val > $max || $val < $min); ++ return (int) $val; ++} diff --git a/debian/patches/series b/debian/patches/series index 6ea62a0..7e0d40c 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -9,3 +9,4 @@ 0009-HttpKernel-Do-not-call-the-FragmentListener-if-_cont.patch 0010-CVE-2015-8124-Session-Fixation-in-the-Remember-Me-Lo.patch 0011-CVE-2015-8125-Vulnerability-in-Security-Remember-Me-.patch +0012-Fix-possibly-weak-random-number-generator.patch
Attachment:
signature.asc
Description: PGP signature