From 638e6c78ec3de5d0fdd305d5768548806edb0a02 Mon Sep 17 00:00:00 2001 From: terrafrost Date: Mon, 16 Jun 2014 09:40:27 -0500 Subject: [PATCH 1/7] Random: include the Crypt_* classes if they're available also error out if none are available --- phpseclib/Crypt/Random.php | 104 +++++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 34 deletions(-) diff --git a/phpseclib/Crypt/Random.php b/phpseclib/Crypt/Random.php index 02773931..06800a5a 100644 --- a/phpseclib/Crypt/Random.php +++ b/phpseclib/Crypt/Random.php @@ -120,7 +120,7 @@ if (!function_exists('crypt_random_string')) { // easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but // PHP isn't low level to be able to use those as sources and on a web server there's not likely // going to be a ton of keyboard or mouse action. web servers do have one thing that we can use - // however. a ton of people visiting the website. obviously you don't want to base your seeding + // however, a ton of people visiting the website. obviously you don't want to base your seeding // soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled // by the user and (2) this isn't just looking at the data sent by the current user - it's based // on the data sent by all users. one user requests the page and a hash of their info is saved. @@ -191,21 +191,45 @@ if (!function_exists('crypt_random_string')) { // // http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives switch (true) { - case class_exists('Crypt_AES'): + case stream_resolve_include_path('Crypt/AES.php'): + if (!class_exists('Crypt_AES')) { + include_once 'AES.php'; + } $crypto = new Crypt_AES(CRYPT_AES_MODE_CTR); break; - case class_exists('Crypt_TripleDES'): + case stream_resolve_include_path('Crypt/Twofish.php'): + if (!class_exists('Crypt_Twofish')) { + include_once 'Twofish.php'; + } + $crypto = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR); + break; + case stream_resolve_include_path('Crypt/Blowfish.php'): + if (!class_exists('Crypt_Blowfish')) { + include_once 'Blowfish.php'; + } + $crypto = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR); + break; + case stream_resolve_include_path('Crypt/TripleDES.php'): + if (!class_exists('Crypt_TripleDES')) { + include_once 'TripleDES.php'; + } $crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR); break; - case class_exists('Crypt_DES'): + case stream_resolve_include_path('Crypt/DES.php'): + if (!class_exists('Crypt_DES')) { + include_once 'DES.php'; + } $crypto = new Crypt_DES(CRYPT_DES_MODE_CTR); break; - case class_exists('Crypt_RC4'): + case stream_resolve_include_path('Crypt/RC4.php'): + if (!class_exists('Crypt_RC4')) { + include_once 'RC4.php'; + } $crypto = new Crypt_RC4(); break; default: - $crypto = $seed; - return crypt_random_string($length); + user_error('crypt_random_string requires at least one symmetric cipher be loaded'); + return false; } $crypto->setKey($key); @@ -213,39 +237,51 @@ if (!function_exists('crypt_random_string')) { $crypto->enableContinuousBuffer(); } - if (is_string($crypto)) { - // the following is based off of ANSI X9.31: - // - // http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf - // - // OpenSSL uses that same standard for it's random numbers: - // - // http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c - // (do a search for "ANS X9.31 A.2.4") - // - // ANSI X9.31 recommends ciphers be used and phpseclib does use them if they're available (see - // later on in the code) but if they're not we'll use sha1 - $result = ''; - while (strlen($result) < $length) { // each loop adds 20 bytes - // microtime() isn't packed as "densely" as it could be but then neither is that the idea. - // the idea is simply to ensure that each "block" has a unique element to it. - $i = pack('H*', sha1(microtime())); - $r = pack('H*', sha1($i ^ $v)); - $v = pack('H*', sha1($r ^ $i)); - $result.= $r; - } - return substr($result, 0, $length); - } - //return $crypto->encrypt(str_repeat("\0", $length)); + // the following is based off of ANSI X9.31: + // + // http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf + // + // OpenSSL uses that same standard for it's random numbers: + // + // http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c + // (do a search for "ANS X9.31 A.2.4") $result = ''; while (strlen($result) < $length) { - $i = $crypto->encrypt(microtime()); - $r = $crypto->encrypt($i ^ $v); - $v = $crypto->encrypt($r ^ $i); + $i = $crypto->encrypt(microtime()); // strlen(microtime()) == 21 + $r = $crypto->encrypt($i ^ $v); // strlen($v) == 20 + $v = $crypto->encrypt($r ^ $i); // strlen($r) == 20 $result.= $r; } return substr($result, 0, $length); } } + +if (!function_exists('stream_resolve_include_path')) { + /** + * Resolve filename against the include path. + * + * stream_resolve_include_path was introduced in PHP 5.3.2. This is kinda a PHP_Compat layer for those not using that version. + * + * @param Integer $length + * @return String + * @access public + */ + function stream_resolve_include_path($filename) + { + $paths = PATH_SEPARATOR == ':' ? + preg_split('#(? Date: Mon, 16 Jun 2014 09:47:13 -0500 Subject: [PATCH 2/7] SSH2: replace _is_includable() with stream_resolve_include_path --- phpseclib/Net/SSH2.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/phpseclib/Net/SSH2.php b/phpseclib/Net/SSH2.php index 49382177..29879711 100644 --- a/phpseclib/Net/SSH2.php +++ b/phpseclib/Net/SSH2.php @@ -1107,31 +1107,31 @@ class Net_SSH2 'none' // OPTIONAL no encryption; NOT RECOMMENDED ); - if (!$this->_is_includable('Crypt/RC4.php')) { + if (stream_resolve_include_path('Crypt/RC4.php') === false) { $encryption_algorithms = array_diff( $encryption_algorithms, array('arcfour256', 'arcfour128', 'arcfour') ); } - if (!$this->_is_includable('Crypt/Rijndael.php')) { + if (stream_resolve_include_path('Crypt/Rijndael.php') === false) { $encryption_algorithms = array_diff( $encryption_algorithms, array('aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc') ); } - if (!$this->_is_includable('Crypt/Twofish.php')) { + if (stream_resolve_include_path('Crypt/Twofish.php') === false) { $encryption_algorithms = array_diff( $encryption_algorithms, array('twofish128-ctr', 'twofish192-ctr', 'twofish256-ctr', 'twofish128-cbc', 'twofish192-cbc', 'twofish256-cbc', 'twofish-cbc') ); } - if (!$this->_is_includable('Crypt/Blowfish.php')) { + if (stream_resolve_include_path('Crypt/Blowfish.php') === false) { $encryption_algorithms = array_diff( $encryption_algorithms, array('blowfish-ctr', 'blowfish-cbc') ); } - if (!$this->_is_includable('Crypt/TripleDES.php')) { + if (stream_resolve_include_path('Crypt/TripleDES.php') === false) { $encryption_algorithms = array_diff( $encryption_algorithms, array('3des-ctr', '3des-cbc') From 82b5e02f06a78670d79a4bcf472b768523597283 Mon Sep 17 00:00:00 2001 From: terrafrost Date: Mon, 16 Jun 2014 09:53:55 -0500 Subject: [PATCH 3/7] Random: add explanatory comment --- phpseclib/Crypt/Random.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/phpseclib/Crypt/Random.php b/phpseclib/Crypt/Random.php index 06800a5a..c4ff83f3 100644 --- a/phpseclib/Crypt/Random.php +++ b/phpseclib/Crypt/Random.php @@ -3,6 +3,9 @@ /** * Random Number Generator * + * The idea behind this function is that it can be easily replaced with your own crypt_random_string() + * function. eg. maybe you have a better source of entropy for creating the initial states or whatever. + * * PHP versions 4 and 5 * * Here's a short example of how to use this library: From 9c90beaf8241e21665f6efa065bc0f33f3c93ffd Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Tue, 17 Jun 2014 14:38:24 +0200 Subject: [PATCH 4/7] Replace stream_resolve_include_path with phpseclib_is_includable. --- phpseclib/Crypt/Random.php | 28 +++++++++++++++------------- phpseclib/Net/SSH2.php | 10 +++++----- tests/bootstrap.php | 14 +------------- 3 files changed, 21 insertions(+), 31 deletions(-) diff --git a/phpseclib/Crypt/Random.php b/phpseclib/Crypt/Random.php index c4ff83f3..0416594f 100644 --- a/phpseclib/Crypt/Random.php +++ b/phpseclib/Crypt/Random.php @@ -194,37 +194,37 @@ if (!function_exists('crypt_random_string')) { // // http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives switch (true) { - case stream_resolve_include_path('Crypt/AES.php'): + case phpseclib_is_includable('Crypt/AES.php'): if (!class_exists('Crypt_AES')) { include_once 'AES.php'; } $crypto = new Crypt_AES(CRYPT_AES_MODE_CTR); break; - case stream_resolve_include_path('Crypt/Twofish.php'): + case phpseclib_is_includable('Crypt/Twofish.php'): if (!class_exists('Crypt_Twofish')) { include_once 'Twofish.php'; } $crypto = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR); break; - case stream_resolve_include_path('Crypt/Blowfish.php'): + case phpseclib_is_includable('Crypt/Blowfish.php'): if (!class_exists('Crypt_Blowfish')) { include_once 'Blowfish.php'; } $crypto = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR); break; - case stream_resolve_include_path('Crypt/TripleDES.php'): + case phpseclib_is_includable('Crypt/TripleDES.php'): if (!class_exists('Crypt_TripleDES')) { include_once 'TripleDES.php'; } $crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR); break; - case stream_resolve_include_path('Crypt/DES.php'): + case phpseclib_is_includable('Crypt/DES.php'): if (!class_exists('Crypt_DES')) { include_once 'DES.php'; } $crypto = new Crypt_DES(CRYPT_DES_MODE_CTR); break; - case stream_resolve_include_path('Crypt/RC4.php'): + case phpseclib_is_includable('Crypt/RC4.php'): if (!class_exists('Crypt_RC4')) { include_once 'RC4.php'; } @@ -261,30 +261,32 @@ if (!function_exists('crypt_random_string')) { } } -if (!function_exists('stream_resolve_include_path')) { +if (!function_exists('phpseclib_is_includable')) { /** * Resolve filename against the include path. * - * stream_resolve_include_path was introduced in PHP 5.3.2. This is kinda a PHP_Compat layer for those not using that version. + * Wrapper around stream_resolve_include_path() (which was introduced in + * PHP 5.3.2) with fallback implementation for earlier PHP versions. * - * @param Integer $length - * @return String + * @param string $filename + * @return mixed Filename (string) on success, false otherwise. * @access public */ - function stream_resolve_include_path($filename) + function phpseclib_is_includable($filename) { + if (function_exists('stream_resolve_include_path')) { + return stream_resolve_include_path($filename); + } $paths = PATH_SEPARATOR == ':' ? preg_split('#(? Date: Tue, 17 Jun 2014 20:06:26 -0500 Subject: [PATCH 5/7] Random: a few changes to the stream_resolve_include_path_function --- phpseclib/Crypt/Random.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/phpseclib/Crypt/Random.php b/phpseclib/Crypt/Random.php index 0416594f..b34b7980 100644 --- a/phpseclib/Crypt/Random.php +++ b/phpseclib/Crypt/Random.php @@ -277,16 +277,24 @@ if (!function_exists('phpseclib_is_includable')) { if (function_exists('stream_resolve_include_path')) { return stream_resolve_include_path($filename); } + + // handle non-relative paths + if (file_exists($filename)) { + return realpath($filename); + } + $paths = PATH_SEPARATOR == ':' ? preg_split('#(? Date: Wed, 18 Jun 2014 23:41:26 +0200 Subject: [PATCH 6/7] Drop Net_SSH2::_is_includable() method. --- phpseclib/Net/SSH2.php | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/phpseclib/Net/SSH2.php b/phpseclib/Net/SSH2.php index bc2ee2d8..25795537 100644 --- a/phpseclib/Net/SSH2.php +++ b/phpseclib/Net/SSH2.php @@ -3768,32 +3768,4 @@ class Net_SSH2 } return $this->exit_status; } - - /** - * Is a path includable? - * - * @return Boolean - * @access private - */ - function _is_includable($suffix) - { - // stream_resolve_include_path was introduced in PHP 5.3.2 - if (function_exists('stream_resolve_include_path')) { - return stream_resolve_include_path($suffix) !== false; - } - - $paths = PATH_SEPARATOR == ':' ? - preg_split('#(? Date: Thu, 19 Jun 2014 02:30:08 +0200 Subject: [PATCH 7/7] phpseclib_is_includable() -> phpseclib_resolve_include_path() --- phpseclib/Crypt/Random.php | 16 ++++++++-------- phpseclib/Net/SSH2.php | 10 +++++----- tests/bootstrap.php | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/phpseclib/Crypt/Random.php b/phpseclib/Crypt/Random.php index b34b7980..55c6763e 100644 --- a/phpseclib/Crypt/Random.php +++ b/phpseclib/Crypt/Random.php @@ -194,37 +194,37 @@ if (!function_exists('crypt_random_string')) { // // http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives switch (true) { - case phpseclib_is_includable('Crypt/AES.php'): + case phpseclib_resolve_include_path('Crypt/AES.php'): if (!class_exists('Crypt_AES')) { include_once 'AES.php'; } $crypto = new Crypt_AES(CRYPT_AES_MODE_CTR); break; - case phpseclib_is_includable('Crypt/Twofish.php'): + case phpseclib_resolve_include_path('Crypt/Twofish.php'): if (!class_exists('Crypt_Twofish')) { include_once 'Twofish.php'; } $crypto = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR); break; - case phpseclib_is_includable('Crypt/Blowfish.php'): + case phpseclib_resolve_include_path('Crypt/Blowfish.php'): if (!class_exists('Crypt_Blowfish')) { include_once 'Blowfish.php'; } $crypto = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR); break; - case phpseclib_is_includable('Crypt/TripleDES.php'): + case phpseclib_resolve_include_path('Crypt/TripleDES.php'): if (!class_exists('Crypt_TripleDES')) { include_once 'TripleDES.php'; } $crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR); break; - case phpseclib_is_includable('Crypt/DES.php'): + case phpseclib_resolve_include_path('Crypt/DES.php'): if (!class_exists('Crypt_DES')) { include_once 'DES.php'; } $crypto = new Crypt_DES(CRYPT_DES_MODE_CTR); break; - case phpseclib_is_includable('Crypt/RC4.php'): + case phpseclib_resolve_include_path('Crypt/RC4.php'): if (!class_exists('Crypt_RC4')) { include_once 'RC4.php'; } @@ -261,7 +261,7 @@ if (!function_exists('crypt_random_string')) { } } -if (!function_exists('phpseclib_is_includable')) { +if (!function_exists('phpseclib_resolve_include_path')) { /** * Resolve filename against the include path. * @@ -272,7 +272,7 @@ if (!function_exists('phpseclib_is_includable')) { * @return mixed Filename (string) on success, false otherwise. * @access public */ - function phpseclib_is_includable($filename) + function phpseclib_resolve_include_path($filename) { if (function_exists('stream_resolve_include_path')) { return stream_resolve_include_path($filename); diff --git a/phpseclib/Net/SSH2.php b/phpseclib/Net/SSH2.php index 25795537..3d8f6127 100644 --- a/phpseclib/Net/SSH2.php +++ b/phpseclib/Net/SSH2.php @@ -1107,31 +1107,31 @@ class Net_SSH2 'none' // OPTIONAL no encryption; NOT RECOMMENDED ); - if (phpseclib_is_includable('Crypt/RC4.php') === false) { + if (phpseclib_resolve_include_path('Crypt/RC4.php') === false) { $encryption_algorithms = array_diff( $encryption_algorithms, array('arcfour256', 'arcfour128', 'arcfour') ); } - if (phpseclib_is_includable('Crypt/Rijndael.php') === false) { + if (phpseclib_resolve_include_path('Crypt/Rijndael.php') === false) { $encryption_algorithms = array_diff( $encryption_algorithms, array('aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc') ); } - if (phpseclib_is_includable('Crypt/Twofish.php') === false) { + if (phpseclib_resolve_include_path('Crypt/Twofish.php') === false) { $encryption_algorithms = array_diff( $encryption_algorithms, array('twofish128-ctr', 'twofish192-ctr', 'twofish256-ctr', 'twofish128-cbc', 'twofish192-cbc', 'twofish256-cbc', 'twofish-cbc') ); } - if (phpseclib_is_includable('Crypt/Blowfish.php') === false) { + if (phpseclib_resolve_include_path('Crypt/Blowfish.php') === false) { $encryption_algorithms = array_diff( $encryption_algorithms, array('blowfish-ctr', 'blowfish-cbc') ); } - if (phpseclib_is_includable('Crypt/TripleDES.php') === false) { + if (phpseclib_resolve_include_path('Crypt/TripleDES.php') === false) { $encryption_algorithms = array_diff( $encryption_algorithms, array('3des-ctr', '3des-cbc') diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 2885ada5..561b0a82 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -21,7 +21,7 @@ function phpseclib_autoload($class) { $file = str_replace('_', '/', $class) . '.php'; - if (phpseclib_is_includable($file)) { + if (phpseclib_resolve_include_path($file)) { // @codingStandardsIgnoreStart require $file; // @codingStandardsIgnoreEnd