37,8 → 37,6 |
* ?> |
* </code> |
* |
* @category Net |
* @package SSH2 |
* @author Jim Wigginton <terrafrost@php.net> |
* @copyright 2007 Jim Wigginton |
* @license http://www.opensource.org/licenses/mit-license.html MIT License |
76,9 → 74,7 |
/** |
* Pure-PHP implementation of SSHv2. |
* |
* @package SSH2 |
* @author Jim Wigginton <terrafrost@php.net> |
* @access public |
*/ |
class SSH2 |
{ |
85,7 → 81,6 |
/**#@+ |
* Compression Types |
* |
* @access private |
*/ |
/** |
* No compression |
123,7 → 118,6 |
* |
* @see \phpseclib3\Net\SSH2::send_channel_packet() |
* @see \phpseclib3\Net\SSH2::get_channel_packet() |
* @access private |
*/ |
const CHANNEL_EXEC = 1; // PuTTy uses 0x100 |
const CHANNEL_SHELL = 2; |
134,7 → 128,6 |
/** |
* Returns the message numbers |
* |
* @access public |
* @see \phpseclib3\Net\SSH2::getLog() |
*/ |
const LOG_SIMPLE = 1; |
141,28 → 134,24 |
/** |
* Returns the message content |
* |
* @access public |
* @see \phpseclib3\Net\SSH2::getLog() |
*/ |
const LOG_COMPLEX = 2; |
/** |
* Outputs the content real-time |
* |
* @access public |
* @see \phpseclib3\Net\SSH2::getLog() |
*/ |
const LOG_REALTIME = 3; |
/** |
* Dumps the content real-time to a file |
* |
* @access public |
* @see \phpseclib3\Net\SSH2::getLog() |
*/ |
const LOG_REALTIME_FILE = 4; |
/** |
* Outputs the message numbers real-time |
*/ |
const LOG_SIMPLE_REALTIME = 5; |
/** |
* Make sure that the log never gets larger than this |
* |
* @access public |
* @see \phpseclib3\Net\SSH2::getLog() |
*/ |
const LOG_MAX_SIZE = 1048576; // 1024 * 1024 |
170,7 → 159,6 |
/** |
* Returns when a string matching $expect exactly is found |
* |
* @access public |
* @see \phpseclib3\Net\SSH2::read() |
*/ |
const READ_SIMPLE = 1; |
177,7 → 165,6 |
/** |
* Returns when a string matching the regular expression $expect is found |
* |
* @access public |
* @see \phpseclib3\Net\SSH2::read() |
*/ |
const READ_REGEX = 2; |
187,7 → 174,6 |
* Some data packets may only contain a single character so it may be necessary |
* to call read() multiple times when using this option |
* |
* @access public |
* @see \phpseclib3\Net\SSH2::read() |
*/ |
const READ_NEXT = 3; |
196,7 → 182,6 |
* The SSH identifier |
* |
* @var string |
* @access private |
*/ |
private $identifier; |
|
204,7 → 189,6 |
* The Socket Object |
* |
* @var resource|closed-resource|null |
* @access private |
*/ |
public $fsock; |
|
215,7 → 199,6 |
* if a requisite function has been successfully executed. If not, an error should be thrown. |
* |
* @var int |
* @access private |
*/ |
protected $bitmap = 0; |
|
225,7 → 208,6 |
* @see self::getErrors() |
* @see self::getLastError() |
* @var array |
* @access private |
*/ |
private $errors = []; |
|
234,7 → 216,6 |
* |
* @see self::getServerIdentification() |
* @var string|false |
* @access private |
*/ |
protected $server_identifier = false; |
|
243,7 → 224,6 |
* |
* @see self::getKexAlgorithims() |
* @var array|false |
* @access private |
*/ |
private $kex_algorithms = false; |
|
252,7 → 232,6 |
* |
* @see self::getMethodsNegotiated() |
* @var string|false |
* @access private |
*/ |
private $kex_algorithm = false; |
|
261,7 → 240,6 |
* |
* @see self::_key_exchange() |
* @var int |
* @access private |
*/ |
private $kex_dh_group_size_min = 1536; |
|
270,7 → 248,6 |
* |
* @see self::_key_exchange() |
* @var int |
* @access private |
*/ |
private $kex_dh_group_size_preferred = 2048; |
|
279,7 → 256,6 |
* |
* @see self::_key_exchange() |
* @var int |
* @access private |
*/ |
private $kex_dh_group_size_max = 4096; |
|
288,7 → 264,6 |
* |
* @see self::getServerHostKeyAlgorithms() |
* @var array|false |
* @access private |
*/ |
private $server_host_key_algorithms = false; |
|
297,7 → 272,6 |
* |
* @see self::getEncryptionAlgorithmsClient2Server() |
* @var array|false |
* @access private |
*/ |
private $encryption_algorithms_client_to_server = false; |
|
306,7 → 280,6 |
* |
* @see self::getEncryptionAlgorithmsServer2Client() |
* @var array|false |
* @access private |
*/ |
private $encryption_algorithms_server_to_client = false; |
|
315,7 → 288,6 |
* |
* @see self::getMACAlgorithmsClient2Server() |
* @var array|false |
* @access private |
*/ |
private $mac_algorithms_client_to_server = false; |
|
324,7 → 296,6 |
* |
* @see self::getMACAlgorithmsServer2Client() |
* @var array|false |
* @access private |
*/ |
private $mac_algorithms_server_to_client = false; |
|
333,7 → 304,6 |
* |
* @see self::getCompressionAlgorithmsClient2Server() |
* @var array|false |
* @access private |
*/ |
private $compression_algorithms_client_to_server = false; |
|
342,7 → 312,6 |
* |
* @see self::getCompressionAlgorithmsServer2Client() |
* @var array|false |
* @access private |
*/ |
private $compression_algorithms_server_to_client = false; |
|
351,7 → 320,6 |
* |
* @see self::getLanguagesServer2Client() |
* @var array|false |
* @access private |
*/ |
private $languages_server_to_client = false; |
|
360,7 → 328,6 |
* |
* @see self::getLanguagesClient2Server() |
* @var array|false |
* @access private |
*/ |
private $languages_client_to_server = false; |
|
369,7 → 336,6 |
* |
* @see self::setPreferredAlgorithms() |
* @var array |
* @access private |
*/ |
private $preferred = []; |
|
386,7 → 352,6 |
* @see self::__construct() |
* @see self::_send_binary_packet() |
* @var int |
* @access private |
*/ |
private $encrypt_block_size = 8; |
|
396,7 → 361,6 |
* @see self::__construct() |
* @see self::_get_binary_packet() |
* @var int |
* @access private |
*/ |
private $decrypt_block_size = 8; |
|
405,7 → 369,6 |
* |
* @see self::_get_binary_packet() |
* @var SymmetricKey|false |
* @access private |
*/ |
private $decrypt = false; |
|
413,7 → 376,6 |
* Decryption Algorithm Name |
* |
* @var string|null |
* @access private |
*/ |
private $decryptName; |
|
423,7 → 385,6 |
* Used by GCM |
* |
* @var string|null |
* @access private |
*/ |
private $decryptInvocationCounter; |
|
433,7 → 394,6 |
* Used by GCM |
* |
* @var string|null |
* @access private |
*/ |
private $decryptFixedPart; |
|
442,7 → 402,6 |
* |
* @see self::_get_binary_packet() |
* @var object |
* @access private |
*/ |
private $lengthDecrypt = false; |
|
451,7 → 410,6 |
* |
* @see self::_send_binary_packet() |
* @var SymmetricKey|false |
* @access private |
*/ |
private $encrypt = false; |
|
459,7 → 417,6 |
* Encryption Algorithm Name |
* |
* @var string|null |
* @access private |
*/ |
private $encryptName; |
|
469,7 → 426,6 |
* Used by GCM |
* |
* @var string|null |
* @access private |
*/ |
private $encryptInvocationCounter; |
|
479,7 → 435,6 |
* Used by GCM |
* |
* @var string|null |
* @access private |
*/ |
private $encryptFixedPart; |
|
488,7 → 443,6 |
* |
* @see self::_send_binary_packet() |
* @var object |
* @access private |
*/ |
private $lengthEncrypt = false; |
|
497,7 → 451,6 |
* |
* @see self::_send_binary_packet() |
* @var object |
* @access private |
*/ |
private $hmac_create = false; |
|
505,7 → 458,6 |
* Client to Server HMAC Name |
* |
* @var string|false |
* @access private |
*/ |
private $hmac_create_name; |
|
513,7 → 465,6 |
* Client to Server ETM |
* |
* @var int|false |
* @access private |
*/ |
private $hmac_create_etm; |
|
522,7 → 473,6 |
* |
* @see self::_get_binary_packet() |
* @var object |
* @access private |
*/ |
private $hmac_check = false; |
|
530,7 → 480,6 |
* Server to Client HMAC Name |
* |
* @var string|false |
* @access private |
*/ |
private $hmac_check_name; |
|
538,7 → 487,6 |
* Server to Client ETM |
* |
* @var int|false |
* @access private |
*/ |
private $hmac_check_etm; |
|
551,7 → 499,6 |
* |
* @see self::_get_binary_packet() |
* @var int |
* @access private |
*/ |
private $hmac_size = false; |
|
560,7 → 507,6 |
* |
* @see self::getServerPublicHostKey() |
* @var string |
* @access private |
*/ |
private $server_public_host_key; |
|
575,7 → 521,6 |
* |
* @see self::_key_exchange() |
* @var string |
* @access private |
*/ |
private $session_id = false; |
|
586,7 → 531,6 |
* |
* @see self::_key_exchange() |
* @var string |
* @access private |
*/ |
private $exchange_hash = false; |
|
644,7 → 588,6 |
* |
* @see self::_send_binary_packet() |
* @var int |
* @access private |
*/ |
private $send_seq_no = 0; |
|
655,7 → 598,6 |
* |
* @see self::_get_binary_packet() |
* @var int |
* @access private |
*/ |
private $get_seq_no = 0; |
|
667,7 → 609,6 |
* @see self::get_channel_packet() |
* @see self::exec() |
* @var array |
* @access private |
*/ |
protected $server_channels = []; |
|
680,7 → 621,6 |
* @see self::get_channel_packet() |
* @see self::exec() |
* @var array |
* @access private |
*/ |
private $channel_buffers = []; |
|
691,7 → 631,6 |
* |
* @see self::get_channel_packet() |
* @var array |
* @access private |
*/ |
protected $channel_status = []; |
|
702,7 → 641,6 |
* |
* @see self::send_channel_packet() |
* @var array |
* @access private |
*/ |
private $packet_size_client_to_server = []; |
|
711,7 → 649,6 |
* |
* @see self::getLog() |
* @var array |
* @access private |
*/ |
private $message_number_log = []; |
|
720,7 → 657,6 |
* |
* @see self::getLog() |
* @var array |
* @access private |
*/ |
private $message_log = []; |
|
732,7 → 668,6 |
* @var int |
* @see self::send_channel_packet() |
* @see self::exec() |
* @access private |
*/ |
protected $window_size = 0x7FFFFFFF; |
|
746,7 → 681,6 |
* @var int |
* @see self::_send_channel_packet() |
* @see self::exec() |
* @access private |
*/ |
private $window_resize = 0x40000000; |
|
757,7 → 691,6 |
* |
* @see self::send_channel_packet() |
* @var array |
* @access private |
*/ |
protected $window_size_server_to_client = []; |
|
768,7 → 701,6 |
* |
* @see self::get_channel_packet() |
* @var array |
* @access private |
*/ |
private $window_size_client_to_server = []; |
|
779,7 → 711,6 |
* |
* @see self::getServerPublicHostKey() |
* @var string |
* @access private |
*/ |
private $signature = ''; |
|
790,7 → 721,6 |
* |
* @see self::getServerPublicHostKey() |
* @var string |
* @access private |
*/ |
private $signature_format = ''; |
|
799,7 → 729,6 |
* |
* @see self::read() |
* @var string |
* @access private |
*/ |
private $interactiveBuffer = ''; |
|
811,7 → 740,6 |
* @see self::_send_binary_packet() |
* @see self::_get_binary_packet() |
* @var int |
* @access private |
*/ |
private $log_size; |
|
819,7 → 747,6 |
* Timeout |
* |
* @see self::setTimeout() |
* @access private |
*/ |
protected $timeout; |
|
827,7 → 754,6 |
* Current Timeout |
* |
* @see self::get_channel_packet() |
* @access private |
*/ |
protected $curTimeout; |
|
835,7 → 761,6 |
* Keep Alive Interval |
* |
* @see self::setKeepAlive() |
* @access private |
*/ |
private $keepAlive; |
|
844,7 → 769,6 |
* |
* @see self::_append_log() |
* @var resource|closed-resource |
* @access private |
*/ |
private $realtime_log_file; |
|
853,7 → 777,6 |
* |
* @see self::_append_log() |
* @var int |
* @access private |
*/ |
private $realtime_log_size; |
|
862,7 → 785,6 |
* |
* @see self::getServerPublicHostKey() |
* @var bool |
* @access private |
*/ |
private $signature_validated = false; |
|
870,7 → 792,7 |
* Real-time log file wrap boolean |
* |
* @see self::_append_log() |
* @access private |
* @var bool |
*/ |
private $realtime_log_wrap; |
|
878,7 → 800,6 |
* Flag to suppress stderr from output |
* |
* @see self::enableQuietMode() |
* @access private |
*/ |
private $quiet_mode = false; |
|
886,7 → 807,6 |
* Time of first network activity |
* |
* @var float |
* @access private |
*/ |
private $last_packet; |
|
894,7 → 814,6 |
* Exit status returned from ssh if any |
* |
* @var int |
* @access private |
*/ |
private $exit_status; |
|
903,7 → 822,6 |
* |
* @var bool |
* @see self::enablePTY() |
* @access private |
*/ |
private $request_pty = false; |
|
911,7 → 829,6 |
* Flag set while exec() is running when using enablePTY() |
* |
* @var bool |
* @access private |
*/ |
private $in_request_pty_exec = false; |
|
919,7 → 836,6 |
* Flag set after startSubsystem() is called |
* |
* @var bool |
* @access private |
*/ |
private $in_subsystem; |
|
927,7 → 843,6 |
* Contents of stdError |
* |
* @var string |
* @access private |
*/ |
private $stdErrorLog; |
|
936,7 → 851,6 |
* |
* @see self::_keyboard_interactive_process() |
* @var string |
* @access private |
*/ |
private $last_interactive_response = ''; |
|
945,7 → 859,6 |
* |
* @see self::_keyboard_interactive_process() |
* @var array |
* @access private |
*/ |
private $keyboard_requests_responses = []; |
|
958,7 → 871,6 |
* @see self::_filter() |
* @see self::getBannerMessage() |
* @var string |
* @access private |
*/ |
private $banner_message = ''; |
|
967,7 → 879,6 |
* |
* @see self::isTimeout() |
* @var bool |
* @access private |
*/ |
private $is_timeout = false; |
|
976,7 → 887,6 |
* |
* @see self::_format_log() |
* @var string |
* @access private |
*/ |
private $log_boundary = ':'; |
|
985,7 → 895,6 |
* |
* @see self::_format_log() |
* @var int |
* @access private |
*/ |
private $log_long_width = 65; |
|
994,7 → 903,6 |
* |
* @see self::_format_log() |
* @var int |
* @access private |
*/ |
private $log_short_width = 16; |
|
1004,7 → 912,6 |
* @see self::__construct() |
* @see self::_connect() |
* @var string |
* @access private |
*/ |
private $host; |
|
1014,7 → 921,6 |
* @see self::__construct() |
* @see self::_connect() |
* @var int |
* @access private |
*/ |
private $port; |
|
1025,7 → 931,6 |
* @see self::setWindowColumns() |
* @see self::setWindowSize() |
* @var int |
* @access private |
*/ |
private $windowColumns = 80; |
|
1036,7 → 941,6 |
* @see self::setWindowRows() |
* @see self::setWindowSize() |
* @var int |
* @access private |
*/ |
private $windowRows = 24; |
|
1046,7 → 950,6 |
* @see self::setCryptoEngine() |
* @see self::_key_exchange() |
* @var int |
* @access private |
*/ |
private static $crypto_engine = false; |
|
1054,7 → 957,6 |
* A System_SSH_Agent for use in the SSH2 Agent Forwarding scenario |
* |
* @var Agent |
* @access private |
*/ |
private $agent; |
|
1070,7 → 972,6 |
* Send the identification string first? |
* |
* @var bool |
* @access private |
*/ |
private $send_id_string_first = true; |
|
1078,7 → 979,6 |
* Send the key exchange initiation packet first? |
* |
* @var bool |
* @access private |
*/ |
private $send_kex_first = true; |
|
1086,7 → 986,6 |
* Some versions of OpenSSH incorrectly calculate the key size |
* |
* @var bool |
* @access private |
*/ |
private $bad_key_size_fix = false; |
|
1094,7 → 993,6 |
* Should we try to re-connect to re-establish keys? |
* |
* @var bool |
* @access private |
*/ |
private $retry_connect = false; |
|
1102,7 → 1000,6 |
* Binary Packet Buffer |
* |
* @var string|false |
* @access private |
*/ |
private $binary_packet_buffer = false; |
|
1110,7 → 1007,6 |
* Preferred Signature Format |
* |
* @var string|false |
* @access private |
*/ |
protected $preferred_signature_format = false; |
|
1118,7 → 1014,6 |
* Authentication Credentials |
* |
* @var array |
* @access private |
*/ |
protected $auth = []; |
|
1126,7 → 1021,6 |
* Terminal |
* |
* @var string |
* @access private |
*/ |
private $term = 'vt100'; |
|
1135,7 → 1029,6 |
* |
* @see https://tools.ietf.org/html/rfc4252#section-5.1 |
* @var array|null |
* @access private |
*/ |
private $auth_methods_to_continue = null; |
|
1143,7 → 1036,6 |
* Compression method |
* |
* @var int |
* @access private |
*/ |
private $compress = self::NET_SSH2_COMPRESSION_NONE; |
|
1151,7 → 1043,6 |
* Decompression method |
* |
* @var int |
* @access private |
*/ |
private $decompress = self::NET_SSH2_COMPRESSION_NONE; |
|
1159,7 → 1050,6 |
* Compression context |
* |
* @var resource|false|null |
* @access private |
*/ |
private $compress_context; |
|
1167,7 → 1057,6 |
* Decompression context |
* |
* @var resource|object |
* @access private |
*/ |
private $decompress_context; |
|
1175,7 → 1064,6 |
* Regenerate Compression Context |
* |
* @var bool |
* @access private |
*/ |
private $regenerate_compression_context = false; |
|
1183,7 → 1071,6 |
* Regenerate Decompression Context |
* |
* @var bool |
* @access private |
*/ |
private $regenerate_decompression_context = false; |
|
1191,7 → 1078,6 |
* Smart multi-factor authentication flag |
* |
* @var bool |
* @access private |
*/ |
private $smartMFA = true; |
|
1204,7 → 1090,6 |
* @param int $port |
* @param int $timeout |
* @see self::login() |
* @access public |
*/ |
public function __construct($host, $port = 22, $timeout = 10) |
{ |
1314,7 → 1199,6 |
* OpenSSL, mcrypt, Eval, PHP |
* |
* @param int $engine |
* @access public |
*/ |
public static function setCryptoEngine($engine) |
{ |
1328,7 → 1212,6 |
* both sides MUST send an identification string". It does not say which side sends it first. In |
* theory it shouldn't matter but it is a fact of life that some SSH servers are simply buggy |
* |
* @access public |
*/ |
public function sendIdentificationStringFirst() |
{ |
1342,7 → 1225,6 |
* both sides MUST send an identification string". It does not say which side sends it first. In |
* theory it shouldn't matter but it is a fact of life that some SSH servers are simply buggy |
* |
* @access public |
*/ |
public function sendIdentificationStringLast() |
{ |
1356,7 → 1238,6 |
* sending the [SSH_MSG_KEXINIT] packet". It does not say which side sends it first. In theory |
* it shouldn't matter but it is a fact of life that some SSH servers are simply buggy |
* |
* @access public |
*/ |
public function sendKEXINITFirst() |
{ |
1370,7 → 1251,6 |
* sending the [SSH_MSG_KEXINIT] packet". It does not say which side sends it first. In theory |
* it shouldn't matter but it is a fact of life that some SSH servers are simply buggy |
* |
* @access public |
*/ |
public function sendKEXINITLast() |
{ |
1382,7 → 1262,6 |
* |
* @throws \UnexpectedValueException on receipt of unexpected packets |
* @throws \RuntimeException on other errors |
* @access private |
*/ |
private function connect() |
{ |
1526,7 → 1405,6 |
* |
* You should overwrite this method in your own class if you want to use another identifier |
* |
* @access protected |
* @return string |
*/ |
private function generate_identifier() |
1565,7 → 1443,6 |
* @throws \UnexpectedValueException on receipt of unexpected packets |
* @throws \RuntimeException on other errors |
* @throws \phpseclib3\Exception\NoSupportedAlgorithmsException when none of the algorithms phpseclib has loaded are compatible |
* @access private |
*/ |
private function key_exchange($kexinit_payload_server = false) |
{ |
2081,7 → 1958,6 |
* |
* @param string $algorithm Name of the encryption algorithm |
* @return int|null Number of bytes as an integer or null for unknown |
* @access private |
*/ |
private function encryption_algorithm_to_key_size($algorithm) |
{ |
2129,7 → 2005,6 |
* |
* @param string $algorithm Name of the encryption algorithm |
* @return SymmetricKey|null |
* @access private |
*/ |
private static function encryption_algorithm_to_crypt_instance($algorithm) |
{ |
2178,7 → 2053,6 |
* |
* @param string $algorithm Name of the encryption algorithm |
* @return array{Hash, int}|null |
* @access private |
*/ |
private static function mac_algorithm_to_hash_instance($algorithm) |
{ |
2214,7 → 2088,6 |
* @link https://bugzilla.mindrot.org/show_bug.cgi?id=1291 |
* @param string $algorithm Name of the encryption algorithm |
* @return bool |
* @access private |
*/ |
private static function bad_algorithm_candidate($algorithm) |
{ |
2237,7 → 2110,6 |
* @param string|AsymmetricKey|array[]|Agent|null ...$args |
* @return bool |
* @see self::_login() |
* @access public |
*/ |
public function login($username, ...$args) |
{ |
2263,7 → 2135,6 |
* @param string ...$args |
* @return bool |
* @see self::_login_helper() |
* @access private |
*/ |
protected function sublogin($username, ...$args) |
{ |
2361,7 → 2232,6 |
* @return bool |
* @throws \UnexpectedValueException on receipt of unexpected packets |
* @throws \RuntimeException on other errors |
* @access private |
*/ |
private function login_helper($username, $password = null) |
{ |
2468,7 → 2338,9 |
$this->send_binary_packet($packet, $logged); |
|
$response = $this->get_binary_packet(); |
|
if ($response === false) { |
return false; |
} |
list($type) = Strings::unpackSSH2('C', $response); |
switch ($type) { |
case NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ: // in theory, the password can be changed |
2507,7 → 2379,6 |
* @param string $username |
* @param string|array $password |
* @return bool |
* @access private |
*/ |
private function keyboard_interactive_login($username, $password) |
{ |
2531,7 → 2402,6 |
* @param string|array ...$responses |
* @return bool |
* @throws \RuntimeException on connection error |
* @access private |
*/ |
private function keyboard_interactive_process(...$responses) |
{ |
2628,7 → 2498,6 |
* @param string $username |
* @param \phpseclib3\System\SSH\Agent $agent |
* @return bool |
* @access private |
*/ |
private function ssh_agent_login($username, Agent $agent) |
{ |
2653,7 → 2522,6 |
* @param \phpseclib3\Crypt\Common\PrivateKey $privatekey |
* @return bool |
* @throws \RuntimeException on connection error |
* @access private |
*/ |
private function privatekey_login($username, PrivateKey $privatekey) |
{ |
2785,7 → 2653,6 |
* Setting $timeout to false or 0 will mean there is no timeout. |
* |
* @param mixed $timeout |
* @access public |
*/ |
public function setTimeout($timeout) |
{ |
2798,7 → 2665,6 |
* Sends an SSH2_MSG_IGNORE message every x seconds, if x is a positive non-zero number. |
* |
* @param int $interval |
* @access public |
*/ |
public function setKeepAlive($interval) |
{ |
2808,7 → 2674,6 |
/** |
* Get the output from stdError |
* |
* @access public |
*/ |
public function getStdError() |
{ |
2825,7 → 2690,6 |
* @return string|bool |
* @psalm-return ($callback is callable ? bool : string|bool) |
* @throws \RuntimeException on connection error |
* @access public |
*/ |
public function exec($command, callable $callback = null) |
{ |
2918,7 → 2782,7 |
|
$this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_DATA; |
|
if ($callback === false || $this->in_request_pty_exec) { |
if ($this->in_request_pty_exec) { |
return true; |
} |
|
2951,7 → 2815,6 |
* @return bool |
* @throws \UnexpectedValueException on receipt of unexpected packets |
* @throws \RuntimeException on other errors |
* @access private |
*/ |
private function initShell() |
{ |
3027,7 → 2890,6 |
* @see self::read() |
* @see self::write() |
* @return int |
* @access public |
*/ |
private function get_interactive_channel() |
{ |
3045,7 → 2907,6 |
* Return an available open channel |
* |
* @return int |
* @access public |
*/ |
private function get_open_channel() |
{ |
3063,7 → 2924,6 |
* Request agent forwarding of remote server |
* |
* @return bool |
* @access public |
*/ |
public function requestAgentForwarding() |
{ |
3104,7 → 2964,6 |
* @param int $mode |
* @return string|bool|null |
* @throws \RuntimeException on connection error |
* @access public |
*/ |
public function read($expect = '', $mode = self::READ_SIMPLE) |
{ |
3178,7 → 3037,6 |
* @see self::stopSubsystem() |
* @param string $subsystem |
* @return bool |
* @access public |
*/ |
public function startSubsystem($subsystem) |
{ |
3228,7 → 3086,6 |
* |
* @see self::startSubsystem() |
* @return bool |
* @access public |
*/ |
public function stopSubsystem() |
{ |
3242,7 → 3099,6 |
* |
* If read() timed out you might want to just close the channel and have it auto-restart on the next read() call |
* |
* @access public |
*/ |
public function reset() |
{ |
3254,7 → 3110,6 |
* |
* Did exec() or read() return because they timed out or because they encountered the end? |
* |
* @access public |
*/ |
public function isTimeout() |
{ |
3264,7 → 3119,6 |
/** |
* Disconnect |
* |
* @access public |
*/ |
public function disconnect() |
{ |
3281,7 → 3135,6 |
* Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call |
* disconnect(). |
* |
* @access public |
*/ |
public function __destruct() |
{ |
3292,7 → 3145,6 |
* Is the connection still active? |
* |
* @return bool |
* @access public |
*/ |
public function isConnected() |
{ |
3303,7 → 3155,6 |
* Have you successfully been logged in? |
* |
* @return bool |
* @access public |
*/ |
public function isAuthenticated() |
{ |
3371,7 → 3222,6 |
* Resets a connection for re-use |
* |
* @param int $reason |
* @access private |
*/ |
protected function reset_connection($reason) |
{ |
3393,7 → 3243,6 |
* @see self::_send_binary_packet() |
* @param bool $skip_channel_filter |
* @return bool|string |
* @access private |
*/ |
private function get_binary_packet($skip_channel_filter = false) |
{ |
3447,8 → 3296,12 |
|
if (!is_resource($this->fsock) || feof($this->fsock)) { |
$this->bitmap = 0; |
throw new ConnectionClosedException('Connection closed (by server) prematurely ' . $elapsed . 's'); |
$str = 'Connection closed (by server) prematurely'; |
if (isset($elapsed)) { |
$str .= ' ' . $elapsed . 's'; |
} |
throw new ConnectionClosedException($str); |
} |
|
$start = microtime(true); |
$raw = stream_get_contents($this->fsock, $this->decrypt_block_size); |
3639,7 → 3492,6 |
* @see self::get_binary_packet() |
* @param int $remaining_length |
* @return string |
* @access private |
*/ |
private function read_remaining_bytes($remaining_length) |
{ |
3699,7 → 3551,6 |
* @param string $payload |
* @param bool $skip_channel_filter |
* @return string|bool |
* @access private |
*/ |
private function filter($payload, $skip_channel_filter) |
{ |
3850,7 → 3701,6 |
* |
* Suppress stderr from output |
* |
* @access public |
*/ |
public function enableQuietMode() |
{ |
3862,7 → 3712,6 |
* |
* Show stderr in output |
* |
* @access public |
*/ |
public function disableQuietMode() |
{ |
3874,7 → 3723,6 |
* |
* @see self::enableQuietMode() |
* @see self::disableQuietMode() |
* @access public |
* @return bool |
*/ |
public function isQuietModeEnabled() |
3885,7 → 3733,6 |
/** |
* Enable request-pty when using exec() |
* |
* @access public |
*/ |
public function enablePTY() |
{ |
3895,7 → 3742,6 |
/** |
* Disable request-pty when using exec() |
* |
* @access public |
*/ |
public function disablePTY() |
{ |
3911,7 → 3757,6 |
* |
* @see self::enablePTY() |
* @see self::disablePTY() |
* @access public |
* @return bool |
*/ |
public function isPTYEnabled() |
3937,7 → 3782,6 |
* @param bool $skip_extended |
* @return mixed |
* @throws \RuntimeException on connection error |
* @access private |
*/ |
protected function get_channel_packet($client_channel, $skip_extended = false) |
{ |
4161,7 → 4005,6 |
* @param string $logged |
* @see self::_get_binary_packet() |
* @return void |
* @access private |
*/ |
protected function send_binary_packet($data, $logged = null) |
{ |
4306,28 → 4149,61 |
* |
* @param string $message_number |
* @param string $message |
* @access private |
*/ |
private function append_log($message_number, $message) |
{ |
$this->append_log_helper( |
NET_SSH2_LOGGING, |
$message_number, |
$message, |
$this->message_number_log, |
$this->message_log, |
$this->log_size, |
$this->realtime_log_file, |
$this->realtime_log_wrap, |
$this->realtime_log_size |
); |
} |
|
/** |
* Logs data packet helper |
* |
* @param int $constant |
* @param string $message_number |
* @param string $message |
* @param array &$message_number_log |
* @param array &$message_log |
* @param int &$log_size |
* @param resource &$realtime_log_file |
* @param bool &$realtime_log_wrap |
* @param int &$realtime_log_size |
*/ |
protected function append_log_helper($constant, $message_number, $message, array &$message_number_log, array &$message_log, &$log_size, &$realtime_log_file, &$realtime_log_wrap, &$realtime_log_size) |
{ |
// remove the byte identifying the message type from all but the first two messages (ie. the identification strings) |
if (strlen($message_number) > 2) { |
Strings::shift($message); |
} |
|
switch (NET_SSH2_LOGGING) { |
switch ($constant) { |
// useful for benchmarks |
case self::LOG_SIMPLE: |
$this->message_number_log[] = $message_number; |
$message_number_log[] = $message_number; |
break; |
case self::LOG_SIMPLE_REALTIME: |
echo $message_number; |
echo PHP_SAPI == 'cli' ? "\r\n" : '<br>'; |
@flush(); |
@ob_flush(); |
break; |
// the most useful log for SSH2 |
case self::LOG_COMPLEX: |
$this->message_number_log[] = $message_number; |
$this->log_size += strlen($message); |
$this->message_log[] = $message; |
while ($this->log_size > self::LOG_MAX_SIZE) { |
$this->log_size -= strlen(array_shift($this->message_log)); |
array_shift($this->message_number_log); |
$message_number_log[] = $message_number; |
$log_size += strlen($message); |
$message_log[] = $message; |
while ($log_size > self::LOG_MAX_SIZE) { |
$log_size -= strlen(array_shift($message_log)); |
array_shift($message_number_log); |
} |
break; |
// dump the output out realtime; packets may be interspersed with non packets, |
4351,28 → 4227,28 |
// the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily |
// at the beginning of the file |
case self::LOG_REALTIME_FILE: |
if (!isset($this->realtime_log_file)) { |
if (!isset($realtime_log_file)) { |
// PHP doesn't seem to like using constants in fopen() |
$filename = NET_SSH2_LOG_REALTIME_FILENAME; |
$fp = fopen($filename, 'w'); |
$this->realtime_log_file = $fp; |
$realtime_log_file = $fp; |
} |
if (!is_resource($this->realtime_log_file)) { |
if (!is_resource($realtime_log_file)) { |
break; |
} |
$entry = $this->format_log([$message], [$message_number]); |
if ($this->realtime_log_wrap) { |
if ($realtime_log_wrap) { |
$temp = "<<< START >>>\r\n"; |
$entry .= $temp; |
fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp)); |
fseek($realtime_log_file, ftell($realtime_log_file) - strlen($temp)); |
} |
$this->realtime_log_size += strlen($entry); |
if ($this->realtime_log_size > self::LOG_MAX_SIZE) { |
fseek($this->realtime_log_file, 0); |
$this->realtime_log_size = strlen($entry); |
$this->realtime_log_wrap = true; |
$realtime_log_size += strlen($entry); |
if ($realtime_log_size > self::LOG_MAX_SIZE) { |
fseek($realtime_log_file, 0); |
$realtime_log_size = strlen($entry); |
$realtime_log_wrap = true; |
} |
fputs($this->realtime_log_file, $entry); |
fputs($realtime_log_file, $entry); |
} |
} |
|
4426,7 → 4302,6 |
* @param int $client_channel |
* @param bool $want_reply |
* @return void |
* @access private |
*/ |
private function close_channel($client_channel, $want_reply = false) |
{ |
4463,7 → 4338,6 |
* |
* @param int $reason |
* @return false |
* @access protected |
*/ |
protected function disconnect_helper($reason) |
{ |
4511,7 → 4385,6 |
* |
* Returns a string if NET_SSH2_LOGGING == self::LOG_COMPLEX, an array if NET_SSH2_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SSH2_LOGGING') |
* |
* @access public |
* @return array|false|string |
*/ |
public function getLog() |
4536,10 → 4409,9 |
* |
* @param array $message_log |
* @param array $message_number_log |
* @access private |
* @return string |
*/ |
protected function format_log($message_log, $message_number_log) |
protected function format_log(array $message_log, array $message_number_log) |
{ |
$output = ''; |
for ($i = 0; $i < count($message_log); $i++) { |
4574,7 → 4446,6 |
* of said channel opening. Must be called after |
* channel open confirmation received |
* |
* @access private |
*/ |
private function on_channel_open() |
{ |
4590,9 → 4461,8 |
* @param array $array1 |
* @param array $array2 |
* @return mixed False if intersection is empty, else intersected value. |
* @access private |
*/ |
private static function array_intersect_first($array1, $array2) |
private static function array_intersect_first(array $array1, array $array2) |
{ |
foreach ($array1 as $value) { |
if (in_array($value, $array2)) { |
4606,7 → 4476,6 |
* Returns all errors |
* |
* @return string[] |
* @access public |
*/ |
public function getErrors() |
{ |
4617,7 → 4486,6 |
* Returns the last error |
* |
* @return string |
* @access public |
*/ |
public function getLastError() |
{ |
4632,7 → 4500,6 |
* Return the server identification. |
* |
* @return string|false |
* @access public |
*/ |
public function getServerIdentification() |
{ |
4645,7 → 4512,6 |
* Returns a list of algorithms the server supports |
* |
* @return array |
* @access public |
*/ |
public function getServerAlgorithms() |
{ |
4673,7 → 4539,6 |
* Returns a list of KEX algorithms that phpseclib supports |
* |
* @return array |
* @access public |
*/ |
public static function getSupportedKEXAlgorithms() |
{ |
4710,7 → 4575,6 |
* Returns a list of host key algorithms that phpseclib supports |
* |
* @return array |
* @access public |
*/ |
public static function getSupportedHostKeyAlgorithms() |
{ |
4730,7 → 4594,6 |
* Returns a list of symmetric key algorithms that phpseclib supports |
* |
* @return array |
* @access public |
*/ |
public static function getSupportedEncryptionAlgorithms() |
{ |
4750,7 → 4613,7 |
'aes192-ctr', // RECOMMENDED AES with 192-bit key |
'aes256-ctr', // RECOMMENDED AES with 256-bit key |
|
// from <https://git.io/fhxOl>: |
// from <https://github.com/openssh/openssh-portable/blob/001aa55/PROTOCOL.chacha20poly1305>: |
// one of the big benefits of chacha20-poly1305 is speed. the problem is... |
// libsodium doesn't generate the poly1305 keys in the way ssh does and openssl's PHP bindings don't even |
// seem to support poly1305 currently. so even if libsodium or openssl are being used for the chacha20 |
4835,7 → 4698,6 |
* Returns a list of MAC algorithms that phpseclib supports |
* |
* @return array |
* @access public |
*/ |
public static function getSupportedMACAlgorithms() |
{ |
4866,7 → 4728,6 |
* Returns a list of compression algorithms that phpseclib supports |
* |
* @return array |
* @access public |
*/ |
public static function getSupportedCompressionAlgorithms() |
{ |
4884,7 → 4745,6 |
* Uses the same format as https://www.php.net/ssh2-methods-negotiated |
* |
* @return array |
* @access public |
*/ |
public function getAlgorithmsNegotiated() |
{ |
4916,7 → 4776,6 |
* Allows you to set the terminal |
* |
* @param string $term |
* @access public |
*/ |
public function setTerminal($term) |
{ |
4928,7 → 4787,6 |
* <https://www.php.net/manual/en/function.ssh2-connect.php> |
* |
* @param array $methods |
* @access public |
*/ |
public function setPreferredAlgorithms(array $methods) |
{ |
5015,7 → 4873,6 |
* authentication may be relevant for getting legal protection." |
* |
* @return string |
* @access public |
*/ |
public function getBannerMessage() |
{ |
5031,7 → 4888,6 |
* @return string|false |
* @throws \RuntimeException on badly formatted keys |
* @throws \phpseclib3\Exception\NoSupportedAlgorithmsException when the key isn't in a supported format |
* @access public |
*/ |
public function getServerPublicHostKey() |
{ |
5116,7 → 4972,6 |
* Returns the exit status of an SSH command or false. |
* |
* @return false|int |
* @access public |
*/ |
public function getExitStatus() |
{ |
5130,7 → 4985,6 |
* Returns the number of columns for the terminal window size. |
* |
* @return int |
* @access public |
*/ |
public function getWindowColumns() |
{ |
5141,7 → 4995,6 |
* Returns the number of rows for the terminal window size. |
* |
* @return int |
* @access public |
*/ |
public function getWindowRows() |
{ |
5152,7 → 5005,6 |
* Sets the number of columns for the terminal window size. |
* |
* @param int $value |
* @access public |
*/ |
public function setWindowColumns($value) |
{ |
5163,7 → 5015,6 |
* Sets the number of rows for the terminal window size. |
* |
* @param int $value |
* @access public |
*/ |
public function setWindowRows($value) |
{ |
5175,7 → 5026,6 |
* |
* @param int $columns |
* @param int $rows |
* @access public |
*/ |
public function setWindowSize($columns = 80, $rows = 24) |
{ |
5187,7 → 5037,6 |
* To String Magic Method |
* |
* @return string |
* @access public |
*/ |
#[\ReturnTypeWillChange] |
public function __toString() |
5248,7 → 5097,6 |
* |
* @param string $old |
* @param string $new |
* @access private |
*/ |
private function updateLogHistory($old, $new) |
{ |