From 1d2219713ab10d22f2784178009c4d08b97a831e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Apr 2024 18:27:30 +0000 Subject: [PATCH 1/2] chore(deps): Bump phpseclib/phpseclib from 2.0.45 to 2.0.47 Bumps [phpseclib/phpseclib](https://github.com/phpseclib/phpseclib) from 2.0.45 to 2.0.47. - [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.45...2.0.47) --- updated-dependencies: - dependency-name: phpseclib/phpseclib dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- composer.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index 52b0500f1..e6859ab7c 100644 --- a/composer.lock +++ b/composer.lock @@ -2874,16 +2874,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "2.0.45", + "version": "2.0.47", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "28d8f438a0064c9de80857e3270d071495544640" + "reference": "b7d7d90ee7df7f33a664b4aea32d50a305d35adb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/28d8f438a0064c9de80857e3270d071495544640", - "reference": "28d8f438a0064c9de80857e3270d071495544640", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/b7d7d90ee7df7f33a664b4aea32d50a305d35adb", + "reference": "b7d7d90ee7df7f33a664b4aea32d50a305d35adb", "shasum": "" }, "require": { @@ -2964,7 +2964,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/2.0.45" + "source": "https://github.com/phpseclib/phpseclib/tree/2.0.47" }, "funding": [ { @@ -2980,7 +2980,7 @@ "type": "tidelift" } ], - "time": "2023-09-15T20:55:47+00:00" + "time": "2024-02-26T04:55:38+00:00" }, { "name": "pimple/pimple", From 81faccc9d03f36c0f28c4224e9e0057a3e0a69a4 Mon Sep 17 00:00:00 2001 From: nextcloud-command Date: Thu, 4 Apr 2024 18:30:36 +0000 Subject: [PATCH 2/2] chore(autoloader): Dump autoloader Signed-off-by: nextcloud-command --- composer/installed.json | 14 ++-- composer/installed.php | 10 +-- phpseclib/phpseclib/phpseclib/Crypt/AES.php | 42 ++-------- phpseclib/phpseclib/phpseclib/Crypt/Base.php | 2 + phpseclib/phpseclib/phpseclib/Crypt/Hash.php | 2 +- phpseclib/phpseclib/phpseclib/Crypt/RSA.php | 1 + .../phpseclib/phpseclib/Crypt/Rijndael.php | 4 +- phpseclib/phpseclib/phpseclib/File/ASN1.php | 5 ++ phpseclib/phpseclib/phpseclib/File/X509.php | 3 +- .../phpseclib/phpseclib/Math/BigInteger.php | 55 ++++++++++++-- phpseclib/phpseclib/phpseclib/Net/SFTP.php | 5 +- phpseclib/phpseclib/phpseclib/Net/SSH2.php | 76 +++++++++++++++++-- 12 files changed, 151 insertions(+), 68 deletions(-) diff --git a/composer/installed.json b/composer/installed.json index 961a7c9a9..9823e6294 100644 --- a/composer/installed.json +++ b/composer/installed.json @@ -2997,17 +2997,17 @@ }, { "name": "phpseclib/phpseclib", - "version": "2.0.45", - "version_normalized": "2.0.45.0", + "version": "2.0.47", + "version_normalized": "2.0.47.0", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "28d8f438a0064c9de80857e3270d071495544640" + "reference": "b7d7d90ee7df7f33a664b4aea32d50a305d35adb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/28d8f438a0064c9de80857e3270d071495544640", - "reference": "28d8f438a0064c9de80857e3270d071495544640", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/b7d7d90ee7df7f33a664b4aea32d50a305d35adb", + "reference": "b7d7d90ee7df7f33a664b4aea32d50a305d35adb", "shasum": "" }, "require": { @@ -3025,7 +3025,7 @@ "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations.", "ext-xml": "Install the XML extension to load XML formatted public keys." }, - "time": "2023-09-15T20:55:47+00:00", + "time": "2024-02-26T04:55:38+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3090,7 +3090,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/2.0.45" + "source": "https://github.com/phpseclib/phpseclib/tree/2.0.47" }, "funding": [ { diff --git a/composer/installed.php b/composer/installed.php index 878a0ea10..a53a828bd 100644 --- a/composer/installed.php +++ b/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'nextcloud/3rdparty', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => 'c1dfb58d1a08450a3451688a55ce2bd2a5bf79f1', + 'reference' => '1d2219713ab10d22f2784178009c4d08b97a831e', 'type' => 'library', 'install_path' => __DIR__ . '/../', 'aliases' => array(), @@ -319,7 +319,7 @@ 'nextcloud/3rdparty' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => 'c1dfb58d1a08450a3451688a55ce2bd2a5bf79f1', + 'reference' => '1d2219713ab10d22f2784178009c4d08b97a831e', 'type' => 'library', 'install_path' => __DIR__ . '/../', 'aliases' => array(), @@ -419,9 +419,9 @@ 'dev_requirement' => false, ), 'phpseclib/phpseclib' => array( - 'pretty_version' => '2.0.45', - 'version' => '2.0.45.0', - 'reference' => '28d8f438a0064c9de80857e3270d071495544640', + 'pretty_version' => '2.0.47', + 'version' => '2.0.47.0', + 'reference' => 'b7d7d90ee7df7f33a664b4aea32d50a305d35adb', 'type' => 'library', 'install_path' => __DIR__ . '/../phpseclib/phpseclib', 'aliases' => array(), diff --git a/phpseclib/phpseclib/phpseclib/Crypt/AES.php b/phpseclib/phpseclib/phpseclib/Crypt/AES.php index 7d8cb8b03..9903db105 100644 --- a/phpseclib/phpseclib/phpseclib/Crypt/AES.php +++ b/phpseclib/phpseclib/phpseclib/Crypt/AES.php @@ -84,43 +84,13 @@ function setBlockLength($length) */ function setKeyLength($length) { - switch ($length) { - case 160: - $length = 192; - break; - case 224: - $length = 256; - } parent::setKeyLength($length); - } - - /** - * Sets the key. - * - * Rijndael supports five different key lengths, AES only supports three. - * - * @see \phpseclib\Crypt\Rijndael:setKey() - * @see setKeyLength() - * @access public - * @param string $key - */ - function setKey($key) - { - parent::setKey($key); - - if (!$this->explicit_key_length) { - $length = strlen($key); - switch (true) { - case $length <= 16: - $this->key_length = 16; - break; - case $length <= 24: - $this->key_length = 24; - break; - default: - $this->key_length = 32; - } - $this->_setEngine(); + switch ($this->key_length) { + case 20: + $this->key_length = 24; + break; + case 28: + $this->key_length = 32; } } } diff --git a/phpseclib/phpseclib/phpseclib/Crypt/Base.php b/phpseclib/phpseclib/phpseclib/Crypt/Base.php index 7bb357a7b..ab5944cde 100644 --- a/phpseclib/phpseclib/phpseclib/Crypt/Base.php +++ b/phpseclib/phpseclib/phpseclib/Crypt/Base.php @@ -514,6 +514,8 @@ function __construct($mode = self::MODE_CBC) switch (true) { // PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster case (PHP_OS & "\xDF\xDF\xDF") === 'WIN': + case !function_exists('php_uname'): + case !is_string(php_uname('m')): case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM': case PHP_INT_SIZE == 8: define('CRYPT_BASE_USE_REG_INTVAL', true); diff --git a/phpseclib/phpseclib/phpseclib/Crypt/Hash.php b/phpseclib/phpseclib/phpseclib/Crypt/Hash.php index 248b65ef7..5e5d13d4c 100644 --- a/phpseclib/phpseclib/phpseclib/Crypt/Hash.php +++ b/phpseclib/phpseclib/phpseclib/Crypt/Hash.php @@ -866,7 +866,7 @@ function _add() $result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument; } - if ((php_uname('m') & "\xDF\xDF\xDF") != 'ARM') { + if (function_exists('php_uname') && is_string(php_uname('m')) && (php_uname('m') & "\xDF\xDF\xDF") != 'ARM') { return fmod($result, $mod); } diff --git a/phpseclib/phpseclib/phpseclib/Crypt/RSA.php b/phpseclib/phpseclib/phpseclib/Crypt/RSA.php index a8fa23156..fec689585 100644 --- a/phpseclib/phpseclib/phpseclib/Crypt/RSA.php +++ b/phpseclib/phpseclib/phpseclib/Crypt/RSA.php @@ -570,6 +570,7 @@ function createKey($bits = 1024, $timeout = false, $partial = array()) $publickey = call_user_func_array(array($this, '_convertPublicKey'), array_values($this->_parseKey($publickey, self::PUBLIC_FORMAT_PKCS1))); // clear the buffer of error strings stemming from a minimalistic openssl.cnf + // https://github.com/php/php-src/issues/11054 talks about other errors this'll pick up while (openssl_error_string() !== false) { } diff --git a/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php b/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php index 7a6be2a67..4665738e1 100644 --- a/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php +++ b/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php @@ -814,7 +814,6 @@ function _setupInlineCrypt() // Generating encrypt code: $init_encrypt.= ' - static $tables; if (empty($tables)) { $tables = &$self->_getTables(); } @@ -871,7 +870,6 @@ function _setupInlineCrypt() // Generating decrypt code: $init_decrypt.= ' - static $invtables; if (empty($invtables)) { $invtables = &$self->_getInvTables(); } @@ -928,7 +926,7 @@ function _setupInlineCrypt() $lambda_functions[$code_hash] = $this->_createInlineCryptFunction( array( - 'init_crypt' => '', + 'init_crypt' => 'static $tables; static $invtables;', 'init_encrypt' => $init_encrypt, 'init_decrypt' => $init_decrypt, 'encrypt_block' => $encrypt_block, diff --git a/phpseclib/phpseclib/phpseclib/File/ASN1.php b/phpseclib/phpseclib/phpseclib/File/ASN1.php index 099e1ec01..dba99de73 100644 --- a/phpseclib/phpseclib/phpseclib/File/ASN1.php +++ b/phpseclib/phpseclib/phpseclib/File/ASN1.php @@ -1176,6 +1176,11 @@ function _decodeOID($content) $oid = array(); $pos = 0; $len = strlen($content); + // see https://github.com/openjdk/jdk/blob/2deb318c9f047ec5a4b160d66a4b52f93688ec42/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java#L55 + if ($len > 4096) { + //user_error('Object Identifier size is limited to 4096 bytes'); + return false; + } if (ord($content[$len - 1]) & 0x80) { return false; diff --git a/phpseclib/phpseclib/phpseclib/File/X509.php b/phpseclib/phpseclib/phpseclib/File/X509.php index 05f61e828..7b8d96e29 100644 --- a/phpseclib/phpseclib/phpseclib/File/X509.php +++ b/phpseclib/phpseclib/phpseclib/File/X509.php @@ -2070,7 +2070,8 @@ function validateURL($url) if ($names = $this->getExtension('id-ce-subjectAltName')) { foreach ($names as $name) { foreach ($name as $key => $value) { - $value = str_replace(array('.', '*'), array('\.', '[^.]*'), $value); + $value = preg_quote($value); + $value = str_replace('\*', '[^.]*', $value); switch ($key) { case 'dNSName': /* From RFC2818 "HTTP over TLS": diff --git a/phpseclib/phpseclib/phpseclib/Math/BigInteger.php b/phpseclib/phpseclib/phpseclib/Math/BigInteger.php index 81b69ace6..7747a95b6 100644 --- a/phpseclib/phpseclib/phpseclib/Math/BigInteger.php +++ b/phpseclib/phpseclib/phpseclib/Math/BigInteger.php @@ -163,23 +163,23 @@ class BigInteger * * @see __construct() */ - protected static $base; - protected static $baseFull; - protected static $maxDigit; - protected static $msb; + static $base; + static $baseFull; + static $maxDigit; + static $msb; /** * $max10 in greatest $max10Len satisfying * $max10 = 10**$max10Len <= 2**$base. */ - protected static $max10; + static $max10; /** * $max10Len in greatest $max10Len satisfying * $max10 = 10**$max10Len <= 2**$base. */ - protected static $max10Len; - protected static $maxDigit2; + static $max10Len; + static $maxDigit2; /**#@-*/ /** @@ -729,6 +729,33 @@ function toString() return $result; } + /** + * Return the size of a BigInteger in bits + * + * @return int + */ + function getLength() + { + if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) { + return strlen($this->toBits()); + } + + $max = count($this->value) - 1; + return $max != -1 ? + $max * self::$base + intval(ceil(log($this->value[$max] + 1, 2))) : + 0; + } + + /** + * Return the size of a BigInteger in bytes + * + * @return int + */ + function getLengthInBytes() + { + return (int) ceil($this->getLength() / 8); + } + /** * Copy an object * @@ -3237,6 +3264,11 @@ function randomPrime($arg1, $arg2 = false, $timeout = false) $min = $temp; } + $length = $max->getLength(); + if ($length > 8196) { + user_error('Generation of random prime numbers larger than 8196 has been disabled'); + } + static $one, $two; if (!isset($one)) { $one = new static(1); @@ -3344,7 +3376,14 @@ function _make_odd() */ function isPrime($t = false) { - $length = strlen($this->toBytes()); + $length = $this->getLength(); + // OpenSSL limits RSA keys to 16384 bits. The length of an RSA key is equal to the length of the modulo, which is + // produced by multiplying the primes p and q by one another. The largest number two 8196 bit primes can produce is + // a 16384 bit number so, basically, 8196 bit primes are the largest OpenSSL will generate and if that's the largest + // that it'll generate it also stands to reason that that's the largest you'll be able to test primality on + if ($length > 8196) { + user_error('Primality testing is not supported for numbers larger than 8196 bits'); + } if (!$t) { // see HAC 4.49 "Note (controlling the error probability)" diff --git a/phpseclib/phpseclib/phpseclib/Net/SFTP.php b/phpseclib/phpseclib/phpseclib/Net/SFTP.php index 332dade63..28b568062 100644 --- a/phpseclib/phpseclib/phpseclib/Net/SFTP.php +++ b/phpseclib/phpseclib/phpseclib/Net/SFTP.php @@ -3640,6 +3640,7 @@ function _reset_connection($reason) $this->use_request_id = false; $this->pwd = false; $this->requestBuffer = array(); + $this->partial_init = false; } /** @@ -3788,7 +3789,7 @@ function getSFTPLog() } /** - * Returns all errors + * Returns all errors on the SFTP layer * * @return array * @access public @@ -3799,7 +3800,7 @@ function getSFTPErrors() } /** - * Returns the last error + * Returns the last error on the SFTP layer * * @return string * @access public diff --git a/phpseclib/phpseclib/phpseclib/Net/SSH2.php b/phpseclib/phpseclib/phpseclib/Net/SSH2.php index 2a0b28fae..607cc2145 100644 --- a/phpseclib/phpseclib/phpseclib/Net/SSH2.php +++ b/phpseclib/phpseclib/phpseclib/Net/SSH2.php @@ -1096,10 +1096,20 @@ class SSH2 */ var $smartMFA = true; + /** + * Extra packets counter + * + * @var bool + * @access private + */ + var $extra_packets; + /** * Default Constructor. * * $host can either be a string, representing the host, or a stream resource. + * If $host is a stream resource then $port doesn't do anything, altho $timeout + * still will be used * * @param mixed $host * @param int $port @@ -1117,6 +1127,7 @@ function __construct($host, $port = 22, $timeout = 10) 4 => 'NET_SSH2_MSG_DEBUG', 5 => 'NET_SSH2_MSG_SERVICE_REQUEST', 6 => 'NET_SSH2_MSG_SERVICE_ACCEPT', + 7 => 'NET_SSH2_MSG_EXT_INFO', // RFC 8308 20 => 'NET_SSH2_MSG_KEXINIT', 21 => 'NET_SSH2_MSG_NEWKEYS', 30 => 'NET_SSH2_MSG_KEXDH_INIT', @@ -1189,6 +1200,8 @@ function __construct($host, $port = 22, $timeout = 10) 31 => 'NET_SSH2_MSG_KEX_ECDH_REPLY') ); + $this->timeout = $timeout; + if (is_resource($host)) { $this->fsock = $host; return; @@ -1197,7 +1210,6 @@ function __construct($host, $port = 22, $timeout = 10) if (is_string($host)) { $this->host = $host; $this->port = $port; - $this->timeout = $timeout; } } @@ -1501,6 +1513,8 @@ function _key_exchange($kexinit_payload_server = false) $preferred['client_to_server']['comp'] : $this->getSupportedCompressionAlgorithms(); + $kex_algorithms = array_merge($kex_algorithms, array('ext-info-c', 'kex-strict-c-v00@openssh.com')); + // some SSH servers have buggy implementations of some of the above algorithms switch (true) { case $this->server_identifier == 'SSH-2.0-SSHD': @@ -1563,6 +1577,7 @@ function _key_exchange($kexinit_payload_server = false) return false; } + $this->extra_packets = 0; $kexinit_payload_server = $this->_get_binary_packet(); if ($kexinit_payload_server === false) { $this->bitmap = 0; @@ -1587,6 +1602,12 @@ function _key_exchange($kexinit_payload_server = false) } $temp = unpack('Nlength', $this->_string_shift($response, 4)); $this->kex_algorithms = explode(',', $this->_string_shift($response, $temp['length'])); + if (in_array('kex-strict-s-v00@openssh.com', $this->kex_algorithms)) { + if ($this->session_id === false && $this->extra_packets) { + user_error('Possible Terrapin Attack detected'); + return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); + } + } if (strlen($response) < 4) { return false; @@ -1993,6 +2014,10 @@ function _key_exchange($kexinit_payload_server = false) return false; } + if (in_array('kex-strict-s-v00@openssh.com', $this->kex_algorithms)) { + $this->get_seq_no = $this->send_seq_no = 0; + } + $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes); $this->encrypt = $this->_encryption_algorithm_to_crypt_instance($encrypt); @@ -2267,7 +2292,9 @@ function _bad_algorithm_candidate($algorithm) function login($username) { $args = func_get_args(); - $this->auth[] = $args; + if (!$this->retry_connect) { + $this->auth[] = $args; + } // try logging with 'none' as an authentication method first since that's what // PuTTY does @@ -2410,6 +2437,35 @@ function _login_helper($username, $password = null) } extract(unpack('Ctype', $this->_string_shift($response, 1))); + if ($type == NET_SSH2_MSG_EXT_INFO) { + if (strlen($response) < 4) { + return false; + } + $nr_extensions = unpack('Nlength', $this->_string_shift($response, 4)); + for ($i = 0; $i < $nr_extensions['length']; $i++) { + if (strlen($response) < 4) { + return false; + } + $temp = unpack('Nlength', $this->_string_shift($response, 4)); + $extension_name = $this->_string_shift($response, $temp['length']); + if ($extension_name == 'server-sig-algs') { + if (strlen($response) < 4) { + return false; + } + $temp = unpack('Nlength', $this->_string_shift($response, 4)); + $this->supported_private_key_algorithms = explode(',', $this->_string_shift($response, $temp['length'])); + } + } + + $response = $this->_get_binary_packet(); + if ($response === false) { + $this->bitmap = 0; + user_error('Connection closed by server'); + return false; + } + extract(unpack('Ctype', $this->_string_shift($response, 1))); + } + if ($type != NET_SSH2_MSG_SERVICE_ACCEPT) { user_error('Expected SSH_MSG_SERVICE_ACCEPT'); return false; @@ -2777,7 +2833,7 @@ function _privatekey_login($username, $privatekey) $algos = array('rsa-sha2-256', 'rsa-sha2-512', 'ssh-rsa'); if (isset($this->preferred['hostkey'])) { - $algos = array_intersect($this->preferred['hostkey'], $algos); + $algos = array_intersect($algos, $this->preferred['hostkey']); } $algo = $this->_array_intersect_first($algos, $this->supported_private_key_algorithms); @@ -3593,6 +3649,9 @@ function _get_binary_packet($skip_channel_filter = false) } $start = microtime(true); + $sec = (int) floor($this->curTimeout); + $usec = (int) (1000000 * ($this->curTimeout - $sec)); + stream_set_timeout($this->fsock, $sec, $usec); $raw = stream_get_contents($this->fsock, $this->decrypt_block_size); if (!strlen($raw)) { @@ -3732,9 +3791,11 @@ function _filter($payload, $skip_channel_filter) $this->bitmap = 0; return false; case NET_SSH2_MSG_IGNORE: + $this->extra_packets++; $payload = $this->_get_binary_packet($skip_channel_filter); break; case NET_SSH2_MSG_DEBUG: + $this->extra_packets++; $this->_string_shift($payload, 2); if (strlen($payload) < 4) { return false; @@ -3746,6 +3807,7 @@ function _filter($payload, $skip_channel_filter) case NET_SSH2_MSG_UNIMPLEMENTED: return false; case NET_SSH2_MSG_KEXINIT: + // this is here for key re-exchanges after the initial key exchange if ($this->session_id !== false) { $this->send_kex_first = false; if (!$this->_key_exchange($payload)) { @@ -4642,7 +4704,9 @@ function _array_intersect_first($array1, $array2) } /** - * Returns all errors + * Returns all errors / debug messages on the SSH layer + * + * If you are looking for messages from the SFTP layer, please see SFTP::getSFTPErrors() * * @return string[] * @access public @@ -4653,7 +4717,9 @@ function getErrors() } /** - * Returns the last error + * Returns the last error received on the SSH layer + * + * If you are looking for messages from the SFTP layer, please see SFTP::getLastSFTPError() * * @return string * @access public