Merge branch '3.0'

This commit is contained in:
terrafrost 2022-01-30 01:19:37 -06:00
commit 48259b20b3
10 changed files with 113 additions and 43 deletions

View File

@ -158,9 +158,9 @@ abstract class Strings
/**
* Create SSH2-style string
*
* @param string[] ...$elements
* @param string|int|float|array|bool ...$elements
* @access public
* @return mixed
* @return string
*/
public static function packSSH2(...$elements)
{

View File

@ -123,6 +123,12 @@ abstract class AsymmetricKey
*/
private $comment;
/**
* @param string $type
* @return string
*/
abstract public function toString($type, array $options = []);
/**
* The constructor
*/
@ -245,7 +251,7 @@ abstract class AsymmetricKey
* @param string $type
* @param string $key
* @param string $password optional
* @return AsymmetricKey
* @return static
*/
public static function loadFormat($type, $key, $password = false)
{

View File

@ -213,6 +213,13 @@ abstract class SymmetricKey
self::ENGINE_OPENSSL_GCM => 'OpenSSL (GCM)'
];
/** @var string|null */
public $fixed;
/** @var string|null */
public $invocation_counter;
/** @var string|null */
public $name;
/**
* The Encryption Mode
*
@ -3412,4 +3419,4 @@ abstract class SymmetricKey
{
return array_flip(self::MODE_MAP)[$this->mode];
}
}
}

View File

@ -78,7 +78,7 @@ abstract class DH extends AsymmetricKey
* - a string (eg. diffie-hellman-group14-sha1)
*
* @access public
* @return \phpseclib3\Crypt\DH|bool
* @return Parameters
*/
public static function createParameters(...$args)
{
@ -397,4 +397,4 @@ abstract class DH extends AsymmetricKey
$key = $type::saveParameters($this->prime, $this->base);
return self::load($key, 'PKCS1');
}
}
}

View File

@ -129,7 +129,7 @@ abstract class DSA extends AsymmetricKey
SSH DSA implementations only support keys with an N of 160.
puttygen let's you set the size of L (but not the size of N) and uses 2048 as the
default L value. that's not really compliant with any of the FIPS standards, however,
for the purposes of maintaining compatibility with puttygen, we'll support it
for the purposes of maintaining compatibility with puttygen, we'll support it
*/
//case ($L >= 512 || $L <= 1024) && (($L & 0x3F) == 0) && $N == 160:
// FIPS 186-3 changed this as follows:
@ -341,4 +341,4 @@ abstract class DSA extends AsymmetricKey
{
return $this->shortFormat;
}
}
}

View File

@ -69,6 +69,11 @@ class Hash
*/
const PADDING_SHAKE = 3;
/** @var int|false */
public $etm;
/** @var string|false */
public $name;
/**
* Padding Type
*

View File

@ -51,7 +51,7 @@ abstract class Random
}
try {
return \random_bytes($length);
return random_bytes($length);
} catch (\Exception $e) {
// random_compat will throw an Exception, which in PHP 5 does not implement Throwable
} catch (\Throwable $e) {

View File

@ -116,6 +116,18 @@ class SFTP extends SSH2
*/
private $status_codes = [];
/** @var array<int, string> */
private $attributes;
/** @var array<int, string> */
private $open_flags;
/** @var array<int, string> */
private $open_flags5;
/** @var array<int, string> */
private $file_types;
/**
* The Request ID
*
@ -188,7 +200,7 @@ class SFTP extends SSH2
/**
* Current working directory
*
* @var string
* @var string|bool
* @see self::realpath()
* @see self::chdir()
* @access private
@ -242,7 +254,7 @@ class SFTP extends SSH2
*
* @see self::__construct()
* @see self::get()
* @var array
* @var int
* @access private
*/
private $max_sftp_packet;
@ -781,7 +793,7 @@ class SFTP extends SSH2
/**
* Returns the current directory name
*
* @return string|false
* @return string|bool
* @access public
*/
public function pwd()
@ -1226,7 +1238,7 @@ class SFTP extends SSH2
* $sftp->setListOrder();
* Don't do any sort of sorting
*
* @param string[] ...$args
* @param string ...$args
* @access public
*/
public function setListOrder(...$args)
@ -1809,7 +1821,7 @@ class SFTP extends SSH2
$packet = Strings::packSSH2('s', $path);
$packet.= $this->version >= 4 ?
pack('Ca*', NET_SFTP_TYPE_UNKNOWN, $attr) :
$atr;
$attr;
$this->send_sftp_packet(NET_SFTP_SETSTAT, $packet);
$i++;
@ -3131,7 +3143,7 @@ class SFTP extends SSH2
// see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.4
// represents the number of bytes that the file consumes on the disk. will
// usually be larger than the 'size' field
list($attr['allocation-size']) = Strings::unpack('Q', $response);
list($attr['allocation-size']) = Strings::unpackSSH2('Q', $response);
break;
case NET_SFTP_ATTR_TEXT_HINT: // 0x00000800
// https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.10
@ -3146,7 +3158,7 @@ class SFTP extends SSH2
break;
case NET_SFTP_ATTR_LINK_COUNT: // 0x00002000
// see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.12
list($attr['link-count']) = Strings::unpackSS2('N', $response);
list($attr['link-count']) = Strings::unpackSSH2('N', $response);
break;
case NET_SFTP_ATTR_UNTRANSLATED_NAME:// 0x00004000
// see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.13

