From e6dac085cb1d601da1fc63bfd59d811612fa6ef4 Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 8 Oct 2021 12:24:19 +0000 Subject: update composer libs --- .../phpseclib/phpseclib/phpseclib/Crypt/Base.php | 67 ++++++++----- vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php | 66 ++++++++++++- vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php | 80 ++++++++++++---- vendor/phpseclib/phpseclib/phpseclib/File/X509.php | 11 ++- .../phpseclib/phpseclib/Math/BigInteger.php | 6 +- vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php | 75 +++++++++++++-- .../phpseclib/phpseclib/Net/SFTP/Stream.php | 6 +- vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php | 105 +++++++++++++-------- 8 files changed, 315 insertions(+), 101 deletions(-) (limited to 'vendor/phpseclib') diff --git a/vendor/phpseclib/phpseclib/phpseclib/Crypt/Base.php b/vendor/phpseclib/phpseclib/phpseclib/Crypt/Base.php index efbcd242b..8822b9b88 100644 --- a/vendor/phpseclib/phpseclib/phpseclib/Crypt/Base.php +++ b/vendor/phpseclib/phpseclib/phpseclib/Crypt/Base.php @@ -779,12 +779,14 @@ abstract class Base } if ($this->engine === self::ENGINE_MCRYPT) { + set_error_handler(array($this, 'do_nothing')); + if ($this->changed) { $this->_setupMcrypt(); $this->changed = false; } if ($this->enchanged) { - @mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); + mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); $this->enchanged = false; } @@ -817,15 +819,15 @@ abstract class Base if ($len >= $block_size) { if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) { if ($this->enbuffer['enmcrypt_init'] === true) { - @mcrypt_generic_init($this->enmcrypt, $this->key, $iv); + mcrypt_generic_init($this->enmcrypt, $this->key, $iv); $this->enbuffer['enmcrypt_init'] = false; } - $ciphertext.= @mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size)); + $ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size)); $iv = substr($ciphertext, -$block_size); $len%= $block_size; } else { while ($len >= $block_size) { - $iv = @mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size); + $iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size); $ciphertext.= $iv; $len-= $block_size; $i+= $block_size; @@ -834,22 +836,26 @@ abstract class Base } if ($len) { - $iv = @mcrypt_generic($this->ecb, $iv); + $iv = mcrypt_generic($this->ecb, $iv); $block = $iv ^ substr($plaintext, -$len); $iv = substr_replace($iv, $block, 0, $len); $ciphertext.= $block; $pos = $len; } + restore_error_handler(); + return $ciphertext; } - $ciphertext = @mcrypt_generic($this->enmcrypt, $plaintext); + $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext); if (!$this->continuousBuffer) { - @mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); + mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); } + restore_error_handler(); + return $ciphertext; } @@ -1118,13 +1124,14 @@ abstract class Base } if ($this->engine === self::ENGINE_MCRYPT) { + set_error_handler(array($this, 'do_nothing')); $block_size = $this->block_size; if ($this->changed) { $this->_setupMcrypt(); $this->changed = false; } if ($this->dechanged) { - @mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); + mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); $this->dechanged = false; } @@ -1152,26 +1159,30 @@ abstract class Base } if ($len >= $block_size) { $cb = substr($ciphertext, $i, $len - $len % $block_size); - $plaintext.= @mcrypt_generic($this->ecb, $iv . $cb) ^ $cb; + $plaintext.= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb; $iv = substr($cb, -$block_size); $len%= $block_size; } if ($len) { - $iv = @mcrypt_generic($this->ecb, $iv); + $iv = mcrypt_generic($this->ecb, $iv); $plaintext.= $iv ^ substr($ciphertext, -$len); $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len); $pos = $len; } + restore_error_handler(); + return $plaintext; } - $plaintext = @mdecrypt_generic($this->demcrypt, $ciphertext); + $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext); if (!$this->continuousBuffer) { - @mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); + mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); } + restore_error_handler(); + return $this->paddable ? $this->_unpad($plaintext) : $plaintext; } @@ -1649,9 +1660,12 @@ abstract class Base } return false; case self::ENGINE_MCRYPT: - return $this->cipher_name_mcrypt && + set_error_handler(array($this, 'do_nothing')); + $result = $this->cipher_name_mcrypt && extension_loaded('mcrypt') && - in_array($this->cipher_name_mcrypt, @mcrypt_list_algorithms()); + in_array($this->cipher_name_mcrypt, mcrypt_list_algorithms()); + restore_error_handler(); + return $result; case self::ENGINE_INTERNAL: return true; } @@ -1728,17 +1742,19 @@ abstract class Base } if ($this->engine != self::ENGINE_MCRYPT && $this->enmcrypt) { + set_error_handler(array($this, 'do_nothing')); // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed, // (re)open them with the module named in $this->cipher_name_mcrypt - @mcrypt_module_close($this->enmcrypt); - @mcrypt_module_close($this->demcrypt); + mcrypt_module_close($this->enmcrypt); + mcrypt_module_close($this->demcrypt); $this->enmcrypt = null; $this->demcrypt = null; if ($this->ecb) { - @mcrypt_module_close($this->ecb); + mcrypt_module_close($this->ecb); $this->ecb = null; } + restore_error_handler(); } $this->changed = true; @@ -1851,19 +1867,19 @@ abstract class Base self::MODE_STREAM => MCRYPT_MODE_STREAM, ); - $this->demcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); - $this->enmcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); + $this->demcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); + $this->enmcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer() // to workaround mcrypt's broken ncfb implementation in buffered mode // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps} if ($this->mode == self::MODE_CFB) { - $this->ecb = @mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, ''); + $this->ecb = mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, ''); } } // else should mcrypt_generic_deinit be called? if ($this->mode == self::MODE_CFB) { - @mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size)); + mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size)); } } @@ -2696,4 +2712,13 @@ abstract class Base return $safeint . '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))'; } } + + /** + * Dummy error handler to suppress mcrypt errors + * + * @access private + */ + function do_nothing() + { + } } diff --git a/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php index 17e2b8329..e26fe41dd 100644 --- a/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php +++ b/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php @@ -1219,6 +1219,7 @@ class RSA $length = $this->_decodeLength($temp); switch ($this->_string_shift($temp, $length)) { case "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01": // rsaEncryption + case "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0A": // rsaPSS break; case "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03": // pbeWithMD5AndDES-CBC /* @@ -2579,9 +2580,9 @@ class RSA $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; } @@ -2916,6 +2917,59 @@ class RSA return $em; } + /** + * EMSA-PKCS1-V1_5-ENCODE (without NULL) + * + * Quoting https://tools.ietf.org/html/rfc8017#page-65, + * + * "The parameters field associated with id-sha1, id-sha224, id-sha256, + * id-sha384, id-sha512, id-sha512/224, and id-sha512/256 should + * generally be omitted, but if present, it shall have a value of type + * NULL" + * + * @access private + * @param string $m + * @param int $emLen + * @return string + */ + function _emsa_pkcs1_v1_5_encode_without_null($m, $emLen) + { + $h = $this->hash->hash($m); + if ($h === false) { + return false; + } + + switch ($this->hashName) { + case 'sha1': + $t = pack('H*', '301f300706052b0e03021a0414'); + break; + case 'sha256': + $t = pack('H*', '302f300b06096086480165030402010420'); + break; + case 'sha384': + $t = pack('H*', '303f300b06096086480165030402020430'); + break; + case 'sha512': + $t = pack('H*', '304f300b06096086480165030402030440'); + break; + default: + return false; + } + $t.= $h; + $tLen = strlen($t); + + if ($emLen < $tLen + 11) { + user_error('Intended encoded message length too short'); + return false; + } + + $ps = str_repeat(chr(0xFF), $emLen - $tLen - 3); + + $em = "\0\1$ps\0$t"; + + return $em; + } + /** * RSASSA-PKCS1-V1_5-SIGN * @@ -2982,13 +3036,17 @@ class RSA // EMSA-PKCS1-v1_5 encoding $em2 = $this->_emsa_pkcs1_v1_5_encode($m, $this->k); - if ($em2 === false) { + $em3 = $this->_emsa_pkcs1_v1_5_encode_without_null($m, $this->k); + + if ($em2 === false && $em3 === false) { user_error('RSA modulus too short'); return false; } // Compare - return $this->_equals($em, $em2); + + return ($em2 !== false && $this->_equals($em, $em2)) || + ($em3 !== false && $this->_equals($em, $em3)); } /** diff --git a/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php b/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php index 807ca88ce..fb2d64485 100644 --- a/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php +++ b/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php @@ -234,8 +234,11 @@ class ASN1 { $current = array('start' => $start); + if (!isset($encoded[$encoded_pos])) { + return false; + } $type = ord($encoded[$encoded_pos++]); - $start++; + $startOffset = 1; $constructed = ($type >> 5) & 1; @@ -244,15 +247,28 @@ class ASN1 $tag = 0; // process septets (since the eighth bit is ignored, it's not an octet) do { + if (!isset($encoded[$encoded_pos])) { + return false; + } $temp = ord($encoded[$encoded_pos++]); + $startOffset++; $loop = $temp >> 7; $tag <<= 7; - $tag |= $temp & 0x7F; - $start++; + $temp &= 0x7F; + // "bits 7 to 1 of the first subsequent octet shall not all be zero" + if ($startOffset == 2 && $temp == 0) { + return false; + } + $tag |= $temp; } while ($loop); } + $start+= $startOffset; + // Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13 + if (!isset($encoded[$encoded_pos])) { + return false; + } $length = ord($encoded[$encoded_pos++]); $start++; if ($length == 0x80) { // indefinite length @@ -344,13 +360,16 @@ class ASN1 switch ($tag) { case self::TYPE_BOOLEAN: // "The contents octets shall consist of a single octet." -- paragraph 8.2.1 - //if (strlen($content) != 1) { - // return false; - //} + if ($constructed || strlen($content) != 1) { + return false; + } $current['content'] = (bool) ord($content[$content_pos]); break; case self::TYPE_INTEGER: case self::TYPE_ENUMERATED: + if ($constructed) { + return false; + } $current['content'] = new BigInteger(substr($content, $content_pos), -256); break; case self::TYPE_REAL: // not currently supported @@ -370,15 +389,15 @@ class ASN1 $last = count($temp) - 1; for ($i = 0; $i < $last; $i++) { // all subtags should be bit strings - //if ($temp[$i]['type'] != self::TYPE_BIT_STRING) { - // return false; - //} + if ($temp[$i]['type'] != self::TYPE_BIT_STRING) { + return false; + } $current['content'].= substr($temp[$i]['content'], 1); } // all subtags should be bit strings - //if ($temp[$last]['type'] != self::TYPE_BIT_STRING) { - // return false; - //} + if ($temp[$last]['type'] != self::TYPE_BIT_STRING) { + return false; + } $current['content'] = $temp[$last]['content'][0] . $current['content'] . substr($temp[$i]['content'], 1); } break; @@ -395,9 +414,9 @@ class ASN1 } $content_pos += $temp['length']; // all subtags should be octet strings - //if ($temp['type'] != self::TYPE_OCTET_STRING) { - // return false; - //} + if ($temp['type'] != self::TYPE_OCTET_STRING) { + return false; + } $current['content'].= $temp['content']; $length+= $temp['length']; } @@ -408,12 +427,15 @@ class ASN1 break; case self::TYPE_NULL: // "The contents octets shall not contain any octets." -- paragraph 8.8.2 - //if (strlen($content)) { - // return false; - //} + if ($constructed || strlen($content)) { + return false; + } break; case self::TYPE_SEQUENCE: case self::TYPE_SET: + if (!$constructed) { + return false; + } $offset = 0; $current['content'] = array(); $content_len = strlen($content); @@ -434,7 +456,13 @@ class ASN1 } break; case self::TYPE_OBJECT_IDENTIFIER: + if ($constructed) { + return false; + } $current['content'] = $this->_decodeOID(substr($content, $content_pos)); + if ($current['content'] === false) { + return false; + } break; /* Each character string type shall be encoded as if it had been declared: [UNIVERSAL x] IMPLICIT OCTET STRING @@ -464,12 +492,20 @@ class ASN1 case self::TYPE_UTF8_STRING: // ???? case self::TYPE_BMP_STRING: + if ($constructed) { + return false; + } $current['content'] = substr($content, $content_pos); break; case self::TYPE_UTC_TIME: case self::TYPE_GENERALIZED_TIME: + if ($constructed) { + return false; + } $current['content'] = $this->_decodeTime(substr($content, $content_pos), $tag); + break; default: + return false; } $start+= $length; @@ -966,7 +1002,10 @@ class ASN1 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: @@ -1127,6 +1166,11 @@ class ASN1 $oid = array(); $pos = 0; $len = strlen($content); + + if (ord($content[$len - 1]) & 0x80) { + return false; + } + $n = new BigInteger(); while ($pos < $len) { $temp = ord($content[$pos++]); diff --git a/vendor/phpseclib/phpseclib/phpseclib/File/X509.php b/vendor/phpseclib/phpseclib/phpseclib/File/X509.php index 3520efdc1..0da0b83cc 100644 --- a/vendor/phpseclib/phpseclib/phpseclib/File/X509.php +++ b/vendor/phpseclib/phpseclib/phpseclib/File/X509.php @@ -1622,7 +1622,6 @@ class X509 $id = $extensions[$i]['extnId']; $value = &$extensions[$i]['extnValue']; $value = base64_decode($value); - $decoded = $asn1->decodeBER($value); /* [extnValue] contains the DER encoding of an ASN.1 value corresponding to the extension type identified by extnID */ $map = $this->_getMapping($id); @@ -1630,6 +1629,7 @@ class X509 $decoder = $id == 'id-ce-nameConstraints' ? array($this, '_decodeNameConstraintIP') : array($this, '_decodeIP'); + $decoded = $asn1->decodeBER($value); $mapped = $asn1->asn1map($decoded[0], $map, array('iPAddress' => $decoder)); $value = $mapped === false ? $decoded[0] : $mapped; @@ -5054,9 +5054,12 @@ class X509 * subject=/O=organization/OU=org unit/CN=common name * issuer=/O=organization/CN=common name */ - $temp = strlen($str) <= ini_get('pcre.backtrack_limit') ? - preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1) : - $str; + if (strlen($str) > ini_get('pcre.backtrack_limit')) { + $temp = $str; + } else { + $temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1); + $temp = preg_replace('#-+END.*[\r\n ]*.*#ms', '', $temp, 1); + } // remove new lines $temp = str_replace(array("\r", "\n", ' '), '', $temp); // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff diff --git a/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php b/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php index 9df0bf0f2..fc24b9145 100644 --- a/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php +++ b/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php @@ -658,11 +658,11 @@ class BigInteger { $hex = $this->toHex($twos_compliment); $bits = ''; - for ($i = strlen($hex) - 8, $start = strlen($hex) & 7; $i >= $start; $i-=8) { - $bits = str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT) . $bits; + for ($i = strlen($hex) - 6, $start = strlen($hex) % 6; $i >= $start; $i-=6) { + $bits = str_pad(decbin(hexdec(substr($hex, $i, 6))), 24, '0', STR_PAD_LEFT) . $bits; } if ($start) { // hexdec('') == 0 - $bits = str_pad(decbin(hexdec(substr($hex, 0, $start))), 8, '0', STR_PAD_LEFT) . $bits; + $bits = str_pad(decbin(hexdec(substr($hex, 0, $start))), 8 * $start, '0', STR_PAD_LEFT) . $bits; } $result = $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0'); diff --git a/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php b/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php index 8ae43fa04..1e6fba9fc 100644 --- a/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php +++ b/vendor/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 @@ class SFTP extends SSH2 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( @@ -446,6 +467,8 @@ class SFTP extends SSH2 $response = $this->_get_channel_packet(self::CHANNEL, true); if ($response === false) { return false; + } elseif ($response === true && $this->isTimeout()) { + return false; } $packet = pack( @@ -492,6 +515,8 @@ class SFTP extends SSH2 if ($response === false) { return false; } + } elseif ($response === true && $this->isTimeout()) { + return false; } $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_DATA; @@ -1024,7 +1049,7 @@ class SFTP extends SSH2 uasort($contents, array(&$this, '_comparator')); } - return $raw ? $contents : array_keys($contents); + return $raw ? $contents : array_map('strval', array_keys($contents)); } /** @@ -2293,7 +2318,13 @@ class SFTP extends SSH2 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; } @@ -3004,9 +3035,17 @@ class SFTP extends SSH2 $packet_type = '-> ' . $this->packet_types[$type] . ' (' . round($stop - $start, 4) . 's)'; if (NET_SFTP_LOGGING == self::LOG_REALTIME) { - echo "
\r\n" . $this->_format_log(array($data), array($packet_type)) . "\r\n
\r\n"; - flush(); - ob_flush(); + switch (PHP_SAPI) { + case 'cli': + $start = $stop = "\r\n"; + break; + default: + $start = '
';
+                        $stop = '
'; + } + echo $start . $this->_format_log(array($data), array($packet_type)) . $stop; + @flush(); + @ob_flush(); } else { $this->packet_type_log[] = $packet_type; if (NET_SFTP_LOGGING == self::LOG_COMPLEX) { @@ -3047,6 +3086,8 @@ class SFTP extends SSH2 */ 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']; @@ -3063,11 +3104,17 @@ class SFTP extends SSH2 // 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; } + if ($temp === false) { + return false; + } $this->packet_buffer.= $temp; } if (strlen($this->packet_buffer) < 4) { @@ -3079,7 +3126,7 @@ class SFTP extends SSH2 // 256 * 1024 is what SFTP_MAX_MSG_LENGTH is set to in OpenSSH's sftp-common.h - if ($tempLength > 256 * 1024) { + if (!$this->use_request_id && $tempLength > 256 * 1024) { user_error('Invalid SFTP packet size'); return false; } @@ -3113,9 +3160,17 @@ class SFTP extends SSH2 $packet_type = '<- ' . $this->packet_types[$this->packet_type] . ' (' . round($stop - $start, 4) . 's)'; if (NET_SFTP_LOGGING == self::LOG_REALTIME) { - echo "
\r\n" . $this->_format_log(array($packet), array($packet_type)) . "\r\n
\r\n"; - flush(); - ob_flush(); + switch (PHP_SAPI) { + case 'cli': + $start = $stop = "\r\n"; + break; + default: + $start = '
';
+                        $stop = '
'; + } + echo $start . $this->_format_log(array($packet), array($packet_type)) . $stop; + @flush(); + @ob_flush(); } else { $this->packet_type_log[] = $packet_type; if (NET_SFTP_LOGGING == self::LOG_COMPLEX) { diff --git a/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php b/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php index 1a44b10a0..ec9e5841a 100644 --- a/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php +++ b/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php @@ -410,7 +410,7 @@ class Stream { switch ($whence) { case SEEK_SET: - if ($offset >= $this->size || $offset < 0) { + if ($offset < 0) { return false; } break; @@ -447,7 +447,9 @@ class Stream // and https://github.com/php/php-src/blob/master/main/php_streams.h#L592 switch ($option) { case 1: // PHP_STREAM_META_TOUCH - return $this->sftp->touch($path, $var[0], $var[1]); + $time = isset($var[0]) ? $var[0] : null; + $atime = isset($var[1]) ? $var[1] : null; + return $this->sftp->touch($path, $time, $atime); case 2: // PHP_STREAM_OWNER_NAME case 3: // PHP_STREAM_GROUP_NAME return false; diff --git a/vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php b/vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php index e2571190b..e449d987a 100644 --- a/vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php +++ b/vendor/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 @@ class SSH2 function _key_exchange($kexinit_payload_server = false) { $preferred = $this->preferred; + $send_kex = true; $kex_algorithms = isset($preferred['kex']) ? $preferred['kex'] : @@ -1430,7 +1439,7 @@ class SSH2 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 @@ class SSH2 user_error('Expected SSH_MSG_KEXINIT'); return false; } + + $send_kex = false; } $response = $kexinit_payload_server; @@ -1518,7 +1529,7 @@ class SSH2 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 @@ class SSH2 // 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 @@ class SSH2 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 @@ class SSH2 } 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 @@ class SSH2 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,13 +2643,21 @@ class SSH2 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 // they should be $this->_updateLogHistory('UNKNOWN (60)', 'NET_SSH2_MSG_USERAUTH_PK_OK'); + break; + case NET_SSH2_MSG_USERAUTH_SUCCESS: + $this->bitmap |= self::MASK_LOGIN; + return true; + default: + user_error('Unexpected response to publickey authentication pt 1'); + return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); } $packet = $part1 . chr(1) . $part2; @@ -2662,13 +2686,16 @@ class SSH2 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; return true; } - return false; + user_error('Unexpected response to publickey authentication pt 2'); + return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); } /** @@ -2690,7 +2717,7 @@ class SSH2 * * Sends an SSH2_MSG_IGNORE message every x seconds, if x is a positive non-zero number. * - * @param mixed $timeout + * @param int $interval * @access public */ function setKeepAlive($interval) @@ -2927,28 +2954,6 @@ class SSH2 return false; } - $response = $this->_get_binary_packet(); - if ($response === false) { - $this->bitmap = 0; - user_error('Connection closed by server'); - return false; - } - - if (!strlen($response)) { - return false; - } - list(, $type) = unpack('C', $this->_string_shift($response, 1)); - - switch ($type) { - case NET_SSH2_MSG_CHANNEL_SUCCESS: - // if a pty can't be opened maybe commands can still be executed - case NET_SSH2_MSG_CHANNEL_FAILURE: - break; - default: - user_error('Unable to request pseudo-terminal'); - return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); - } - $packet = pack( 'CNNa*C', NET_SSH2_MSG_CHANNEL_REQUEST, @@ -2961,14 +2966,7 @@ class SSH2 return false; } - $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_REQUEST; - - $response = $this->_get_channel_packet(self::CHANNEL_SHELL); - if ($response === false) { - return false; - } - - $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_DATA; + $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_IGNORE; $this->bitmap |= self::MASK_SHELL; @@ -3340,7 +3338,7 @@ class SSH2 $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 { @@ -3534,6 +3532,10 @@ class SSH2 // 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) { @@ -3897,6 +3899,16 @@ class SSH2 return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); } break; + case NET_SSH2_MSG_IGNORE: + switch ($type) { + case NET_SSH2_MSG_CHANNEL_SUCCESS: + //$this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_DATA; + continue 3; + case NET_SSH2_MSG_CHANNEL_FAILURE: + user_error('Error opening channel'); + return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); + } + break; case NET_SSH2_MSG_CHANNEL_REQUEST: switch ($type) { case NET_SSH2_MSG_CHANNEL_SUCCESS: @@ -3916,6 +3928,10 @@ class SSH2 switch ($type) { case NET_SSH2_MSG_CHANNEL_DATA: + //if ($this->channel_status[$channel] == NET_SSH2_MSG_IGNORE) { + // $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_DATA; + //} + /* if ($channel == self::CHANNEL_EXEC) { // SCP requires null packets, such as this, be sent. further, in the case of the ssh.com SSH server @@ -5150,4 +5166,15 @@ class SSH2 ); } } + + /** + * 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; + } } -- cgit v1.2.3