From 341042da908cce9d489b187ce14607404876db1a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 19 Jan 2021 16:19:29 +0000 Subject: [PATCH] Bump phpseclib/phpseclib from 2.0.25 to 2.0.30 Bumps [phpseclib/phpseclib](https://github.com/phpseclib/phpseclib) from 2.0.25 to 2.0.30. - [Release notes](https://github.com/phpseclib/phpseclib/releases) - [Changelog](https://github.com/phpseclib/phpseclib/blob/master/CHANGELOG.md) - [Commits](https://github.com/phpseclib/phpseclib/compare/2.0.25...2.0.30) Signed-off-by: dependabot-preview[bot] Signed-off-by: Christoph Wurst --- .gitignore | 1 + composer.json | 2 +- composer.lock | 33 ++- composer/InstalledVersions.php | 10 +- composer/installed.json | 33 ++- composer/installed.php | 10 +- .../src/PackageVersions/Versions.php | 4 +- phpseclib/phpseclib/phpseclib/Crypt/Base.php | 17 +- phpseclib/phpseclib/phpseclib/Crypt/Hash.php | 1 - phpseclib/phpseclib/phpseclib/Crypt/RSA.php | 30 ++- .../phpseclib/phpseclib/Crypt/Random.php | 2 +- phpseclib/phpseclib/phpseclib/File/ANSI.php | 50 ++-- phpseclib/phpseclib/phpseclib/File/ASN1.php | 9 +- phpseclib/phpseclib/phpseclib/File/X509.php | 34 +-- .../phpseclib/phpseclib/Math/BigInteger.php | 22 +- phpseclib/phpseclib/phpseclib/Net/SFTP.php | 110 +++++++-- .../phpseclib/phpseclib/Net/SFTP/Stream.php | 5 +- phpseclib/phpseclib/phpseclib/Net/SSH1.php | 5 +- phpseclib/phpseclib/phpseclib/Net/SSH2.php | 231 ++++++++++++------ 19 files changed, 390 insertions(+), 219 deletions(-) diff --git a/.gitignore b/.gitignore index d545f5dc4..0a43b9c67 100644 --- a/.gitignore +++ b/.gitignore @@ -169,6 +169,7 @@ phpseclib/phpseclib/phpunit.xml.dist phpseclib/phpseclib/build/ phpseclib/phpseclib/tests/ phpseclib/phpseclib/travis/ +phpseclib/phpseclib/BACKERS.md phpseclib/phpseclib/CHANGELOG.md phpseclib/phpseclib/README.md phpseclib/phpseclib/composer.json diff --git a/composer.json b/composer.json index 474e6000f..4abdb75ab 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ "patchwork/jsqueeze": "^2.0", "pear/archive_tar": "^1.4.9", "pear/pear-core-minimal": "^v1.10", - "phpseclib/phpseclib": "2.0.25", + "phpseclib/phpseclib": "2.0.30", "php-http/guzzle7-adapter": "^0.1.1", "php-opencloud/openstack": "^3.1", "pimple/pimple": "3.3.1", diff --git a/composer.lock b/composer.lock index 5da9abcf7..28d9351f4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f35d374817174e0d9a6799d28df23f28", + "content-hash": "19396043a057e62803ec1197dda205f9", "packages": [ { "name": "aws/aws-sdk-php", @@ -2719,16 +2719,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "2.0.25", + "version": "2.0.30", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "c18159618ed7cd7ff721ac1a8fec7860a475d2f0" + "reference": "136b9ca7eebef78be14abf90d65c5e57b6bc5d36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/c18159618ed7cd7ff721ac1a8fec7860a475d2f0", - "reference": "c18159618ed7cd7ff721ac1a8fec7860a475d2f0", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/136b9ca7eebef78be14abf90d65c5e57b6bc5d36", + "reference": "136b9ca7eebef78be14abf90d65c5e57b6bc5d36", "shasum": "" }, "require": { @@ -2736,8 +2736,7 @@ }, "require-dev": { "phing/phing": "~2.7", - "phpunit/phpunit": "^4.8.35|^5.7|^6.0", - "sami/sami": "~2.0", + "phpunit/phpunit": "^4.8.35|^5.7|^6.0|^9.4", "squizlabs/php_codesniffer": "~2.0" }, "suggest": { @@ -2807,7 +2806,25 @@ "x.509", "x509" ], - "time": "2020-02-25T04:16:50+00:00" + "support": { + "issues": "https://github.com/phpseclib/phpseclib/issues", + "source": "https://github.com/phpseclib/phpseclib/tree/2.0.30" + }, + "funding": [ + { + "url": "https://github.com/terrafrost", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpseclib", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", + "type": "tidelift" + } + ], + "time": "2020-12-17T05:42:04+00:00" }, { "name": "pimple/pimple", diff --git a/composer/InstalledVersions.php b/composer/InstalledVersions.php index 472662d36..e3957703e 100644 --- a/composer/InstalledVersions.php +++ b/composer/InstalledVersions.php @@ -29,7 +29,7 @@ class InstalledVersions 'aliases' => array ( ), - 'reference' => 'a9db460535cf4f02e8004ccd22fefffe2a11026e', + 'reference' => '89184bb343bc24ea8fbfbd983829e9e74e31cf54', 'name' => 'nextcloud/3rdparty', ), 'versions' => @@ -302,7 +302,7 @@ class InstalledVersions 'aliases' => array ( ), - 'reference' => 'a9db460535cf4f02e8004ccd22fefffe2a11026e', + 'reference' => '89184bb343bc24ea8fbfbd983829e9e74e31cf54', ), 'nextcloud/lognormalizer' => array ( @@ -444,12 +444,12 @@ class InstalledVersions ), 'phpseclib/phpseclib' => array ( - 'pretty_version' => '2.0.25', - 'version' => '2.0.25.0', + 'pretty_version' => '2.0.30', + 'version' => '2.0.30.0', 'aliases' => array ( ), - 'reference' => 'c18159618ed7cd7ff721ac1a8fec7860a475d2f0', + 'reference' => '136b9ca7eebef78be14abf90d65c5e57b6bc5d36', ), 'pimple/pimple' => array ( diff --git a/composer/installed.json b/composer/installed.json index 0a77d842e..657c3322b 100644 --- a/composer/installed.json +++ b/composer/installed.json @@ -2839,17 +2839,17 @@ }, { "name": "phpseclib/phpseclib", - "version": "2.0.25", - "version_normalized": "2.0.25.0", + "version": "2.0.30", + "version_normalized": "2.0.30.0", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "c18159618ed7cd7ff721ac1a8fec7860a475d2f0" + "reference": "136b9ca7eebef78be14abf90d65c5e57b6bc5d36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/c18159618ed7cd7ff721ac1a8fec7860a475d2f0", - "reference": "c18159618ed7cd7ff721ac1a8fec7860a475d2f0", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/136b9ca7eebef78be14abf90d65c5e57b6bc5d36", + "reference": "136b9ca7eebef78be14abf90d65c5e57b6bc5d36", "shasum": "" }, "require": { @@ -2857,8 +2857,7 @@ }, "require-dev": { "phing/phing": "~2.7", - "phpunit/phpunit": "^4.8.35|^5.7|^6.0", - "sami/sami": "~2.0", + "phpunit/phpunit": "^4.8.35|^5.7|^6.0|^9.4", "squizlabs/php_codesniffer": "~2.0" }, "suggest": { @@ -2867,7 +2866,7 @@ "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." }, - "time": "2020-02-25T04:16:50+00:00", + "time": "2020-12-17T05:42:04+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2930,6 +2929,24 @@ "x.509", "x509" ], + "support": { + "issues": "https://github.com/phpseclib/phpseclib/issues", + "source": "https://github.com/phpseclib/phpseclib/tree/2.0.30" + }, + "funding": [ + { + "url": "https://github.com/terrafrost", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpseclib", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", + "type": "tidelift" + } + ], "install-path": "../phpseclib/phpseclib" }, { diff --git a/composer/installed.php b/composer/installed.php index 85cb45d3b..b32088ae1 100644 --- a/composer/installed.php +++ b/composer/installed.php @@ -6,7 +6,7 @@ 'aliases' => array ( ), - 'reference' => 'a9db460535cf4f02e8004ccd22fefffe2a11026e', + 'reference' => '89184bb343bc24ea8fbfbd983829e9e74e31cf54', 'name' => 'nextcloud/3rdparty', ), 'versions' => @@ -279,7 +279,7 @@ 'aliases' => array ( ), - 'reference' => 'a9db460535cf4f02e8004ccd22fefffe2a11026e', + 'reference' => '89184bb343bc24ea8fbfbd983829e9e74e31cf54', ), 'nextcloud/lognormalizer' => array ( @@ -421,12 +421,12 @@ ), 'phpseclib/phpseclib' => array ( - 'pretty_version' => '2.0.25', - 'version' => '2.0.25.0', + 'pretty_version' => '2.0.30', + 'version' => '2.0.30.0', 'aliases' => array ( ), - 'reference' => 'c18159618ed7cd7ff721ac1a8fec7860a475d2f0', + 'reference' => '136b9ca7eebef78be14abf90d65c5e57b6bc5d36', ), 'pimple/pimple' => array ( diff --git a/composer/package-versions-deprecated/src/PackageVersions/Versions.php b/composer/package-versions-deprecated/src/PackageVersions/Versions.php index 9d34770af..4d48c890e 100644 --- a/composer/package-versions-deprecated/src/PackageVersions/Versions.php +++ b/composer/package-versions-deprecated/src/PackageVersions/Versions.php @@ -75,7 +75,7 @@ final class Versions 'php-http/httplug' => '2.2.0@191a0a1b41ed026b717421931f8d3bd2514ffbf9', 'php-http/promise' => '1.1.0@4c4c1f9b7289a2ec57cde7f1e9762a5789506f88', 'php-opencloud/openstack' => 'v3.1.0@7b0eeb63defe533fb802514af3c70855c45eaf1e', - 'phpseclib/phpseclib' => '2.0.25@c18159618ed7cd7ff721ac1a8fec7860a475d2f0', + 'phpseclib/phpseclib' => '2.0.30@136b9ca7eebef78be14abf90d65c5e57b6bc5d36', 'pimple/pimple' => 'v3.3.1@21e45061c3429b1e06233475cc0e1f6fc774d5b0', 'psr/container' => '1.0.0@b7ce3b176482dbbc1245ebf52b181af44c2cf55f', 'psr/http-client' => '1.0.1@2dfb5f6c5eff0e91e20e913f8c5452ed95b86621', @@ -118,7 +118,7 @@ final class Versions 'web-auth/cose-lib' => 'v3.3.1@eea6fae63ff5c81bf98c115b1be5f38a69682c16', 'web-auth/metadata-service' => 'v3.3.1@8488d3a832a38cc81c670fce05de1e515c6e64b1', 'web-auth/webauthn-lib' => 'v3.3.1@e411527a41c1013512fccdfce61681eb36484c77', - 'nextcloud/3rdparty' => 'dev-master@a9db460535cf4f02e8004ccd22fefffe2a11026e', + 'nextcloud/3rdparty' => 'dev-master@89184bb343bc24ea8fbfbd983829e9e74e31cf54', ); private function __construct() diff --git a/phpseclib/phpseclib/phpseclib/Crypt/Base.php b/phpseclib/phpseclib/phpseclib/Crypt/Base.php index 03b176e7b..efbcd242b 100644 --- a/phpseclib/phpseclib/phpseclib/Crypt/Base.php +++ b/phpseclib/phpseclib/phpseclib/Crypt/Base.php @@ -413,7 +413,7 @@ abstract class Base * @var mixed * @access private */ - var $use_inline_crypt; + var $use_inline_crypt = true; /** * If OpenSSL can be used in ECB but not in CTR we can emulate CTR @@ -495,11 +495,6 @@ function __construct($mode = self::MODE_CBC) } $this->_setEngine(); - - // Determining whether inline crypting can be used by the cipher - if ($this->use_inline_crypt !== false) { - $this->use_inline_crypt = version_compare(PHP_VERSION, '5.3.0') >= 0 || function_exists('create_function'); - } } /** @@ -2602,12 +2597,8 @@ function _createInlineCryptFunction($cipher_code) } // Create the $inline function and return its name as string. Ready to run! - if (version_compare(PHP_VERSION, '5.3.0') >= 0) { - eval('$func = function ($_action, &$self, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' } };'); - return $func; - } - - return create_function('$_action, &$self, $_text', $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }'); + eval('$func = function ($_action, &$self, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' } };'); + return $func; } /** @@ -2636,7 +2627,7 @@ function &_getLambdaFunctions() * * @see self::_setupInlineCrypt() * @access private - * @param $bytes + * @param string $bytes * @return string */ function _hashInlineCryptFunction($bytes) diff --git a/phpseclib/phpseclib/phpseclib/Crypt/Hash.php b/phpseclib/phpseclib/phpseclib/Crypt/Hash.php index a61668209..248b65ef7 100644 --- a/phpseclib/phpseclib/phpseclib/Crypt/Hash.php +++ b/phpseclib/phpseclib/phpseclib/Crypt/Hash.php @@ -849,7 +849,6 @@ function _not($int) * _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the * possibility of overflow exists, care has to be taken. BigInteger could be used but this should be faster. * - * @param int $... * @return int * @see self::_sha256() * @access private diff --git a/phpseclib/phpseclib/phpseclib/Crypt/RSA.php b/phpseclib/phpseclib/phpseclib/Crypt/RSA.php index 72be6eeb1..17e2b8329 100644 --- a/phpseclib/phpseclib/phpseclib/Crypt/RSA.php +++ b/phpseclib/phpseclib/phpseclib/Crypt/RSA.php @@ -537,7 +537,7 @@ function __construct() * @access public * @param int $bits * @param int $timeout - * @param array $p + * @param array $partial */ function createKey($bits = 1024, $timeout = false, $partial = array()) { @@ -716,7 +716,12 @@ function createKey($bits = 1024, $timeout = false, $partial = array()) * * @access private * @see self::setPrivateKeyFormat() - * @param string $RSAPrivateKey + * @param Math_BigInteger $n + * @param Math_BigInteger $e + * @param Math_BigInteger $d + * @param array $primes + * @param array $exponents + * @param array $coefficients * @return string */ function _convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients) @@ -997,8 +1002,9 @@ function _convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients) * * @access private * @see self::setPublicKeyFormat() - * @param string $RSAPrivateKey - * @return string + * @param Math_BigInteger $n + * @param Math_BigInteger $e + * @return string|array */ function _convertPublicKey($n, $e) { @@ -1539,6 +1545,8 @@ function. As is, the definitive authority on this encoding scheme isn't the IET return $components; } + + return false; } /** @@ -1878,7 +1886,6 @@ function setPrivateKey($key = false, $type = false) * * @see self::getPublicKey() * @access public - * @param string $key * @param int $type optional */ function getPublicKey($type = self::PUBLIC_FORMAT_PKCS8) @@ -1936,7 +1943,6 @@ function getPublicKeyFingerprint($algorithm = 'md5') * * @see self::getPublicKey() * @access public - * @param string $key * @param int $type optional * @return mixed */ @@ -1961,8 +1967,7 @@ function getPrivateKey($type = self::PUBLIC_FORMAT_PKCS1) * * @see self::getPrivateKey() * @access private - * @param string $key - * @param int $type optional + * @param int $mode optional */ function _getPrivatePublicKey($mode = self::PUBLIC_FORMAT_PKCS8) { @@ -2179,7 +2184,7 @@ function setMGFHash($hash) * of the hash function Hash) and 0. * * @access public - * @param int $format + * @param int $sLen */ function setSaltLength($sLen) { @@ -2212,7 +2217,7 @@ function _i2osp($x, $xLen) * See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}. * * @access private - * @param string $x + * @param int|string|resource $x * @return \phpseclib\Math\BigInteger */ function _os2ip($x) @@ -2439,7 +2444,7 @@ function _rsavp1($s) * * @access private * @param string $mgfSeed - * @param int $mgfLen + * @param int $maskLen * @return string */ function _mgf1($mgfSeed, $maskLen) @@ -2948,6 +2953,7 @@ function _rsassa_pkcs1_v1_5_sign($m) * * @access private * @param string $m + * @param string $s * @return string */ function _rsassa_pkcs1_v1_5_verify($m, $s) @@ -3088,7 +3094,7 @@ function encrypt($plaintext) * * @see self::encrypt() * @access public - * @param string $plaintext + * @param string $ciphertext * @return string */ function decrypt($ciphertext) diff --git a/phpseclib/phpseclib/phpseclib/Crypt/Random.php b/phpseclib/phpseclib/phpseclib/Crypt/Random.php index e5c819c76..8f53eb319 100644 --- a/phpseclib/phpseclib/phpseclib/Crypt/Random.php +++ b/phpseclib/phpseclib/phpseclib/Crypt/Random.php @@ -98,7 +98,7 @@ static function string($length) } if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource() $temp = fread($fp, $length); - if (strlen($temp) != $length) { + if (strlen($temp) == $length) { return $temp; } } diff --git a/phpseclib/phpseclib/phpseclib/File/ANSI.php b/phpseclib/phpseclib/phpseclib/File/ANSI.php index 5ff1f2ea1..b6874d357 100644 --- a/phpseclib/phpseclib/phpseclib/File/ANSI.php +++ b/phpseclib/phpseclib/phpseclib/File/ANSI.php @@ -203,8 +203,7 @@ function setDimensions($x, $y) /** * Set the number of lines that should be logged past the terminal height * - * @param int $x - * @param int $y + * @param int $history * @access public */ function setHistory($history) @@ -272,7 +271,7 @@ function appendString($source) case "\x1B[K": // Clear screen from cursor right $this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x); - array_splice($this->attrs[$this->y], $this->x + 1, $this->max_x - $this->x, array_fill($this->x, $this->max_x - $this->x - 1, $this->base_attr_cell)); + array_splice($this->attrs[$this->y], $this->x + 1, $this->max_x - $this->x, array_fill($this->x, $this->max_x - ($this->x - 1), $this->base_attr_cell)); break; case "\x1B[2K": // Clear entire line $this->screen[$this->y] = str_repeat(' ', $this->x); @@ -316,19 +315,20 @@ function appendString($source) $mods = explode(';', $match[1]); foreach ($mods as $mod) { switch ($mod) { - case 0: // Turn off character attributes + case '': + case '0': // Turn off character attributes $attr_cell = clone $this->base_attr_cell; break; - case 1: // Turn bold mode on + case '1': // Turn bold mode on $attr_cell->bold = true; break; - case 4: // Turn underline mode on + case '4': // Turn underline mode on $attr_cell->underline = true; break; - case 5: // Turn blinking mode on + case '5': // Turn blinking mode on $attr_cell->blink = true; break; - case 7: // Turn reverse video on + case '7': // Turn reverse video on $attr_cell->reverse = !$attr_cell->reverse; $temp = $attr_cell->background; $attr_cell->background = $attr_cell->foreground; @@ -341,23 +341,23 @@ function appendString($source) $back = &$attr_cell->{ $attr_cell->reverse ? 'foreground' : 'background' }; switch ($mod) { // @codingStandardsIgnoreStart - case 30: $front = 'black'; break; - case 31: $front = 'red'; break; - case 32: $front = 'green'; break; - case 33: $front = 'yellow'; break; - case 34: $front = 'blue'; break; - case 35: $front = 'magenta'; break; - case 36: $front = 'cyan'; break; - case 37: $front = 'white'; break; - - case 40: $back = 'black'; break; - case 41: $back = 'red'; break; - case 42: $back = 'green'; break; - case 43: $back = 'yellow'; break; - case 44: $back = 'blue'; break; - case 45: $back = 'magenta'; break; - case 46: $back = 'cyan'; break; - case 47: $back = 'white'; break; + case '30': $front = 'black'; break; + case '31': $front = 'red'; break; + case '32': $front = 'green'; break; + case '33': $front = 'yellow'; break; + case '34': $front = 'blue'; break; + case '35': $front = 'magenta'; break; + case '36': $front = 'cyan'; break; + case '37': $front = 'white'; break; + + case '40': $back = 'black'; break; + case '41': $back = 'red'; break; + case '42': $back = 'green'; break; + case '43': $back = 'yellow'; break; + case '44': $back = 'blue'; break; + case '45': $back = 'magenta'; break; + case '46': $back = 'cyan'; break; + case '47': $back = 'white'; break; // @codingStandardsIgnoreEnd default: diff --git a/phpseclib/phpseclib/phpseclib/File/ASN1.php b/phpseclib/phpseclib/phpseclib/File/ASN1.php index 3b8f11bd7..807ca88ce 100644 --- a/phpseclib/phpseclib/phpseclib/File/ASN1.php +++ b/phpseclib/phpseclib/phpseclib/File/ASN1.php @@ -493,6 +493,10 @@ function _decode_ber($encoded, $start = 0, $encoded_pos = 0) */ function asn1map($decoded, $mapping, $special = array()) { + if (!is_array($decoded)) { + return false; + } + if (isset($mapping['explicit']) && is_array($decoded['content'])) { $decoded = $decoded['content'][0]; } @@ -786,7 +790,7 @@ function asn1map($decoded, $mapping, $special = array()) * * @param string $source * @param string $mapping - * @param int $idx + * @param array $special * @return string * @access public */ @@ -802,6 +806,7 @@ function encodeDER($source, $mapping, $special = array()) * @param string $source * @param string $mapping * @param int $idx + * @param array $special * @return string * @access private */ @@ -1157,7 +1162,7 @@ function _decodeOID($content) * Called by _encode_der() * * @access private - * @param string $content + * @param string $source * @return string */ function _encodeOID($source) diff --git a/phpseclib/phpseclib/phpseclib/File/X509.php b/phpseclib/phpseclib/phpseclib/File/X509.php index ddbc61595..3520efdc1 100644 --- a/phpseclib/phpseclib/phpseclib/File/X509.php +++ b/phpseclib/phpseclib/phpseclib/File/X509.php @@ -1608,7 +1608,7 @@ function saveX509($cert, $format = self::FORMAT_PEM) * Map extension values from octet string to extension-specific internal * format. * - * @param array ref $root + * @param array $root (by reference) * @param string $path * @param object $asn1 * @access private @@ -1661,7 +1661,7 @@ function _mapInExtensions(&$root, $path, $asn1) * Map extension values from extension-specific internal format to * octet string. * - * @param array ref $root + * @param array $root (by reference) * @param string $path * @param object $asn1 * @access private @@ -1727,7 +1727,7 @@ function _mapOutExtensions(&$root, $path, $asn1) * Map attribute values from ANY type to attribute-specific internal * format. * - * @param array ref $root + * @param array $root (by reference) * @param string $path * @param object $asn1 * @access private @@ -1768,7 +1768,7 @@ function _mapInAttributes(&$root, $path, $asn1) * Map attribute values from attribute-specific internal format to * ANY type. * - * @param array ref $root + * @param array $root (by reference) * @param string $path * @param object $asn1 * @access private @@ -1811,7 +1811,7 @@ function _mapOutAttributes(&$root, $path, $asn1) * Map DN values from ANY type to DN-specific internal * format. * - * @param array ref $root + * @param array $root (by reference) * @param string $path * @param object $asn1 * @access private @@ -1841,7 +1841,7 @@ function _mapInDNs(&$root, $path, $asn1) * Map DN values from DN-specific internal format to * ANY type. * - * @param array ref $root + * @param array $root (by reference) * @param string $path * @param object $asn1 * @access private @@ -3195,7 +3195,8 @@ function getPublicKey() /** * Load a Certificate Signing Request * - * @param string $csr + * @param string|array $csr + * @param int $mode * @access public * @return mixed */ @@ -3332,7 +3333,7 @@ function saveCSR($csr, $format = self::FORMAT_PEM) * * https://developer.mozilla.org/en-US/docs/HTML/Element/keygen * - * @param string $csr + * @param string|array $spkac * @access public * @return mixed */ @@ -3403,7 +3404,7 @@ function loadSPKAC($spkac) /** * Save a SPKAC CSR request * - * @param array $csr + * @param string|array $spkac * @param int $format optional * @access public * @return string @@ -3447,6 +3448,7 @@ function saveSPKAC($spkac, $format = self::FORMAT_PEM) * Load a Certificate Revocation List * * @param string $crl + * @param int $mode * @access public * @return mixed */ @@ -4043,8 +4045,7 @@ function signCRL($issuer, $crl, $signatureAlgorithm = 'sha1WithRSAEncryption') /** * X.509 certificate signing helper function. * - * @param object $key - * @param \phpseclib\File\X509 $subject + * @param \phpseclib\File\X509 $key * @param string $signatureAlgorithm * @access public * @return mixed @@ -4119,7 +4120,7 @@ function setEndDate($date) * Set Serial Number * * @param string $serial - * @param $base optional + * @param int $base optional * @access public */ function setSerialNumber($serial, $base = -256) @@ -4782,7 +4783,6 @@ function setDomain() * Set the IP Addresses's which the cert is to be valid for * * @access public - * @param string $ipAddress optional */ function setIPAddress() { @@ -5054,11 +5054,13 @@ function _extractBER($str) * subject=/O=organization/OU=org unit/CN=common name * issuer=/O=organization/CN=common name */ - $temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1); - // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff - $temp = preg_replace('#-+[^-]+-+#', '', $temp); + $temp = strlen($str) <= ini_get('pcre.backtrack_limit') ? + preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1) : + $str; // remove new lines $temp = str_replace(array("\r", "\n", ' '), '', $temp); + // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff + $temp = preg_replace('#^-+[^-]+-+|-+[^-]+-+$#', '', $temp); $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false; return $temp != false ? $temp : $str; } diff --git a/phpseclib/phpseclib/phpseclib/Math/BigInteger.php b/phpseclib/phpseclib/phpseclib/Math/BigInteger.php index e7f664670..9df0bf0f2 100644 --- a/phpseclib/phpseclib/phpseclib/Math/BigInteger.php +++ b/phpseclib/phpseclib/phpseclib/Math/BigInteger.php @@ -243,7 +243,7 @@ class BigInteger * ?> * * - * @param $x base-10 number or base-$base number if $base set. + * @param int|string|resource $x base-10 number or base-$base number if $base set. * @param int $base * @return \phpseclib\Math\BigInteger * @access public @@ -1994,7 +1994,7 @@ function _squareReduce($x, $n, $mode) * * @see self::_slidingWindow() * @access private - * @param \phpseclib\Math\BigInteger + * @param \phpseclib\Math\BigInteger $n * @return \phpseclib\Math\BigInteger */ function _mod2($n) @@ -2688,7 +2688,7 @@ function abs() * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y). * * @param \phpseclib\Math\BigInteger $y - * @return int < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal. + * @return int that is < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal. * @access public * @see self::equals() * @internal Could return $this->subtract($x), but that's not as fast as what we do do. @@ -3090,7 +3090,7 @@ function bitwise_rightRotate($shift) * * Byte length is equal to $length. Uses \phpseclib\Crypt\Random if it's loaded and mt_rand if it's not. * - * @param int $length + * @param int $size * @return \phpseclib\Math\BigInteger * @access private */ @@ -3557,7 +3557,7 @@ function _rshift($shift) * * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision * - * @param \phpseclib\Math\BigInteger + * @param \phpseclib\Math\BigInteger $result * @return \phpseclib\Math\BigInteger * @see self::_trim() * @access private @@ -3634,8 +3634,8 @@ function _trim($value) /** * Array Repeat * - * @param $input Array - * @param $multiplier mixed + * @param array $input + * @param mixed $multiplier * @return array * @access private */ @@ -3649,8 +3649,8 @@ function _array_repeat($input, $multiplier) * * Shifts binary strings $shift bits, essentially multiplying by 2**$shift. * - * @param $x String - * @param $shift Integer + * @param string $x (by reference) + * @param int $shift * @return string * @access private */ @@ -3678,8 +3678,8 @@ function _base256_lshift(&$x, $shift) * * Shifts binary strings $shift bits, essentially dividing by 2**$shift and returning the remainder. * - * @param $x String - * @param $shift Integer + * @param string $x (by referenc) + * @param int $shift * @return string * @access private */ diff --git a/phpseclib/phpseclib/phpseclib/Net/SFTP.php b/phpseclib/phpseclib/phpseclib/Net/SFTP.php index 074b4f7f3..8ae43fa04 100644 --- a/phpseclib/phpseclib/phpseclib/Net/SFTP.php +++ b/phpseclib/phpseclib/phpseclib/Net/SFTP.php @@ -259,6 +259,16 @@ class SFTP extends SSH2 */ var $requestBuffer = array(); + /** + * Preserve timestamps on file downloads / uploads + * + * @see self::get() + * @see self::put() + * @var bool + * @access private + */ + var $preserveTime = false; + /** * Default Constructor. * @@ -397,21 +407,21 @@ function __construct($host, $port = 22, $timeout = 10) if (!defined('NET_SFTP_QUEUE_SIZE')) { define('NET_SFTP_QUEUE_SIZE', 32); } + if (!defined('NET_SFTP_UPLOAD_QUEUE_SIZE')) { + define('NET_SFTP_UPLOAD_QUEUE_SIZE', 1024); + } } /** * Login * * @param string $username - * @param string $password * @return bool * @access public */ function login($username) { - $args = func_get_args(); - $this->auth[] = $args; - if (!call_user_func_array(array(&$this, '_login'), $args)) { + if (!call_user_func_array('parent::login', func_get_args())) { return false; } @@ -718,7 +728,7 @@ function _realpath($path) } } - if ($path[0] != '/') { + if (!strlen($path) || $path[0] != '/') { $path = $this->pwd . '/' . $path; } @@ -1197,6 +1207,9 @@ function _remove_from_stat_cache($path) $temp = &$this->stat_cache; $max = count($dirs) - 1; foreach ($dirs as $i => $dir) { + if (!is_array($temp)) { + return false; + } if ($i === $max) { unset($temp[$dir]); return true; @@ -1213,7 +1226,7 @@ function _remove_from_stat_cache($path) * * Mainly used by file_exists * - * @param string $dir + * @param string $path * @return mixed * @access private */ @@ -1223,6 +1236,9 @@ function _query_stat_cache($path) $temp = &$this->stat_cache; foreach ($dirs as $dir) { + if (!is_array($temp)) { + return null; + } if (!isset($temp[$dir])) { return null; } @@ -1765,6 +1781,8 @@ function symlink($target, $link) * Creates a directory. * * @param string $dir + * @param int $mode + * @param bool $recursive * @return bool * @access public */ @@ -1775,9 +1793,6 @@ function mkdir($dir, $mode = -1, $recursive = false) } $dir = $this->_realpath($dir); - // by not providing any permissions, hopefully the server will use the logged in users umask - their - // default permissions. - $attr = $mode == -1 ? "\0\0\0\0" : pack('N2', NET_SFTP_ATTR_PERMISSIONS, $mode & 07777); if ($recursive) { $dirs = explode('/', preg_replace('#/(?=/)|/$#', '', $dir)); @@ -1788,24 +1803,26 @@ function mkdir($dir, $mode = -1, $recursive = false) for ($i = 0; $i < count($dirs); $i++) { $temp = array_slice($dirs, 0, $i + 1); $temp = implode('/', $temp); - $result = $this->_mkdir_helper($temp, $attr); + $result = $this->_mkdir_helper($temp, $mode); } return $result; } - return $this->_mkdir_helper($dir, $attr); + return $this->_mkdir_helper($dir, $mode); } /** * Helper function for directory creation * * @param string $dir + * @param int $mode * @return bool * @access private */ - function _mkdir_helper($dir, $attr) + function _mkdir_helper($dir, $mode) { - if (!$this->_send_sftp_packet(NET_SFTP_MKDIR, pack('Na*a*', strlen($dir), $dir, $attr))) { + // send SSH_FXP_MKDIR without any attributes (that's what the \0\0\0\0 is doing) + if (!$this->_send_sftp_packet(NET_SFTP_MKDIR, pack('Na*a*', strlen($dir), $dir, "\0\0\0\0"))) { return false; } @@ -1824,6 +1841,10 @@ function _mkdir_helper($dir, $attr) return false; } + if ($mode !== -1) { + $this->chmod($mode, $dir); + } + return true; } @@ -2015,10 +2036,10 @@ function put($remote_file, $data, $mode = self::SOURCE_STRING, $start = -1, $loc $sent = 0; $size = $size < 0 ? ($size & 0x7FFFFFFF) + 0x80000000 : $size; - $sftp_packet_size = 4096; // PuTTY uses 4096 - // make the SFTP packet be exactly 4096 bytes by including the bytes in the NET_SFTP_WRITE packets "header" + $sftp_packet_size = $this->max_sftp_packet; + // make the SFTP packet be exactly the SFTP packet size by including the bytes in the NET_SFTP_WRITE packets "header" $sftp_packet_size-= strlen($handle) + 25; - $i = 0; + $i = $j = 0; while ($dataCallback || ($size === 0 || $sent < $size)) { if ($dataCallback) { $temp = call_user_func($dataCallback, $sftp_packet_size); @@ -2034,7 +2055,7 @@ function put($remote_file, $data, $mode = self::SOURCE_STRING, $start = -1, $loc $subtemp = $offset + $sent; $packet = pack('Na*N3a*', strlen($handle), $handle, $subtemp / 4294967296, $subtemp, strlen($temp), $temp); - if (!$this->_send_sftp_packet(NET_SFTP_WRITE, $packet)) { + if (!$this->_send_sftp_packet(NET_SFTP_WRITE, $packet, $j)) { if ($mode & self::SOURCE_LOCAL_FILE) { fclose($fp); } @@ -2046,8 +2067,9 @@ function put($remote_file, $data, $mode = self::SOURCE_STRING, $start = -1, $loc } $i++; + $j++; - if ($i == NET_SFTP_QUEUE_SIZE) { + if ($i == NET_SFTP_UPLOAD_QUEUE_SIZE) { if (!$this->_read_put_responses($i)) { $i = 0; break; @@ -2065,7 +2087,14 @@ function put($remote_file, $data, $mode = self::SOURCE_STRING, $start = -1, $loc } if ($mode & self::SOURCE_LOCAL_FILE) { - fclose($fp); + if ($this->preserveTime) { + $stat = fstat($fp); + $this->touch($remote_file, $stat['mtime'], $stat['atime']); + } + + if (isset($fp) && is_resource($fp)) { + fclose($fp); + } } return $this->_close_handle($handle); @@ -2188,7 +2217,7 @@ function get($remote_file, $local_file = false, $offset = 0, $length = -1, $prog $res_offset = $stat['size']; } else { $res_offset = 0; - if ($local_file !== false) { + if ($local_file !== false && !is_callable($local_file)) { $fp = fopen($local_file, 'wb'); if (!$fp) { return false; @@ -2198,7 +2227,7 @@ function get($remote_file, $local_file = false, $offset = 0, $length = -1, $prog } } - $fclose_check = $local_file !== false && !is_resource($local_file); + $fclose_check = $local_file !== false && !is_callable($local_file) && !is_resource($local_file); $start = $offset; $read = 0; @@ -2219,9 +2248,6 @@ function get($remote_file, $local_file = false, $offset = 0, $length = -1, $prog } $packet = null; $read+= $packet_size; - if (is_callable($progressCallback)) { - call_user_func($progressCallback, $read); - } $i++; } @@ -2248,9 +2274,14 @@ function get($remote_file, $local_file = false, $offset = 0, $length = -1, $prog $offset+= strlen($temp); if ($local_file === false) { $content.= $temp; + } elseif (is_callable($local_file)) { + $local_file($temp); } else { fputs($fp, $temp); } + if (is_callable($progressCallback)) { + call_user_func($progressCallback, $offset); + } $temp = null; break; case NET_SFTP_STATUS: @@ -2282,6 +2313,11 @@ function get($remote_file, $local_file = false, $offset = 0, $length = -1, $prog if ($fclose_check) { fclose($fp); + + if ($this->preserveTime) { + $stat = $this->stat($remote_file); + touch($local_file, $stat['mtime'], $stat['atime']); + } } if (!$this->_close_handle($handle)) { @@ -2703,6 +2739,7 @@ function _get_lstat_cache_prop($path, $prop) * * @param string $path * @param string $prop + * @param mixed $type * @return mixed * @access private */ @@ -2943,6 +2980,7 @@ function _parseLongname($longname) * * @param int $type * @param string $data + * @param int $request_id * @see self::_get_sftp_packet() * @see self::_send_channel_packet() * @return bool @@ -2950,6 +2988,10 @@ function _parseLongname($longname) */ function _send_sftp_packet($type, $data, $request_id = 1) { + // in SSH2.php the timeout is cumulative per function call. eg. exec() will + // timeout after 10s. but for SFTP.php it's cumulative per packet + $this->curTimeout = $this->timeout; + $packet = $this->use_request_id ? pack('NCNa*', strlen($data) + 5, $type, $request_id, $data) : pack('NCa*', strlen($data) + 1, $type, $data); @@ -3166,4 +3208,24 @@ function _disconnect($reason) $this->pwd = false; parent::_disconnect($reason); } + + /** + * Enable Date Preservation + * + * @access public + */ + function enableDatePreservation() + { + $this->preserveTime = true; + } + + /** + * Disable Date Preservation + * + * @access public + */ + function disableDatePreservation() + { + $this->preserveTime = false; + } } diff --git a/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php b/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php index d2c4425de..1a44b10a0 100644 --- a/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php +++ b/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php @@ -626,7 +626,6 @@ function _mkdir($path, $mode, $options) * $options. What does 8 correspond to? * * @param string $path - * @param int $mode * @param int $options * @return bool * @access public @@ -768,8 +767,8 @@ function _stream_close() * If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not * NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method. * - * @param string - * @param array + * @param string $name + * @param array $arguments * @return mixed * @access public */ diff --git a/phpseclib/phpseclib/phpseclib/Net/SSH1.php b/phpseclib/phpseclib/phpseclib/Net/SSH1.php index ff48d5436..e372b8b92 100644 --- a/phpseclib/phpseclib/phpseclib/Net/SSH1.php +++ b/phpseclib/phpseclib/phpseclib/Net/SSH1.php @@ -812,6 +812,7 @@ function setTimeout($timeout) * @see self::interactiveRead() * @see self::interactiveWrite() * @param string $cmd + * @param bool $block * @return mixed * @access public */ @@ -1385,7 +1386,6 @@ function _rsa_crypt($m, $key) * named constants from it, using the value as the name of the constant and the index as the value of the constant. * If any of the constants that would be defined already exists, none of the constants will be defined. * - * @param array $array * @access private */ function _define_array() @@ -1584,7 +1584,8 @@ function getServerIdentification() * * Makes sure that only the last 1MB worth of packets will be logged * - * @param string $data + * @param int $protocol_flags + * @param string $message * @access private */ function _append_log($protocol_flags, $message) diff --git a/phpseclib/phpseclib/phpseclib/Net/SSH2.php b/phpseclib/phpseclib/phpseclib/Net/SSH2.php index e105b4d0c..e2571190b 100644 --- a/phpseclib/phpseclib/phpseclib/Net/SSH2.php +++ b/phpseclib/phpseclib/phpseclib/Net/SSH2.php @@ -687,6 +687,14 @@ class SSH2 */ var $curTimeout; + /** + * Keep Alive Interval + * + * @see self::setKeepAlive() + * @access private + */ + var $keepAlive; + /** * Real-time log file pointer * @@ -1538,6 +1546,32 @@ function _key_exchange($kexinit_payload_server = false) return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } + $server_host_key_algorithm = $this->_array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms); + if ($server_host_key_algorithm === false) { + user_error('No compatible server host key algorithms found'); + return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); + } + + $mac_algorithm_in = $this->_array_intersect_first($s2c_mac_algorithms, $this->mac_algorithms_server_to_client); + if ($mac_algorithm_in === false) { + user_error('No compatible server to client message authentication algorithms found'); + return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); + } + + $compression_algorithm_out = $this->_array_intersect_first($c2s_compression_algorithms, $this->compression_algorithms_client_to_server); + if ($compression_algorithm_out === false) { + user_error('No compatible client to server compression algorithms found'); + return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); + } + //$this->decompress = $compression_algorithm_out == 'zlib'; + + $compression_algorithm_in = $this->_array_intersect_first($s2c_compression_algorithms, $this->compression_algorithms_client_to_server); + if ($compression_algorithm_in === false) { + user_error('No compatible server to client compression algorithms found'); + return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); + } + //$this->compress = $compression_algorithm_in == 'zlib'; + // Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty. $exchange_hash_rfc4419 = ''; @@ -1773,12 +1807,6 @@ function _key_exchange($kexinit_payload_server = false) $this->session_id = $this->exchange_hash; } - $server_host_key_algorithm = $this->_array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms); - if ($server_host_key_algorithm === false) { - user_error('No compatible server host key algorithms found'); - return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - } - switch ($server_host_key_algorithm) { case 'ssh-dss': $expected_key_format = 'ssh-dss'; @@ -1903,14 +1931,14 @@ function _key_exchange($kexinit_payload_server = false) $this->decrypt->decrypt(str_repeat("\0", 1536)); } - $mac_algorithm = $this->_array_intersect_first($c2s_mac_algorithms, $this->mac_algorithms_client_to_server); - if ($mac_algorithm === false) { + $mac_algorithm_out = $this->_array_intersect_first($c2s_mac_algorithms, $this->mac_algorithms_client_to_server); + if ($mac_algorithm_out === false) { user_error('No compatible client to server message authentication algorithms found'); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $createKeyLength = 0; // ie. $mac_algorithm == 'none' - switch ($mac_algorithm) { + switch ($mac_algorithm_out) { case 'hmac-sha2-256': $this->hmac_create = new Hash('sha256'); $createKeyLength = 32; @@ -1931,17 +1959,11 @@ function _key_exchange($kexinit_payload_server = false) $this->hmac_create = new Hash('md5-96'); $createKeyLength = 16; } - $this->hmac_create->name = $mac_algorithm; - - $mac_algorithm = $this->_array_intersect_first($s2c_mac_algorithms, $this->mac_algorithms_server_to_client); - if ($mac_algorithm === false) { - user_error('No compatible server to client message authentication algorithms found'); - return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - } + $this->hmac_create->name = $mac_algorithm_out; $checkKeyLength = 0; $this->hmac_size = 0; - switch ($mac_algorithm) { + switch ($mac_algorithm_in) { case 'hmac-sha2-256': $this->hmac_check = new Hash('sha256'); $checkKeyLength = 32; @@ -1967,7 +1989,7 @@ function _key_exchange($kexinit_payload_server = false) $checkKeyLength = 16; $this->hmac_size = 12; } - $this->hmac_check->name = $mac_algorithm; + $this->hmac_check->name = $mac_algorithm_in; $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'E' . $this->session_id); while ($createKeyLength > strlen($key)) { @@ -1981,20 +2003,6 @@ function _key_exchange($kexinit_payload_server = false) } $this->hmac_check->setKey(substr($key, 0, $checkKeyLength)); - $compression_algorithm = $this->_array_intersect_first($c2s_compression_algorithms, $this->compression_algorithms_client_to_server); - if ($compression_algorithm === false) { - user_error('No compatible client to server compression algorithms found'); - return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - } - //$this->decompress = $compression_algorithm == 'zlib'; - - $compression_algorithm = $this->_array_intersect_first($s2c_compression_algorithms, $this->compression_algorithms_client_to_server); - if ($compression_algorithm === false) { - user_error('No compatible server to client compression algorithms found'); - return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - } - //$this->compress = $compression_algorithm == 'zlib'; - return true; } @@ -2112,8 +2120,6 @@ function _bad_algorithm_candidate($algorithm) * The $password parameter can be a plaintext password, a \phpseclib\Crypt\RSA object or an array * * @param string $username - * @param mixed $password - * @param mixed $... * @return bool * @see self::_login() * @access public @@ -2122,6 +2128,17 @@ function login($username) { $args = func_get_args(); $this->auth[] = $args; + + // try logging with 'none' as an authentication method first since that's what + // PuTTY does + if (substr($this->server_identifier, 0, 13) != 'SSH-2.0-CoreFTP') { + if ($this->_login($username)) { + return true; + } + if (count($args) == 1) { + return false; + } + } return call_user_func_array(array(&$this, '_login'), $args); } @@ -2129,8 +2146,6 @@ function login($username) * Login Helper * * @param string $username - * @param mixed $password - * @param mixed $... * @return bool * @see self::_login_helper() * @access private @@ -2391,7 +2406,6 @@ function _keyboard_interactive_login($username, $password) /** * Handle the keyboard-interactive requests / responses. * - * @param string $responses... * @return bool * @access private */ @@ -2536,7 +2550,7 @@ function _ssh_agent_login($username, $agent) * Login with an RSA private key * * @param string $username - * @param \phpseclib\Crypt\RSA $password + * @param \phpseclib\Crypt\RSA $privatekey * @return bool * @access private * @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis} @@ -2671,6 +2685,19 @@ function setTimeout($timeout) $this->timeout = $this->curTimeout = $timeout; } + /** + * Set Keep Alive + * + * Sends an SSH2_MSG_IGNORE message every x seconds, if x is a positive non-zero number. + * + * @param mixed $timeout + * @access public + */ + function setKeepAlive($interval) + { + $this->keepAlive = $interval; + } + /** * Get the output from stdError * @@ -2995,7 +3022,7 @@ function _get_open_channel() * @see self::write() * @param string $expect * @param int $mode - * @return string + * @return string|bool * @access public */ function read($expect = '', $mode = self::READ_SIMPLE) @@ -3309,6 +3336,54 @@ function _reset_connection($reason) */ function _get_binary_packet($skip_channel_filter = false) { + if ($skip_channel_filter) { + $read = array($this->fsock); + $write = $except = null; + + if ($this->curTimeout <= 0) { + if ($this->keepAlive <= 0) { + @stream_select($read, $write, $except, null); + } else { + if (!@stream_select($read, $write, $except, $this->keepAlive) && !count($read)) { + $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0)); + return $this->_get_binary_packet(true); + } + } + } else { + if ($this->curTimeout < 0) { + $this->is_timeout = true; + return true; + } + + $read = array($this->fsock); + $write = $except = null; + + $start = microtime(true); + + if ($this->keepAlive > 0 && $this->keepAlive < $this->curTimeout) { + if (!@stream_select($read, $write, $except, $this->keepAlive) && !count($read)) { + $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0)); + $elapsed = microtime(true) - $start; + $this->curTimeout-= $elapsed; + return $this->_get_binary_packet(true); + } + $elapsed = microtime(true) - $start; + $this->curTimeout-= $elapsed; + } + + $sec = floor($this->curTimeout); + $usec = 1000000 * ($this->curTimeout - $sec); + + // on windows this returns a "Warning: Invalid CRT parameters detected" error + if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) { + $this->is_timeout = true; + return true; + } + $elapsed = microtime(true) - $start; + $this->curTimeout-= $elapsed; + } + } + if (!is_resource($this->fsock) || feof($this->fsock)) { $this->bitmap = 0; user_error('Connection closed prematurely'); @@ -3460,9 +3535,19 @@ function _filter($payload, $skip_channel_filter) // only called when we've already logged in if (($this->bitmap & self::MASK_CONNECTED) && $this->isAuthenticated()) { switch (ord($payload[0])) { + case NET_SSH2_MSG_CHANNEL_REQUEST: + if (strlen($payload) == 31) { + extract(unpack('cpacket_type/Nchannel/Nlength', $payload)); + if (substr($payload, 9, $length) == 'keepalive@openssh.com' && isset($this->server_channels[$channel])) { + if (ord(substr($payload, 9 + $length))) { // want reply + $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_SUCCESS, $this->server_channels[$channel])); + } + $payload = $this->_get_binary_packet($skip_channel_filter); + } + } + break; case NET_SSH2_MSG_CHANNEL_DATA: case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA: - case NET_SSH2_MSG_CHANNEL_REQUEST: case NET_SSH2_MSG_CHANNEL_CLOSE: case NET_SSH2_MSG_CHANNEL_EOF: if (!$skip_channel_filter && !empty($this->server_channels)) { @@ -3642,8 +3727,9 @@ function isPTYEnabled() * * Returns the data as a string if it's available and false if not. * - * @param $client_channel - * @return mixed + * @param int $client_channel + * @param bool $skip_extended + * @return mixed|bool * @access private */ function _get_channel_packet($client_channel, $skip_extended = false) @@ -3657,36 +3743,13 @@ function _get_channel_packet($client_channel, $skip_extended = false) $response = $this->binary_packet_buffer; $this->binary_packet_buffer = false; } else { - $read = array($this->fsock); - $write = $except = null; - - if (!$this->curTimeout) { - @stream_select($read, $write, $except, null); - } else { - if ($this->curTimeout < 0) { - $this->is_timeout = true; - return true; - } - - $read = array($this->fsock); - $write = $except = null; - - $start = microtime(true); - $sec = floor($this->curTimeout); - $usec = 1000000 * ($this->curTimeout - $sec); - // on windows this returns a "Warning: Invalid CRT parameters detected" error - if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) { - $this->is_timeout = true; - if ($client_channel == self::CHANNEL_EXEC && !$this->request_pty) { - $this->_close_channel($client_channel); - } - return true; + $response = $this->_get_binary_packet(true); + if ($response === true && $this->is_timeout) { + if ($client_channel == self::CHANNEL_EXEC && !$this->request_pty) { + $this->_close_channel($client_channel); } - $elapsed = microtime(true) - $start; - $this->curTimeout-= $elapsed; + return true; } - - $response = $this->_get_binary_packet(true); if ($response === false) { $this->bitmap = 0; user_error('Connection closed by server'); @@ -3885,7 +3948,7 @@ function _get_channel_packet($client_channel, $skip_extended = false) $this->channel_buffers[$channel][] = $data; break; case NET_SSH2_MSG_CHANNEL_CLOSE: - $this->curTimeout = 0; + $this->curTimeout = 5; if ($this->bitmap & self::MASK_SHELL) { $this->bitmap&= ~self::MASK_SHELL; @@ -3953,7 +4016,7 @@ function _send_binary_packet($data, $logged = null) $packet.= $hmac; $start = microtime(true); - $result = strlen($packet) == fputs($this->fsock, $packet); + $result = strlen($packet) == @fputs($this->fsock, $packet); $stop = microtime(true); if (defined('NET_SSH2_LOGGING')) { @@ -3973,7 +4036,8 @@ function _send_binary_packet($data, $logged = null) * * Makes sure that only the last 1MB worth of packets will be logged * - * @param string $data + * @param string $message_number + * @param string $message * @access private */ function _append_log($message_number, $message) @@ -4114,11 +4178,15 @@ function _close_channel($client_channel, $want_reply = false) $this->channel_status[$client_channel] = NET_SSH2_MSG_CHANNEL_CLOSE; - $this->curTimeout = 0; + $this->curTimeout = 5; while (!is_bool($this->_get_channel_packet($client_channel))) { } + if ($this->is_timeout) { + $this->disconnect(); + } + if ($want_reply) { $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel])); } @@ -4174,7 +4242,6 @@ function _string_shift(&$string, $index = 1) * named constants from it, using the value as the name of the constant and the index as the value of the constant. * If any of the constants that would be defined already exists, none of the constants will be defined. * - * @param array $array * @access private */ function _define_array() @@ -4590,11 +4657,15 @@ function getSupportedEncryptionAlgorithms() //'none' // OPTIONAL no encryption; NOT RECOMMENDED ); - $engines = array( - Base::ENGINE_OPENSSL, - Base::ENGINE_MCRYPT, - Base::ENGINE_INTERNAL - ); + if ($this->crypto_engine) { + $engines = array($this->crypto_engine); + } else { + $engines = array( + Base::ENGINE_OPENSSL, + Base::ENGINE_MCRYPT, + Base::ENGINE_INTERNAL + ); + } $ciphers = array(); foreach ($engines as $engine) {