View File

@ -204,7 +204,7 @@ class SSH2
/**
* The Socket Object
*
* @var object
* @var resource|closed-resource|null
* @access private
*/
public $fsock;
@ -711,7 +711,7 @@ class SSH2
* Interactive Buffer
*
* @see self::read()
* @var array
* @var string
* @access private
*/
private $interactiveBuffer = '';
@ -756,7 +756,7 @@ class SSH2
* Real-time log file pointer
*
* @see self::_append_log()
* @var resource
* @var resource|closed-resource
* @access private
*/
private $realtime_log_file;
@ -798,7 +798,7 @@ class SSH2
/**
* Time of first network activity
*
* @var int
* @var float
* @access private
*/
private $last_packet;
@ -966,7 +966,7 @@ class SSH2
/**
* A System_SSH_Agent for use in the SSH2 Agent Forwarding scenario
*
* @var \phpseclib3\System\Ssh\Agent
* @var Agent
* @access private
*/
private $agent;
@ -975,7 +975,7 @@ class SSH2
* Connection storage to replicates ssh2 extension functionality:
* {@link http://php.net/manual/en/wrappers.ssh2.php#refsect1-wrappers.ssh2-examples}
*
* @var SSH2[]
* @var array<string, SSH2|\WeakReference<SSH2>>
*/
private static $connections;
@ -1063,7 +1063,7 @@ class SSH2
/**
* Decompression method
*
* @var resource|object
* @var int
* @access private
*/
private $decompress = self::NET_SSH2_COMPRESSION_NONE;
@ -1071,7 +1071,7 @@ class SSH2
/**
* Compression context
*
* @var int
* @var resource|false|null
* @access private
*/
private $compress_context;
@ -1200,7 +1200,13 @@ class SSH2
31 => 'NET_SSH2_MSG_KEX_ECDH_REPLY']
);
self::$connections[$this->getResourceId()] = class_exists('WeakReference') ? \WeakReference::create($this) : $this;
/**
* Typehint is required due to a bug in Psalm: https://github.com/vimeo/psalm/issues/7508
* @var \WeakReference<SSH2>|SSH2
*/
self::$connections[$this->getResourceId()] = class_exists('WeakReference')
? \WeakReference::create($this)
: $this;
if (is_resource($host)) {
$this->fsock = $host;
@ -1411,7 +1417,7 @@ class SSH2
if (!$this->send_kex_first) {
$response = $this->get_binary_packet();
if (!strlen($response) || ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
if (is_bool($response) || !strlen($response) || ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
$this->bitmap = 0;
throw new \UnexpectedValueException('Expected SSH_MSG_KEXINIT');
}
@ -1546,7 +1552,11 @@ class SSH2
$kexinit_payload_server = $this->get_binary_packet();
if (!strlen($kexinit_payload_server) || ord($kexinit_payload_server[0]) != NET_SSH2_MSG_KEXINIT) {
if (
is_bool($kexinit_payload_server)
|| !strlen($kexinit_payload_server)
|| ord($kexinit_payload_server[0]) != NET_SSH2_MSG_KEXINIT
) {
$this->disconnect_helper(NET_SSH2_DISCONNECT_PROTOCOL_ERROR);
throw new \UnexpectedValueException('Expected SSH_MSG_KEXINIT');
}
@ -2159,7 +2169,7 @@ class SSH2
* Login Helper
*
* @param string $username
* @param string[] ...$args
* @param string ...$args
* @return bool
* @see self::_login_helper()
* @access private
@ -2402,7 +2412,7 @@ class SSH2
* See {@link http://tools.ietf.org/html/rfc4256 RFC4256} for details. This is not a full-featured keyboard-interactive authenticator.
*
* @param string $username
* @param string $password
* @param string|array $password
* @return bool
* @access private
*/
@ -2425,7 +2435,7 @@ class SSH2
/**
* Handle the keyboard-interactive requests / responses.
*
* @param mixed[] ...$responses
* @param string|array ...$responses
* @return bool
* @throws \RuntimeException on connection error
* @access private
@ -2719,12 +2729,12 @@ class SSH2
* In all likelihood, this is not a feature you want to be taking advantage of.
*
* @param string $command
* @param callback $callback
* @return string
* @return string|bool
* @psalm-return ($callback is callable ? bool : string|bool)
* @throws \RuntimeException on connection error
* @access public
*/
public function exec($command, $callback = null)
public function exec($command, callable $callback = null)
{
$this->curTimeout = $this->timeout;
$this->is_timeout = false;
@ -3290,12 +3300,15 @@ class SSH2
*
* @see self::_send_binary_packet()
* @param bool $skip_channel_filter
* @return string
* @return bool|string
* @access private
*/
private function get_binary_packet($skip_channel_filter = false)
{
if ($skip_channel_filter) {
if (!is_resource($this->fsock)) {
throw new \InvalidArgumentException('fsock is not a resource.');
}
$read = [$this->fsock];
$write = $except = null;
@ -3314,9 +3327,6 @@ class SSH2
return true;
}
$read = [$this->fsock];
$write = $except = null;
$start = microtime(true);
if ($this->keepAlive > 0 && $this->keepAlive < $this->curTimeout) {
@ -3590,7 +3600,7 @@ class SSH2
* @see self::_get_binary_packet()
* @param string $payload
* @param bool $skip_channel_filter
* @return string
* @return string|bool
* @access private
*/
private function filter($payload, $skip_channel_filter)
@ -3624,7 +3634,7 @@ class SSH2
}
// see http://tools.ietf.org/html/rfc4252#section-5.4; only called when the encryption has been activated and when we haven't already logged in
if (($this->bitmap & self::MASK_CONNECTED) && !$this->isAuthenticated() && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) {
if (($this->bitmap & self::MASK_CONNECTED) && !$this->isAuthenticated() && !is_bool($payload) && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) {
Strings::shift($payload, 1);
list($this->banner_message) = Strings::unpackSSH2('s', $payload);
$payload = $this->get_binary_packet();
@ -3632,8 +3642,8 @@ class SSH2
// only called when we've already logged in
if (($this->bitmap & self::MASK_CONNECTED) && $this->isAuthenticated()) {
if ($payload === true) {
return true;
if (is_bool($payload)) {
return $payload;
}
switch (ord($payload[0])) {
@ -4364,7 +4374,7 @@ class SSH2
}
$this->bitmap = 0;
if (is_resource($this->fsock) && get_resource_type($this->fsock) == 'stream') {
if (is_resource($this->fsock) && get_resource_type($this->fsock) === 'stream') {
fclose($this->fsock);
}
@ -5115,11 +5125,12 @@ class SSH2
/**
* Return all excising connections
*
* @return SSH2[]
* @return array<string, SSH2>
*/
public static function getConnections()
{
if (!class_exists('WeakReference')) {
/** @var array<string, SSH2> */
return self::$connections;
}
$temp = [];

29
psalm.xml Normal file
View File

@ -0,0 +1,29 @@
<?xml version="1.0"?>
<psalm
errorLevel="6"
resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
findUnusedPsalmSuppress="true"
sealAllMethods="true"
>
<projectFiles>
<directory name="phpseclib/Net"/>
</projectFiles>
<fileExtensions>
<extension name=".php"/>
</fileExtensions>
<issueHandlers>
<Trace>
<errorLevel type="error">
<directory name="."/>
</errorLevel>
</Trace>
<UndefinedConstant>
<errorLevel type="suppress">
<directory name="phpseclib/Net"/>
</errorLevel>
</UndefinedConstant>
</issueHandlers>
</psalm>