diff --git a/composer.json b/composer.json index 7afe9e648..f662e28b9 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,7 @@ "php-ds/php-ds": "^1.3", "php-http/guzzle7-adapter": "^1.0.0", "php-opencloud/openstack": "^3.1", - "phpseclib/phpseclib": "2.0.31", + "phpseclib/phpseclib": "2.0.32", "pimple/pimple": "^3.4.0", "psr/container": "^1.1.1", "psr/event-dispatcher": "^1.0", diff --git a/composer.lock b/composer.lock index da487fb8e..758998675 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": "bf93471807f72af547c8ebe544a4f69b", + "content-hash": "90923a2f086d237c4c89fd6576d3dee0", "packages": [ { "name": "aws/aws-sdk-php", @@ -2815,16 +2815,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "2.0.31", + "version": "2.0.32", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "233a920cb38636a43b18d428f9a8db1f0a1a08f4" + "reference": "f5c4c19880d45d0be3e7d24ae8ac434844a898cd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/233a920cb38636a43b18d428f9a8db1f0a1a08f4", - "reference": "233a920cb38636a43b18d428f9a8db1f0a1a08f4", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/f5c4c19880d45d0be3e7d24ae8ac434844a898cd", + "reference": "f5c4c19880d45d0be3e7d24ae8ac434844a898cd", "shasum": "" }, "require": { @@ -2904,7 +2904,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/2.0.31" + "source": "https://github.com/phpseclib/phpseclib/tree/2.0.32" }, "funding": [ { @@ -2920,7 +2920,7 @@ "type": "tidelift" } ], - "time": "2021-04-06T13:56:45+00:00" + "time": "2021-06-12T12:12:59+00:00" }, { "name": "pimple/pimple", diff --git a/composer/autoload_files.php b/composer/autoload_files.php index 9fb40d7ef..6d3aa74aa 100644 --- a/composer/autoload_files.php +++ b/composer/autoload_files.php @@ -117,9 +117,9 @@ '4af1dca6db8c527c6eed27bff85ff0e5' => $vendorDir . '/thecodingmachine/safe/generated/yaz.php', 'fe43ca06499ac37bc2dedd823af71eb5' => $vendorDir . '/thecodingmachine/safe/generated/zip.php', '356736db98a6834f0a886b8d509b0ecd' => $vendorDir . '/thecodingmachine/safe/generated/zlib.php', + '8a9dc1de0ca7e01f3e08231539562f61' => $vendorDir . '/aws/aws-sdk-php/src/functions.php', '538ca81a9a966a6716601ecf48f4eaef' => $vendorDir . '/opis/closure/functions.php', - 'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php', '2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php', '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php', - '8a9dc1de0ca7e01f3e08231539562f61' => $vendorDir . '/aws/aws-sdk-php/src/functions.php', + 'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php', ); diff --git a/composer/autoload_static.php b/composer/autoload_static.php index f64ffb50d..59cc63ad8 100644 --- a/composer/autoload_static.php +++ b/composer/autoload_static.php @@ -118,11 +118,11 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652 '4af1dca6db8c527c6eed27bff85ff0e5' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/yaz.php', 'fe43ca06499ac37bc2dedd823af71eb5' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/zip.php', '356736db98a6834f0a886b8d509b0ecd' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/zlib.php', + '8a9dc1de0ca7e01f3e08231539562f61' => __DIR__ . '/..' . '/aws/aws-sdk-php/src/functions.php', '538ca81a9a966a6716601ecf48f4eaef' => __DIR__ . '/..' . '/opis/closure/functions.php', - 'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php', '2c102faa651ef8ea5874edb585946bce' => __DIR__ . '/..' . '/swiftmailer/swiftmailer/lib/swift_required.php', '8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php', - '8a9dc1de0ca7e01f3e08231539562f61' => __DIR__ . '/..' . '/aws/aws-sdk-php/src/functions.php', + 'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php', ); public static $prefixLengthsPsr4 = array ( diff --git a/composer/installed.json b/composer/installed.json index dbfab8016..7ed2cb371 100644 --- a/composer/installed.json +++ b/composer/installed.json @@ -2934,17 +2934,17 @@ }, { "name": "phpseclib/phpseclib", - "version": "2.0.31", - "version_normalized": "2.0.31.0", + "version": "2.0.32", + "version_normalized": "2.0.32.0", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "233a920cb38636a43b18d428f9a8db1f0a1a08f4" + "reference": "f5c4c19880d45d0be3e7d24ae8ac434844a898cd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/233a920cb38636a43b18d428f9a8db1f0a1a08f4", - "reference": "233a920cb38636a43b18d428f9a8db1f0a1a08f4", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/f5c4c19880d45d0be3e7d24ae8ac434844a898cd", + "reference": "f5c4c19880d45d0be3e7d24ae8ac434844a898cd", "shasum": "" }, "require": { @@ -2961,7 +2961,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": "2021-04-06T13:56:45+00:00", + "time": "2021-06-12T12:12:59+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3026,7 +3026,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/2.0.31" + "source": "https://github.com/phpseclib/phpseclib/tree/2.0.32" }, "funding": [ { diff --git a/composer/installed.php b/composer/installed.php index ed330ed4f..b5d513608 100644 --- a/composer/installed.php +++ b/composer/installed.php @@ -5,7 +5,7 @@ 'type' => 'library', 'install_path' => __DIR__ . '/../', 'aliases' => array(), - 'reference' => '8ad453e849bfce8d360f4cc4fa547214930f880e', + 'reference' => 'ace54d905eb58dce4866c6b2a5ad80382a2e9019', 'name' => 'nextcloud/3rdparty', 'dev' => true, ), @@ -286,7 +286,7 @@ 'type' => 'library', 'install_path' => __DIR__ . '/../', 'aliases' => array(), - 'reference' => '8ad453e849bfce8d360f4cc4fa547214930f880e', + 'reference' => 'ace54d905eb58dce4866c6b2a5ad80382a2e9019', 'dev_requirement' => false, ), 'nextcloud/lognormalizer' => array( @@ -425,12 +425,12 @@ 'dev_requirement' => false, ), 'phpseclib/phpseclib' => array( - 'pretty_version' => '2.0.31', - 'version' => '2.0.31.0', + 'pretty_version' => '2.0.32', + 'version' => '2.0.32.0', 'type' => 'library', 'install_path' => __DIR__ . '/../phpseclib/phpseclib', 'aliases' => array(), - 'reference' => '233a920cb38636a43b18d428f9a8db1f0a1a08f4', + 'reference' => 'f5c4c19880d45d0be3e7d24ae8ac434844a898cd', 'dev_requirement' => false, ), 'pimple/pimple' => array( diff --git a/composer/package-versions-deprecated/src/PackageVersions/Versions.php b/composer/package-versions-deprecated/src/PackageVersions/Versions.php index 387024e2c..d057aeda5 100644 --- a/composer/package-versions-deprecated/src/PackageVersions/Versions.php +++ b/composer/package-versions-deprecated/src/PackageVersions/Versions.php @@ -76,7 +76,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.31@233a920cb38636a43b18d428f9a8db1f0a1a08f4', + 'phpseclib/phpseclib' => '2.0.32@f5c4c19880d45d0be3e7d24ae8ac434844a898cd', 'pimple/pimple' => 'v3.4.0@86406047271859ffc13424a048541f4531f53601', 'psr/container' => '1.1.1@8622567409010282b7aeebe4bb841fe98b58dcaf', 'psr/event-dispatcher' => '1.0.0@dbefd12671e8a14ec7f180cab83036ed26714bb0', @@ -120,7 +120,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@8ad453e849bfce8d360f4cc4fa547214930f880e', + 'nextcloud/3rdparty' => 'dev-master@ace54d905eb58dce4866c6b2a5ad80382a2e9019', ); private function __construct() diff --git a/phpseclib/phpseclib/phpseclib/Crypt/RSA.php b/phpseclib/phpseclib/phpseclib/Crypt/RSA.php index 811d039d3..e26fe41dd 100644 --- a/phpseclib/phpseclib/phpseclib/Crypt/RSA.php +++ b/phpseclib/phpseclib/phpseclib/Crypt/RSA.php @@ -2580,9 +2580,9 @@ function _rsaes_oaep_decrypt($c, $l = '') $offset+= $patternMatch ? 0 : 1; } - // we do & instead of && to avoid https://en.wikipedia.org/wiki/Short-circuit_evaluation + // we do | instead of || to avoid https://en.wikipedia.org/wiki/Short-circuit_evaluation // to protect against timing attacks - if (!$hashesMatch & !$patternMatch) { + if (!$hashesMatch | !$patternMatch) { user_error('Decryption error'); return false; } diff --git a/phpseclib/phpseclib/phpseclib/File/ASN1.php b/phpseclib/phpseclib/phpseclib/File/ASN1.php index dc5b78f64..d1a7719f8 100644 --- a/phpseclib/phpseclib/phpseclib/File/ASN1.php +++ b/phpseclib/phpseclib/phpseclib/File/ASN1.php @@ -993,7 +993,10 @@ function _encode_der($source, $mapping, $idx = null, $special = array()) case self::TYPE_GENERALIZED_TIME: $format = $mapping['type'] == self::TYPE_UTC_TIME ? 'y' : 'Y'; $format.= 'mdHis'; + // if $source does _not_ include timezone information within it then assume that the timezone is GMT $date = new DateTime($source, new DateTimeZone('GMT')); + // if $source _does_ include timezone information within it then convert the time to GMT + $date->setTimezone(new DateTimeZone('GMT')); $value = $date->format($format) . 'Z'; break; case self::TYPE_BIT_STRING: diff --git a/phpseclib/phpseclib/phpseclib/File/X509.php b/phpseclib/phpseclib/phpseclib/File/X509.php index 7b1b1cfad..fa3c0264e 100644 --- a/phpseclib/phpseclib/phpseclib/File/X509.php +++ b/phpseclib/phpseclib/phpseclib/File/X509.php @@ -5058,7 +5058,7 @@ function _extractBER($str) $temp = $str; } else { $temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1); - $temp = preg_replace('#-+END.*[\r\n ]*.*#ms', '', $str, 1); + $temp = preg_replace('#-+END.*[\r\n ]*.*#ms', '', $temp, 1); } // remove new lines $temp = str_replace(array("\r", "\n", ' '), '', $temp); diff --git a/phpseclib/phpseclib/phpseclib/Net/SFTP.php b/phpseclib/phpseclib/phpseclib/Net/SFTP.php index 34741831b..f9bb22352 100644 --- a/phpseclib/phpseclib/phpseclib/Net/SFTP.php +++ b/phpseclib/phpseclib/phpseclib/Net/SFTP.php @@ -269,6 +269,16 @@ class SFTP extends SSH2 */ var $preserveTime = false; + /** + * Was the last packet due to the channels being closed or not? + * + * @see self::get() + * @see self::get_sftp_packet() + * @var bool + * @access private + */ + var $channel_close = false; + /** * Default Constructor. * @@ -425,6 +435,17 @@ function login($username) return false; } + return $this->_init_sftp_connection(); + } + + /** + * (Re)initializes the SFTP channel + * + * @return bool + * @access private + */ + function _init_sftp_connection() + { $this->window_size_server_to_client[self::CHANNEL] = $this->window_size; $packet = pack( @@ -2293,7 +2314,13 @@ function get($remote_file, $local_file = false, $offset = 0, $length = -1, $prog if ($fclose_check) { fclose($fp); } - user_error('Expected SSH_FX_DATA or SSH_FXP_STATUS'); + // maybe the file was successfully transferred, maybe it wasn't + if ($this->channel_close) { + $this->_init_sftp_connection(); + return false; + } else { + user_error('Expected SSH_FX_DATA or SSH_FXP_STATUS'); + } } $response = null; } @@ -3055,6 +3082,8 @@ function _reset_connection($reason) */ function _get_sftp_packet($request_id = null) { + $this->channel_close = false; + if (isset($request_id) && isset($this->requestBuffer[$request_id])) { $this->packet_type = $this->requestBuffer[$request_id]['packet_type']; $temp = $this->requestBuffer[$request_id]['packet']; @@ -3071,7 +3100,10 @@ function _get_sftp_packet($request_id = null) // SFTP packet length while (strlen($this->packet_buffer) < 4) { $temp = $this->_get_channel_packet(self::CHANNEL, true); - if (is_bool($temp)) { + if ($temp === true) { + if ($this->channel_status[self::CHANNEL] === NET_SSH2_MSG_CHANNEL_CLOSE) { + $this->channel_close = true; + } $this->packet_type = false; $this->packet_buffer = ''; return false; diff --git a/phpseclib/phpseclib/phpseclib/Net/SSH2.php b/phpseclib/phpseclib/phpseclib/Net/SSH2.php index f8f8dcfde..e449d987a 100644 --- a/phpseclib/phpseclib/phpseclib/Net/SSH2.php +++ b/phpseclib/phpseclib/phpseclib/Net/SSH2.php @@ -970,6 +970,14 @@ class SSH2 */ var $auth = array(); + /** + * The authentication methods that may productively continue authentication. + * + * @see https://tools.ietf.org/html/rfc4252#section-5.1 + * @var array|null + */ + private $auth_methods_to_continue = null; + /** * Default Constructor. * @@ -1347,6 +1355,7 @@ function _generate_identifier() function _key_exchange($kexinit_payload_server = false) { $preferred = $this->preferred; + $send_kex = true; $kex_algorithms = isset($preferred['kex']) ? $preferred['kex'] : @@ -1430,7 +1439,7 @@ function _key_exchange($kexinit_payload_server = false) 0 ); - if ($this->send_kex_first) { + if ($kexinit_payload_server === false) { if (!$this->_send_binary_packet($kexinit_payload_client)) { return false; } @@ -1446,6 +1455,8 @@ function _key_exchange($kexinit_payload_server = false) user_error('Expected SSH_MSG_KEXINIT'); return false; } + + $send_kex = false; } $response = $kexinit_payload_server; @@ -1518,7 +1529,7 @@ function _key_exchange($kexinit_payload_server = false) extract(unpack('Cfirst_kex_packet_follows', $this->_string_shift($response, 1))); $first_kex_packet_follows = $first_kex_packet_follows != 0; - if (!$this->send_kex_first && !$this->_send_binary_packet($kexinit_payload_client)) { + if ($send_kex && !$this->_send_binary_packet($kexinit_payload_client)) { return false; } @@ -2131,7 +2142,7 @@ function login($username) // 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 (substr($this->server_identifier, 0, 13) != 'SSH-2.0-CoreFTP' && $this->auth_methods_to_continue === null) { if ($this->_login($username)) { return true; } @@ -2275,7 +2286,9 @@ function _login_helper($username, $password = null) case NET_SSH2_MSG_USERAUTH_SUCCESS: $this->bitmap |= self::MASK_LOGIN; return true; - //case NET_SSH2_MSG_USERAUTH_FAILURE: + case NET_SSH2_MSG_USERAUTH_FAILURE: + extract(unpack('Nmethodlistlen', $this->_string_shift($response, 4))); + $this->auth_methods_to_continue = explode(',', $this->_string_shift($response, $methodlistlen)); default: return false; } @@ -2347,6 +2360,7 @@ function _login_helper($username, $password = null) } extract(unpack('Nlength', $this->_string_shift($response, 4))); $auth_methods = explode(',', $this->_string_shift($response, $length)); + $this->auth_methods_to_continue = $auth_methods; if (!strlen($response)) { return false; } @@ -2519,6 +2533,8 @@ function _keyboard_interactive_process() case NET_SSH2_MSG_USERAUTH_SUCCESS: return true; case NET_SSH2_MSG_USERAUTH_FAILURE: + extract(unpack('Nmethodlistlen', $this->_string_shift($response, 4))); + $this->auth_methods_to_continue = explode(',', $this->_string_shift($response, $methodlistlen)); return false; } @@ -2627,8 +2643,9 @@ function _privatekey_login($username, $privatekey) if (strlen($response) < 4) { return false; } - extract(unpack('Nlength', $this->_string_shift($response, 4))); - $this->errors[] = 'SSH_MSG_USERAUTH_FAILURE: ' . $this->_string_shift($response, $length); + extract(unpack('Nmethodlistlen', $this->_string_shift($response, 4))); + $this->auth_methods_to_continue = explode(',', $this->_string_shift($response, $methodlistlen)); + $this->errors[] = 'SSH_MSG_USERAUTH_FAILURE'; return false; case NET_SSH2_MSG_USERAUTH_PK_OK: // we'll just take it on faith that the public key blob and the public key algorithm name are as @@ -2669,6 +2686,8 @@ function _privatekey_login($username, $privatekey) switch ($type) { case NET_SSH2_MSG_USERAUTH_FAILURE: // either the login is bad or the server employs multi-factor authentication + extract(unpack('Nmethodlistlen', $this->_string_shift($response, 4))); + $this->auth_methods_to_continue = explode(',', $this->_string_shift($response, $methodlistlen)); return false; case NET_SSH2_MSG_USERAUTH_SUCCESS: $this->bitmap |= self::MASK_LOGIN; @@ -3319,7 +3338,7 @@ function _get_binary_packet($skip_channel_filter = false) $read = array($this->fsock); $write = $except = null; - if ($this->curTimeout <= 0) { + if (!$this->curTimeout) { if ($this->keepAlive <= 0) { @stream_select($read, $write, $except, null); } else { @@ -3513,6 +3532,10 @@ function _filter($payload, $skip_channel_filter) // only called when we've already logged in if (($this->bitmap & self::MASK_CONNECTED) && $this->isAuthenticated()) { + if (is_bool($payload)) { + return $payload; + } + switch (ord($payload[0])) { case NET_SSH2_MSG_CHANNEL_REQUEST: if (strlen($payload) == 31) { @@ -5143,4 +5166,15 @@ function _updateLogHistory($old, $new) ); } } + + /** + * Return the list of authentication methods that may productively continue authentication. + * + * @see https://tools.ietf.org/html/rfc4252#section-5.1 + * @return array|null + */ + public function getAuthMethodsToContinue() + { + return $this->auth_methods_to_continue; + } }