1
0
mirror of https://github.com/danog/phpseclib.git synced 2024-12-11 16:49:42 +01:00

Merge branch '1.0' into 2.0

This commit is contained in:
terrafrost 2021-10-26 20:14:31 -05:00
commit 2de84fba24

View File

@ -61,6 +61,23 @@ use phpseclib\Crypt\Twofish;
use phpseclib\Math\BigInteger; // Used to do Diffie-Hellman key exchange and DSA/RSA signature verification. use phpseclib\Math\BigInteger; // Used to do Diffie-Hellman key exchange and DSA/RSA signature verification.
use phpseclib\System\SSH\Agent; use phpseclib\System\SSH\Agent;
/**#@+
* @access private
*/
/**
* No compression
*/
define('NET_SSH2_COMPRESSION_NONE', 1);
/**
* zlib compression
*/
define('NET_SSH2_COMPRESSION_ZLIB', 2);
/**
* zlib@openssh.com
*/
define('NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH', 3);
/**#@-*/
/** /**
* Pure-PHP implementation of SSHv2. * Pure-PHP implementation of SSHv2.
* *
@ -975,8 +992,57 @@ class SSH2
* *
* @see https://tools.ietf.org/html/rfc4252#section-5.1 * @see https://tools.ietf.org/html/rfc4252#section-5.1
* @var array|null * @var array|null
* @access private
*/ */
private $auth_methods_to_continue = null; var $auth_methods_to_continue = null;
/**
* Compression method
*
* @var int
* @access private
*/
var $compress = NET_SSH2_COMPRESSION_NONE;
/**
* Decompression method
*
* @var resource|object
* @access private
*/
var $decompress = NET_SSH2_COMPRESSION_NONE;
/**
* Compression context
*
* @var int
* @access private
*/
var $compress_context;
/**
* Decompression context
*
* @var resource|object
* @access private
*/
var $decompress_context;
/**
* Regenerate Compression Context
*
* @var bool
* @access private
*/
var $regenerate_compression_context = false;
/**
* Regenerate Decompression Context
*
* @var bool
* @access private
*/
var $regenerate_decompression_context = false;
/** /**
* Default Constructor. * Default Constructor.
@ -1569,19 +1635,25 @@ class SSH2
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
$compression_map = array(
'none' => NET_SSH2_COMPRESSION_NONE,
'zlib' => NET_SSH2_COMPRESSION_ZLIB,
'zlib@openssh.com' => NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH
);
$compression_algorithm_out = $this->_array_intersect_first($c2s_compression_algorithms, $this->compression_algorithms_client_to_server); $compression_algorithm_out = $this->_array_intersect_first($c2s_compression_algorithms, $this->compression_algorithms_client_to_server);
if ($compression_algorithm_out === false) { if ($compression_algorithm_out === false) {
user_error('No compatible client to server compression algorithms found'); user_error('No compatible client to server compression algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
//$this->decompress = $compression_algorithm_out == 'zlib'; $this->compress = $compression_map[$compression_algorithm_out];
$compression_algorithm_in = $this->_array_intersect_first($s2c_compression_algorithms, $this->compression_algorithms_client_to_server); $compression_algorithm_in = $this->_array_intersect_first($s2c_compression_algorithms, $this->compression_algorithms_server_to_client);
if ($compression_algorithm_in === false) { if ($compression_algorithm_in === false) {
user_error('No compatible server to client compression algorithms found'); user_error('No compatible server to client compression algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
//$this->compress = $compression_algorithm_in == 'zlib'; $this->decompress = $compression_map[$compression_algorithm_in];
// Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty. // Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty.
$exchange_hash_rfc4419 = ''; $exchange_hash_rfc4419 = '';
@ -2014,6 +2086,8 @@ class SSH2
} }
$this->hmac_check->setKey(substr($key, 0, $checkKeyLength)); $this->hmac_check->setKey(substr($key, 0, $checkKeyLength));
$this->regenerate_compression_context = $this->regenerate_decompression_context = true;
return true; return true;
} }
@ -3382,7 +3456,7 @@ class SSH2
if (!is_resource($this->fsock) || feof($this->fsock)) { if (!is_resource($this->fsock) || feof($this->fsock)) {
$this->bitmap = 0; $this->bitmap = 0;
user_error('Connection closed (by server) prematurely'); user_error('Connection closed (by server) prematurely ' . $elapsed . 's');
return false; return false;
} }
@ -3453,9 +3527,41 @@ class SSH2
} }
} }
//if ($this->decompress) { switch ($this->decompress) {
// $payload = gzinflate(substr($payload, 2)); case NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH:
//} if (!$this->isAuthenticated()) {
break;
}
case NET_SSH2_COMPRESSION_ZLIB:
if ($this->regenerate_decompression_context) {
$this->regenerate_decompression_context = false;
$cmf = ord($payload[0]);
$cm = $cmf & 0x0F;
if ($cm != 8) { // deflate
user_error("Only CM = 8 ('deflate') is supported ($cm)");
}
$cinfo = ($cmf & 0xF0) >> 4;
if ($cinfo > 7) {
user_error("CINFO above 7 is not allowed ($cinfo)");
}
$windowSize = 1 << ($cinfo + 8);
$flg = ord($payload[1]);
//$fcheck = $flg && 0x0F;
if ((($cmf << 8) | $flg) % 31) {
user_error('fcheck failed');
}
$fdict = boolval($flg & 0x20);
$flevel = ($flg & 0xC0) >> 6;
$this->decompress_context = inflate_init(ZLIB_ENCODING_RAW, ['window' => $cinfo + 8]);
$payload = substr($payload, 2);
}
if ($this->decompress_context) {
$payload = inflate_add($this->decompress_context, $payload, ZLIB_PARTIAL_FLUSH);
}
}
$this->get_seq_no++; $this->get_seq_no++;
@ -4009,11 +4115,27 @@ class SSH2
return false; return false;
} }
//if ($this->compress) { if (!isset($logged)) {
// // the -4 removes the checksum: $logged = $data;
// // http://php.net/function.gzcompress#57710 }
// $data = substr(gzcompress($data), 0, -4);
//} switch ($this->compress) {
case NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH:
if (!$this->isAuthenticated()) {
break;
}
case NET_SSH2_COMPRESSION_ZLIB:
if (!$this->regenerate_compression_context) {
$header = '';
} else {
$this->regenerate_compression_context = false;
$this->compress_context = deflate_init(ZLIB_ENCODING_RAW, ['window' => 15]);
$header = "\x78\x9C";
}
if ($this->compress_context) {
$data = $header . deflate_add($this->compress_context, $data, ZLIB_PARTIAL_FLUSH);
}
}
// 4 (packet length) + 1 (padding length) + 4 (minimal padding amount) == 9 // 4 (packet length) + 1 (padding length) + 4 (minimal padding amount) == 9
$packet_length = strlen($data) + 9; $packet_length = strlen($data) + 9;
@ -4041,10 +4163,10 @@ class SSH2
if (defined('NET_SSH2_LOGGING')) { if (defined('NET_SSH2_LOGGING')) {
$current = microtime(true); $current = microtime(true);
$message_number = isset($this->message_numbers[ord($data[0])]) ? $this->message_numbers[ord($data[0])] : 'UNKNOWN (' . ord($data[0]) . ')'; $message_number = isset($this->message_numbers[ord($logged[0])]) ? $this->message_numbers[ord($logged[0])] : 'UNKNOWN (' . ord($logged[0]) . ')';
$message_number = '-> ' . $message_number . $message_number = '-> ' . $message_number .
' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)'; ' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)';
$this->_append_log($message_number, isset($logged) ? $logged : $data); $this->_append_log($message_number, $logged);
$this->last_packet = $current; $this->last_packet = $current;
} }
@ -4739,10 +4861,12 @@ class SSH2
*/ */
function getSupportedCompressionAlgorithms() function getSupportedCompressionAlgorithms()
{ {
return array( $algos = array('none'); // REQUIRED no compression
'none' // REQUIRED no compression if (function_exists('deflate_init')) {
//'zlib' // OPTIONAL ZLIB (LZ77) compression $algos[] = 'zlib@openssh.com'; // https://datatracker.ietf.org/doc/html/draft-miller-secsh-compression-delayed
); $algos[] = 'zlib';
}
return $algos;
} }
/** /**
@ -4757,18 +4881,24 @@ class SSH2
{ {
$this->_connect(); $this->_connect();
$compression_map = array(
NET_SSH2_COMPRESSION_NONE => 'none',
NET_SSH2_COMPRESSION_ZLIB => 'zlib',
NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH => 'zlib@openssh.com'
);
return array( return array(
'kex' => $this->kex_algorithm, 'kex' => $this->kex_algorithm,
'hostkey' => $this->signature_format, 'hostkey' => $this->signature_format,
'client_to_server' => array( 'client_to_server' => array(
'crypt' => $this->encrypt->name, 'crypt' => $this->encrypt->name,
'mac' => $this->hmac_create->name, 'mac' => $this->hmac_create->name,
'comp' => 'none', 'comp' => $compression_map[$this->compress],
), ),
'server_to_client' => array( 'server_to_client' => array(
'crypt' => $this->decrypt->name, 'crypt' => $this->decrypt->name,
'mac' => $this->hmac_check->name, 'mac' => $this->hmac_check->name,
'comp' => 'none', 'comp' => $compression_map[$this->decompress],
) )
); );
} }