Moved the phpseclib files to their own folder in libraries. Improved the composer autoloader in JCB. Improved the phpseclib class implementation. Added a new Expert Mode to field modeling under the database tab in the field area.
This commit is contained in:
@ -1,17 +1,17 @@
|
||||
[
|
||||
{
|
||||
"name": "phpseclib/phpseclib",
|
||||
"version": "2.0.21",
|
||||
"version_normalized": "2.0.21.0",
|
||||
"version": "2.0.23",
|
||||
"version_normalized": "2.0.23.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||
"reference": "9f1287e68b3f283339a9f98f67515dd619e5bf9d"
|
||||
"reference": "c78eb5058d5bb1a183133c36d4ba5b6675dfa099"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/9f1287e68b3f283339a9f98f67515dd619e5bf9d",
|
||||
"reference": "9f1287e68b3f283339a9f98f67515dd619e5bf9d",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/c78eb5058d5bb1a183133c36d4ba5b6675dfa099",
|
||||
"reference": "c78eb5058d5bb1a183133c36d4ba5b6675dfa099",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -29,7 +29,7 @@
|
||||
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
|
||||
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
|
||||
},
|
||||
"time": "2019-07-12T12:53:49+00:00",
|
||||
"time": "2019-09-17T03:41:22+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
7
libraries/phpseclib/vendor/phpseclib/phpseclib/BACKERS.md
vendored
Normal file
7
libraries/phpseclib/vendor/phpseclib/phpseclib/BACKERS.md
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
# Backers
|
||||
|
||||
phpseclib ongoing development is made possible by [Tidelift](https://tidelift.com/subscription/pkg/packagist-phpseclib-phpseclib?utm_source=packagist-phpseclib-phpseclib&utm_medium=referral&utm_campaign=readme) and by contributions by users like you. Thank you.
|
||||
|
||||
## Backers
|
||||
|
||||
- Zane Hooper
|
@ -45,7 +45,7 @@ AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509
|
||||
* Composer compatible (PSR-0 autoloading)
|
||||
* Install using Composer: `composer require phpseclib/phpseclib:~1.0`
|
||||
* Install using PEAR: See [phpseclib PEAR Channel Documentation](http://phpseclib.sourceforge.net/pear.htm)
|
||||
* [Download 1.0.16 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.16.zip/download)
|
||||
* [Download 1.0.17 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.17.zip/download)
|
||||
|
||||
## Security contact information
|
||||
|
@ -702,7 +702,14 @@ class ASN1
|
||||
return isset($this->oids[$decoded['content']]) ? $this->oids[$decoded['content']] : $decoded['content'];
|
||||
case self::TYPE_UTC_TIME:
|
||||
case self::TYPE_GENERALIZED_TIME:
|
||||
if (isset($mapping['implicit'])) {
|
||||
// for explicitly tagged optional stuff
|
||||
if (is_array($decoded['content'])) {
|
||||
$decoded['content'] = $decoded['content'][0]['content'];
|
||||
}
|
||||
// for implicitly tagged optional stuff
|
||||
// in theory, doing isset($mapping['implicit']) would work but malformed certs do exist
|
||||
// in the wild that OpenSSL decodes without issue so we'll support them as well
|
||||
if (!is_object($decoded['content'])) {
|
||||
$decoded['content'] = $this->_decodeTime($decoded['content'], $decoded['type']);
|
||||
}
|
||||
return $decoded['content'] ? $decoded['content']->format($this->format) : false;
|
||||
@ -843,7 +850,7 @@ class ASN1
|
||||
if ($mapping['type'] == self::TYPE_SET) {
|
||||
sort($value);
|
||||
}
|
||||
$value = implode($value, '');
|
||||
$value = implode('', $value);
|
||||
break;
|
||||
}
|
||||
|
@ -963,6 +963,13 @@ class X509
|
||||
'children' => $AccessDescription
|
||||
);
|
||||
|
||||
$this->SubjectInfoAccessSyntax = array(
|
||||
'type' => ASN1::TYPE_SEQUENCE,
|
||||
'min' => 1,
|
||||
'max' => -1,
|
||||
'children' => $AccessDescription
|
||||
);
|
||||
|
||||
$this->SubjectAltName = $GeneralNames;
|
||||
|
||||
$this->PrivateKeyUsagePeriod = array(
|
||||
@ -1620,7 +1627,10 @@ class X509
|
||||
corresponding to the extension type identified by extnID */
|
||||
$map = $this->_getMapping($id);
|
||||
if (!is_bool($map)) {
|
||||
$mapped = $asn1->asn1map($decoded[0], $map, array('iPAddress' => array($this, '_decodeIP')));
|
||||
$decoder = $id == 'id-ce-nameConstraints' ?
|
||||
array($this, '_decodeNameConstraintIP') :
|
||||
array($this, '_decodeIP');
|
||||
$mapped = $asn1->asn1map($decoded[0], $map, array('iPAddress' => $decoder));
|
||||
$value = $mapped === false ? $decoded[0] : $mapped;
|
||||
|
||||
if ($id == 'id-ce-certificatePolicies') {
|
||||
@ -1889,6 +1899,8 @@ class X509
|
||||
return $this->ExtKeyUsageSyntax;
|
||||
case 'id-pe-authorityInfoAccess':
|
||||
return $this->AuthorityInfoAccessSyntax;
|
||||
case 'id-pe-subjectInfoAccess':
|
||||
return $this->SubjectInfoAccessSyntax;
|
||||
case 'id-ce-subjectAltName':
|
||||
return $this->SubjectAltName;
|
||||
case 'id-ce-subjectDirectoryAttributes':
|
||||
@ -2511,18 +2523,38 @@ class X509
|
||||
return inet_ntop(base64_decode($ip));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes an IP address in a name constraints extension
|
||||
*
|
||||
* Takes in a base64 encoded "blob" and returns a human readable IP address / mask
|
||||
*
|
||||
* @param string $ip
|
||||
* @access private
|
||||
* @return array
|
||||
*/
|
||||
function _decodeNameConstraintIP($ip)
|
||||
{
|
||||
$ip = base64_decode($ip);
|
||||
$size = strlen($ip) >> 1;
|
||||
$mask = substr($ip, $size);
|
||||
$ip = substr($ip, 0, $size);
|
||||
return array(inet_ntop($ip), inet_ntop($mask));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes an IP address
|
||||
*
|
||||
* Takes a human readable IP address into a base64-encoded "blob"
|
||||
*
|
||||
* @param string $ip
|
||||
* @param string|array $ip
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
function _encodeIP($ip)
|
||||
{
|
||||
return base64_encode(inet_pton($ip));
|
||||
return is_string($ip) ?
|
||||
base64_encode(inet_pton($ip)) :
|
||||
base64_encode(inet_pton($ip[0]) . inet_pton($ip[1]));
|
||||
}
|
||||
|
||||
/**
|
@ -545,7 +545,7 @@ class BigInteger
|
||||
$bytes = chr(0);
|
||||
}
|
||||
|
||||
if (ord($bytes[0]) & 0x80) {
|
||||
if ($this->precision <= 0 && (ord($bytes[0]) & 0x80)) {
|
||||
$bytes = chr(0) . $bytes;
|
||||
}
|
||||
|
||||
@ -707,6 +707,7 @@ class BigInteger
|
||||
}
|
||||
|
||||
$temp = $this->copy();
|
||||
$temp->bitmask = false;
|
||||
$temp->is_negative = false;
|
||||
|
||||
$divisor = new static();
|
||||
@ -843,7 +844,7 @@ class BigInteger
|
||||
$opts[] = 'OpenSSL';
|
||||
}
|
||||
if (!empty($opts)) {
|
||||
$engine.= ' (' . implode($opts, ', ') . ')';
|
||||
$engine.= ' (' . implode('.', $opts) . ')';
|
||||
}
|
||||
return array(
|
||||
'value' => '0x' . $this->toHex(true),
|
||||
@ -3569,7 +3570,14 @@ class BigInteger
|
||||
switch (MATH_BIGINTEGER_MODE) {
|
||||
case self::MODE_GMP:
|
||||
if ($this->bitmask !== false) {
|
||||
$flip = gmp_cmp($result->value, gmp_init(0)) < 0;
|
||||
if ($flip) {
|
||||
$result->value = gmp_neg($result->value);
|
||||
}
|
||||
$result->value = gmp_and($result->value, $result->bitmask->value);
|
||||
if ($flip) {
|
||||
$result->value = gmp_neg($result->value);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
@ -410,6 +410,7 @@ class SFTP extends SSH2
|
||||
function login($username)
|
||||
{
|
||||
$args = func_get_args();
|
||||
$this->auth[] = $args;
|
||||
if (!call_user_func_array(array(&$this, '_login'), $args)) {
|
||||
return false;
|
||||
}
|
||||
@ -2975,6 +2976,20 @@ class SFTP extends SSH2
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets a connection for re-use
|
||||
*
|
||||
* @param int $reason
|
||||
* @access private
|
||||
*/
|
||||
function _reset_connection($reason)
|
||||
{
|
||||
parent::_reset_connection($reason);
|
||||
$this->use_request_id = false;
|
||||
$this->pwd = false;
|
||||
$this->requestBuffer = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives SFTP Packets
|
||||
*
|
@ -209,6 +209,15 @@ class SSH2
|
||||
*/
|
||||
var $kex_algorithms = false;
|
||||
|
||||
/**
|
||||
* Key Exchange Algorithm
|
||||
*
|
||||
* @see self::getMethodsNegotiated()
|
||||
* @var string|false
|
||||
* @access private
|
||||
*/
|
||||
var $kex_algorithm = false;
|
||||
|
||||
/**
|
||||
* Minimum Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods
|
||||
*
|
||||
@ -317,6 +326,15 @@ class SSH2
|
||||
*/
|
||||
var $languages_client_to_server = false;
|
||||
|
||||
/**
|
||||
* Preferred Algorithms
|
||||
*
|
||||
* @see self::setPreferredAlgorithms()
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
var $preferred = array();
|
||||
|
||||
/**
|
||||
* Block Size for Server to Client Encryption
|
||||
*
|
||||
@ -898,14 +916,6 @@ class SSH2
|
||||
*/
|
||||
var $bad_key_size_fix = false;
|
||||
|
||||
/**
|
||||
* The selected decryption algorithm
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $decrypt_algorithm = '';
|
||||
|
||||
/**
|
||||
* Should we try to re-connect to re-establish keys?
|
||||
*
|
||||
@ -1280,7 +1290,7 @@ class SSH2
|
||||
$identifier = 'SSH-2.0-phpseclib_2.0';
|
||||
|
||||
$ext = array();
|
||||
if (function_exists('\\Sodium\\library_version_major')) {
|
||||
if (function_exists('sodium_crypto_box_publickey_from_secretkey')) {
|
||||
$ext[] = 'libsodium';
|
||||
}
|
||||
|
||||
@ -1311,141 +1321,59 @@ class SSH2
|
||||
*/
|
||||
function _key_exchange($kexinit_payload_server = false)
|
||||
{
|
||||
$kex_algorithms = array(
|
||||
// Elliptic Curve Diffie-Hellman Key Agreement (ECDH) using
|
||||
// Curve25519. See doc/curve25519-sha256@libssh.org.txt in the
|
||||
// libssh repository for more information.
|
||||
'curve25519-sha256@libssh.org',
|
||||
$preferred = $this->preferred;
|
||||
|
||||
// Diffie-Hellman Key Agreement (DH) using integer modulo prime
|
||||
// groups.
|
||||
'diffie-hellman-group1-sha1', // REQUIRED
|
||||
'diffie-hellman-group14-sha1', // REQUIRED
|
||||
'diffie-hellman-group-exchange-sha1', // RFC 4419
|
||||
'diffie-hellman-group-exchange-sha256', // RFC 4419
|
||||
);
|
||||
if (!function_exists('\\Sodium\\library_version_major')) {
|
||||
$kex_algorithms = array_diff(
|
||||
$kex_algorithms,
|
||||
array('curve25519-sha256@libssh.org')
|
||||
);
|
||||
}
|
||||
|
||||
$server_host_key_algorithms = array(
|
||||
'rsa-sha2-256', // RFC 8332
|
||||
'rsa-sha2-512', // RFC 8332
|
||||
'ssh-rsa', // RECOMMENDED sign Raw RSA Key
|
||||
'ssh-dss' // REQUIRED sign Raw DSS Key
|
||||
);
|
||||
|
||||
$encryption_algorithms = array(
|
||||
// from <http://tools.ietf.org/html/rfc4345#section-4>:
|
||||
'arcfour256',
|
||||
'arcfour128',
|
||||
|
||||
//'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key
|
||||
|
||||
// CTR modes from <http://tools.ietf.org/html/rfc4344#section-4>:
|
||||
'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key
|
||||
'aes192-ctr', // RECOMMENDED AES with 192-bit key
|
||||
'aes256-ctr', // RECOMMENDED AES with 256-bit key
|
||||
|
||||
'twofish128-ctr', // OPTIONAL Twofish in SDCTR mode, with 128-bit key
|
||||
'twofish192-ctr', // OPTIONAL Twofish with 192-bit key
|
||||
'twofish256-ctr', // OPTIONAL Twofish with 256-bit key
|
||||
|
||||
'aes128-cbc', // RECOMMENDED AES with a 128-bit key
|
||||
'aes192-cbc', // OPTIONAL AES with a 192-bit key
|
||||
'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key
|
||||
|
||||
'twofish128-cbc', // OPTIONAL Twofish with a 128-bit key
|
||||
'twofish192-cbc', // OPTIONAL Twofish with a 192-bit key
|
||||
'twofish256-cbc',
|
||||
'twofish-cbc', // OPTIONAL alias for "twofish256-cbc"
|
||||
// (this is being retained for historical reasons)
|
||||
|
||||
'blowfish-ctr', // OPTIONAL Blowfish in SDCTR mode
|
||||
|
||||
'blowfish-cbc', // OPTIONAL Blowfish in CBC mode
|
||||
|
||||
'3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode
|
||||
|
||||
'3des-cbc', // REQUIRED three-key 3DES in CBC mode
|
||||
//'none' // OPTIONAL no encryption; NOT RECOMMENDED
|
||||
);
|
||||
|
||||
if (extension_loaded('openssl') && !extension_loaded('mcrypt')) {
|
||||
// OpenSSL does not support arcfour256 in any capacity and arcfour128 / arcfour support is limited to
|
||||
// instances that do not use continuous buffers
|
||||
$encryption_algorithms = array_diff(
|
||||
$encryption_algorithms,
|
||||
array('arcfour256', 'arcfour128', 'arcfour')
|
||||
);
|
||||
}
|
||||
|
||||
if (class_exists('\phpseclib\Crypt\RC4') === false) {
|
||||
$encryption_algorithms = array_diff(
|
||||
$encryption_algorithms,
|
||||
array('arcfour256', 'arcfour128', 'arcfour')
|
||||
);
|
||||
}
|
||||
if (class_exists('\phpseclib\Crypt\Rijndael') === false) {
|
||||
$encryption_algorithms = array_diff(
|
||||
$encryption_algorithms,
|
||||
array('aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc')
|
||||
);
|
||||
}
|
||||
if (class_exists('\phpseclib\Crypt\Twofish') === false) {
|
||||
$encryption_algorithms = array_diff(
|
||||
$encryption_algorithms,
|
||||
array('twofish128-ctr', 'twofish192-ctr', 'twofish256-ctr', 'twofish128-cbc', 'twofish192-cbc', 'twofish256-cbc', 'twofish-cbc')
|
||||
);
|
||||
}
|
||||
if (class_exists('\phpseclib\Crypt\Blowfish') === false) {
|
||||
$encryption_algorithms = array_diff(
|
||||
$encryption_algorithms,
|
||||
array('blowfish-ctr', 'blowfish-cbc')
|
||||
);
|
||||
}
|
||||
if (class_exists('\phpseclib\Crypt\TripleDES') === false) {
|
||||
$encryption_algorithms = array_diff(
|
||||
$encryption_algorithms,
|
||||
array('3des-ctr', '3des-cbc')
|
||||
);
|
||||
}
|
||||
$encryption_algorithms = array_values($encryption_algorithms);
|
||||
|
||||
$mac_algorithms = array(
|
||||
// from <http://www.ietf.org/rfc/rfc6668.txt>:
|
||||
'hmac-sha2-256',// RECOMMENDED HMAC-SHA256 (digest length = key length = 32)
|
||||
|
||||
'hmac-sha1-96', // RECOMMENDED first 96 bits of HMAC-SHA1 (digest length = 12, key length = 20)
|
||||
'hmac-sha1', // REQUIRED HMAC-SHA1 (digest length = key length = 20)
|
||||
'hmac-md5-96', // OPTIONAL first 96 bits of HMAC-MD5 (digest length = 12, key length = 16)
|
||||
'hmac-md5', // OPTIONAL HMAC-MD5 (digest length = key length = 16)
|
||||
//'none' // OPTIONAL no MAC; NOT RECOMMENDED
|
||||
);
|
||||
|
||||
$compression_algorithms = array(
|
||||
'none' // REQUIRED no compression
|
||||
//'zlib' // OPTIONAL ZLIB (LZ77) compression
|
||||
);
|
||||
$kex_algorithms = isset($preferred['kex']) ?
|
||||
$preferred['kex'] :
|
||||
$this->getSupportedKEXAlgorithms();
|
||||
$server_host_key_algorithms = isset($preferred['hostkey']) ?
|
||||
$preferred['hostkey'] :
|
||||
$this->getSupportedHostKeyAlgorithms();
|
||||
$s2c_encryption_algorithms = isset($preferred['server_to_client']['crypt']) ?
|
||||
$preferred['server_to_client']['crypt'] :
|
||||
$this->getSupportedEncryptionAlgorithms();
|
||||
$c2s_encryption_algorithms = isset($preferred['client_to_server']['crypt']) ?
|
||||
$preferred['client_to_server']['crypt'] :
|
||||
$this->getSupportedEncryptionAlgorithms();
|
||||
$s2c_mac_algorithms = isset($preferred['server_to_client']['mac']) ?
|
||||
$preferred['server_to_client']['mac'] :
|
||||
$this->getSupportedMACAlgorithms();
|
||||
$c2s_mac_algorithms = isset($preferred['client_to_server']['mac']) ?
|
||||
$preferred['client_to_server']['mac'] :
|
||||
$this->getSupportedMACAlgorithms();
|
||||
$s2c_compression_algorithms = isset($preferred['server_to_client']['comp']) ?
|
||||
$preferred['server_to_client']['comp'] :
|
||||
$this->getSupportedCompressionAlgorithms();
|
||||
$c2s_compression_algorithms = isset($preferred['client_to_server']['comp']) ?
|
||||
$preferred['client_to_server']['comp'] :
|
||||
$this->getSupportedCompressionAlgorithms();
|
||||
|
||||
// some SSH servers have buggy implementations of some of the above algorithms
|
||||
switch (true) {
|
||||
case $this->server_identifier == 'SSH-2.0-SSHD':
|
||||
case substr($this->server_identifier, 0, 13) == 'SSH-2.0-DLINK':
|
||||
$mac_algorithms = array_values(array_diff(
|
||||
$mac_algorithms,
|
||||
array('hmac-sha1-96', 'hmac-md5-96')
|
||||
));
|
||||
if (!isset($preferred['server_to_client']['mac'])) {
|
||||
$s2c_mac_algorithms = array_values(array_diff(
|
||||
$s2c_mac_algorithms,
|
||||
array('hmac-sha1-96', 'hmac-md5-96')
|
||||
));
|
||||
}
|
||||
if (!isset($preferred['client_to_server']['mac'])) {
|
||||
$c2s_mac_algorithms = array_values(array_diff(
|
||||
$c2s_mac_algorithms,
|
||||
array('hmac-sha1-96', 'hmac-md5-96')
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
$str_kex_algorithms = implode(',', $kex_algorithms);
|
||||
$str_server_host_key_algorithms = implode(',', $server_host_key_algorithms);
|
||||
$encryption_algorithms_server_to_client = $encryption_algorithms_client_to_server = implode(',', $encryption_algorithms);
|
||||
$mac_algorithms_server_to_client = $mac_algorithms_client_to_server = implode(',', $mac_algorithms);
|
||||
$compression_algorithms_server_to_client = $compression_algorithms_client_to_server = implode(',', $compression_algorithms);
|
||||
$encryption_algorithms_server_to_client = implode(',', $s2c_encryption_algorithms);
|
||||
$encryption_algorithms_client_to_server = implode(',', $c2s_encryption_algorithms);
|
||||
$mac_algorithms_server_to_client = implode(',', $s2c_mac_algorithms);
|
||||
$mac_algorithms_client_to_server = implode(',', $c2s_mac_algorithms);
|
||||
$compression_algorithms_server_to_client = implode(',', $s2c_compression_algorithms);
|
||||
$compression_algorithms_client_to_server = implode(',', $c2s_compression_algorithms);
|
||||
|
||||
$client_cookie = Random::string(16);
|
||||
|
||||
@ -1572,14 +1500,14 @@ class SSH2
|
||||
// we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange
|
||||
// we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the
|
||||
// diffie-hellman key exchange as fast as possible
|
||||
$decrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_server_to_client);
|
||||
$decrypt = $this->_array_intersect_first($s2c_encryption_algorithms, $this->encryption_algorithms_server_to_client);
|
||||
$decryptKeyLength = $this->_encryption_algorithm_to_key_size($decrypt);
|
||||
if ($decryptKeyLength === null) {
|
||||
user_error('No compatible server to client encryption algorithms found');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
}
|
||||
|
||||
$encrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_client_to_server);
|
||||
$encrypt = $this->_array_intersect_first($c2s_encryption_algorithms, $this->encryption_algorithms_client_to_server);
|
||||
$encryptKeyLength = $this->_encryption_algorithm_to_key_size($encrypt);
|
||||
if ($encryptKeyLength === null) {
|
||||
user_error('No compatible client to server encryption algorithms found');
|
||||
@ -1587,7 +1515,7 @@ class SSH2
|
||||
}
|
||||
|
||||
// through diffie-hellman key exchange a symmetric key is obtained
|
||||
$kex_algorithm = $this->_array_intersect_first($kex_algorithms, $this->kex_algorithms);
|
||||
$this->kex_algorithm = $kex_algorithm = $this->_array_intersect_first($kex_algorithms, $this->kex_algorithms);
|
||||
if ($kex_algorithm === false) {
|
||||
user_error('No compatible key exchange algorithms found');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
@ -1598,7 +1526,7 @@ class SSH2
|
||||
|
||||
if ($kex_algorithm === 'curve25519-sha256@libssh.org') {
|
||||
$x = Random::string(32);
|
||||
$eBytes = \Sodium\crypto_box_publickey_from_secretkey($x);
|
||||
$eBytes = sodium_crypto_box_publickey_from_secretkey($x);
|
||||
$clientKexInitMessage = NET_SSH2_MSG_KEX_ECDH_INIT;
|
||||
$serverKexReplyMessage = NET_SSH2_MSG_KEX_ECDH_REPLY;
|
||||
$kexHash = new Hash('sha256');
|
||||
@ -1770,8 +1698,8 @@ class SSH2
|
||||
user_error('Received curve25519 public key of invalid length.');
|
||||
return false;
|
||||
}
|
||||
$key = new BigInteger(\Sodium\crypto_scalarmult($x, $fBytes), 256);
|
||||
\Sodium\memzero($x);
|
||||
$key = new BigInteger(sodium_crypto_scalarmult($x, $fBytes), 256);
|
||||
sodium_memzero($x);
|
||||
} else {
|
||||
$f = new BigInteger($fBytes, -256);
|
||||
$key = $f->modPow($x, $prime);
|
||||
@ -1859,8 +1787,6 @@ class SSH2
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->decrypt_algorithm = $decrypt;
|
||||
|
||||
$keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
|
||||
|
||||
$this->encrypt = $this->_encryption_algorithm_to_crypt_instance($encrypt);
|
||||
@ -1874,6 +1800,10 @@ class SSH2
|
||||
$this->encrypt->enableContinuousBuffer();
|
||||
$this->encrypt->disablePadding();
|
||||
|
||||
if ($this->encrypt->getBlockLength()) {
|
||||
$this->encrypt_block_size = $this->encrypt->getBlockLength() >> 3;
|
||||
}
|
||||
|
||||
$iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id);
|
||||
while ($this->encrypt_block_size > strlen($iv)) {
|
||||
$iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv);
|
||||
@ -1885,6 +1815,8 @@ class SSH2
|
||||
$key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
|
||||
}
|
||||
$this->encrypt->setKey(substr($key, 0, $encryptKeyLength));
|
||||
|
||||
$this->encrypt->name = $decrypt;
|
||||
}
|
||||
|
||||
$this->decrypt = $this->_encryption_algorithm_to_crypt_instance($decrypt);
|
||||
@ -1898,6 +1830,10 @@ class SSH2
|
||||
$this->decrypt->enableContinuousBuffer();
|
||||
$this->decrypt->disablePadding();
|
||||
|
||||
if ($this->decrypt->getBlockLength()) {
|
||||
$this->decrypt_block_size = $this->decrypt->getBlockLength() >> 3;
|
||||
}
|
||||
|
||||
$iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id);
|
||||
while ($this->decrypt_block_size > strlen($iv)) {
|
||||
$iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv);
|
||||
@ -1909,6 +1845,8 @@ class SSH2
|
||||
$key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
|
||||
}
|
||||
$this->decrypt->setKey(substr($key, 0, $decryptKeyLength));
|
||||
|
||||
$this->decrypt->name = $decrypt;
|
||||
}
|
||||
|
||||
/* The "arcfour128" algorithm is the RC4 cipher, as described in
|
||||
@ -1925,7 +1863,7 @@ class SSH2
|
||||
$this->decrypt->decrypt(str_repeat("\0", 1536));
|
||||
}
|
||||
|
||||
$mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_client_to_server);
|
||||
$mac_algorithm = $this->_array_intersect_first($c2s_mac_algorithms, $this->mac_algorithms_client_to_server);
|
||||
if ($mac_algorithm === false) {
|
||||
user_error('No compatible client to server message authentication algorithms found');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
@ -1953,8 +1891,9 @@ class SSH2
|
||||
$this->hmac_create = new Hash('md5-96');
|
||||
$createKeyLength = 16;
|
||||
}
|
||||
$this->hmac_create->name = $mac_algorithm;
|
||||
|
||||
$mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_server_to_client);
|
||||
$mac_algorithm = $this->_array_intersect_first($s2c_mac_algorithms, $this->mac_algorithms_server_to_client);
|
||||
if ($mac_algorithm === false) {
|
||||
user_error('No compatible server to client message authentication algorithms found');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
@ -1988,6 +1927,7 @@ class SSH2
|
||||
$checkKeyLength = 16;
|
||||
$this->hmac_size = 12;
|
||||
}
|
||||
$this->hmac_check->name = $mac_algorithm;
|
||||
|
||||
$key = $kexHash->hash($keyBytes . $this->exchange_hash . 'E' . $this->session_id);
|
||||
while ($createKeyLength > strlen($key)) {
|
||||
@ -2001,19 +1941,19 @@ class SSH2
|
||||
}
|
||||
$this->hmac_check->setKey(substr($key, 0, $checkKeyLength));
|
||||
|
||||
$compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_server_to_client);
|
||||
if ($compression_algorithm === false) {
|
||||
user_error('No compatible server to client compression algorithms found');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
}
|
||||
$this->decompress = $compression_algorithm == 'zlib';
|
||||
|
||||
$compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_client_to_server);
|
||||
$compression_algorithm = $this->_array_intersect_first($c2s_compression_algorithms, $this->compression_algorithms_client_to_server);
|
||||
if ($compression_algorithm === false) {
|
||||
user_error('No compatible client to server compression algorithms found');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
}
|
||||
$this->compress = $compression_algorithm == 'zlib';
|
||||
//$this->decompress = $compression_algorithm == 'zlib';
|
||||
|
||||
$compression_algorithm = $this->_array_intersect_first($s2c_compression_algorithms, $this->compression_algorithms_client_to_server);
|
||||
if ($compression_algorithm === false) {
|
||||
user_error('No compatible server to client compression algorithms found');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
}
|
||||
//$this->compress = $compression_algorithm == 'zlib';
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -2105,7 +2045,7 @@ class SSH2
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Tests whether or not proposed algorithm has a potential for issues
|
||||
*
|
||||
* @link https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/ssh2-aesctr-openssh.html
|
||||
@ -3266,6 +3206,9 @@ class SSH2
|
||||
function ping()
|
||||
{
|
||||
if (!$this->isAuthenticated()) {
|
||||
if (!empty($this->auth)) {
|
||||
return $this->_reconnect();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3376,7 +3319,7 @@ class SSH2
|
||||
// "implementations SHOULD check that the packet length is reasonable"
|
||||
// PuTTY uses 0x9000 as the actual max packet size and so to shall we
|
||||
if ($remaining_length < -$this->decrypt_block_size || $remaining_length > 0x9000 || $remaining_length % $this->decrypt_block_size != 0) {
|
||||
if (!$this->bad_key_size_fix && $this->_bad_algorithm_candidate($this->decrypt_algorithm) && !($this->bitmap & SSH2::MASK_LOGIN)) {
|
||||
if (!$this->bad_key_size_fix && $this->_bad_algorithm_candidate($this->decrypt->name) && !($this->bitmap & SSH2::MASK_LOGIN)) {
|
||||
$this->bad_key_size_fix = true;
|
||||
$this->_reset_connection(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
return false;
|
||||
@ -4173,10 +4116,14 @@ class SSH2
|
||||
if ($this->bitmap & self::MASK_CONNECTED) {
|
||||
$data = pack('CNNa*Na*', NET_SSH2_MSG_DISCONNECT, $reason, 0, '', 0, '');
|
||||
$this->_send_binary_packet($data);
|
||||
$this->bitmap = 0;
|
||||
fclose($this->fsock);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->bitmap = 0;
|
||||
if (is_resource($this->fsock) && get_resource_type($this->fsock) == 'stream') {
|
||||
fclose($this->fsock);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4497,6 +4444,309 @@ class SSH2
|
||||
return $this->languages_client_to_server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of algorithms the server supports
|
||||
*
|
||||
* @return array
|
||||
* @access public
|
||||
*/
|
||||
public function getServerAlgorithms()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return array(
|
||||
'kex' => $this->kex_algorithms,
|
||||
'hostkey' => $this->server_host_key_algorithms,
|
||||
'client_to_server' => array(
|
||||
'crypt' => $this->encryption_algorithms_client_to_server,
|
||||
'mac' => $this->mac_algorithms_client_to_server,
|
||||
'comp' => $this->compression_algorithms_client_to_server,
|
||||
'lang' => $this->languages_client_to_server
|
||||
),
|
||||
'server_to_client' => array(
|
||||
'crypt' => $this->encryption_algorithms_server_to_client,
|
||||
'mac' => $this->mac_algorithms_server_to_client,
|
||||
'comp' => $this->compression_algorithms_server_to_client,
|
||||
'lang' => $this->languages_server_to_client
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of KEX algorithms that phpseclib supports
|
||||
*
|
||||
* @return array
|
||||
* @access public
|
||||
*/
|
||||
function getSupportedKEXAlgorithms()
|
||||
{
|
||||
$kex_algorithms = array(
|
||||
// Elliptic Curve Diffie-Hellman Key Agreement (ECDH) using
|
||||
// Curve25519. See doc/curve25519-sha256@libssh.org.txt in the
|
||||
// libssh repository for more information.
|
||||
'curve25519-sha256@libssh.org',
|
||||
|
||||
'diffie-hellman-group-exchange-sha256',// RFC 4419
|
||||
'diffie-hellman-group-exchange-sha1', // RFC 4419
|
||||
|
||||
// Diffie-Hellman Key Agreement (DH) using integer modulo prime
|
||||
// groups.
|
||||
'diffie-hellman-group14-sha1', // REQUIRED
|
||||
'diffie-hellman-group1-sha1', // REQUIRED
|
||||
);
|
||||
|
||||
if (!function_exists('sodium_crypto_box_publickey_from_secretkey')) {
|
||||
$kex_algorithms = array_diff(
|
||||
$kex_algorithms,
|
||||
array('curve25519-sha256@libssh.org')
|
||||
);
|
||||
}
|
||||
|
||||
return $kex_algorithms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of host key algorithms that phpseclib supports
|
||||
*
|
||||
* @return array
|
||||
* @access public
|
||||
*/
|
||||
function getSupportedHostKeyAlgorithms()
|
||||
{
|
||||
return array(
|
||||
'rsa-sha2-256', // RFC 8332
|
||||
'rsa-sha2-512', // RFC 8332
|
||||
'ssh-rsa', // RECOMMENDED sign Raw RSA Key
|
||||
'ssh-dss' // REQUIRED sign Raw DSS Key
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of symmetric key algorithms that phpseclib supports
|
||||
*
|
||||
* @return array
|
||||
* @access public
|
||||
*/
|
||||
function getSupportedEncryptionAlgorithms()
|
||||
{
|
||||
$algos = array(
|
||||
// from <http://tools.ietf.org/html/rfc4345#section-4>:
|
||||
'arcfour256',
|
||||
'arcfour128',
|
||||
|
||||
//'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key
|
||||
|
||||
// CTR modes from <http://tools.ietf.org/html/rfc4344#section-4>:
|
||||
'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key
|
||||
'aes192-ctr', // RECOMMENDED AES with 192-bit key
|
||||
'aes256-ctr', // RECOMMENDED AES with 256-bit key
|
||||
|
||||
'twofish128-ctr', // OPTIONAL Twofish in SDCTR mode, with 128-bit key
|
||||
'twofish192-ctr', // OPTIONAL Twofish with 192-bit key
|
||||
'twofish256-ctr', // OPTIONAL Twofish with 256-bit key
|
||||
|
||||
'aes128-cbc', // RECOMMENDED AES with a 128-bit key
|
||||
'aes192-cbc', // OPTIONAL AES with a 192-bit key
|
||||
'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key
|
||||
|
||||
'twofish128-cbc', // OPTIONAL Twofish with a 128-bit key
|
||||
'twofish192-cbc', // OPTIONAL Twofish with a 192-bit key
|
||||
'twofish256-cbc',
|
||||
'twofish-cbc', // OPTIONAL alias for "twofish256-cbc"
|
||||
// (this is being retained for historical reasons)
|
||||
|
||||
'blowfish-ctr', // OPTIONAL Blowfish in SDCTR mode
|
||||
|
||||
'blowfish-cbc', // OPTIONAL Blowfish in CBC mode
|
||||
|
||||
'3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode
|
||||
|
||||
'3des-cbc', // REQUIRED three-key 3DES in CBC mode
|
||||
|
||||
//'none' // OPTIONAL no encryption; NOT RECOMMENDED
|
||||
);
|
||||
|
||||
$engines = array(
|
||||
Base::ENGINE_OPENSSL,
|
||||
Base::ENGINE_MCRYPT,
|
||||
Base::ENGINE_INTERNAL
|
||||
);
|
||||
|
||||
$ciphers = array();
|
||||
foreach ($engines as $engine) {
|
||||
foreach ($algos as $algo) {
|
||||
$obj = $this->_encryption_algorithm_to_crypt_instance($algo);
|
||||
if ($obj instanceof Rijndael) {
|
||||
$obj->setKeyLength(preg_replace('#[^\d]#', '', $algo));
|
||||
}
|
||||
switch ($algo) {
|
||||
case 'arcfour128':
|
||||
case 'arcfour256':
|
||||
if ($engine == Base::ENGINE_INTERNAL) {
|
||||
$algos = array_diff($algos, array($algo));
|
||||
$ciphers[] = $algo;
|
||||
} else {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
if ($obj->isValidEngine($engine)) {
|
||||
$algos = array_diff($algos, array($algo));
|
||||
$ciphers[] = $algo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ciphers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of MAC algorithms that phpseclib supports
|
||||
*
|
||||
* @return array
|
||||
* @access public
|
||||
*/
|
||||
function getSupportedMACAlgorithms()
|
||||
{
|
||||
return array(
|
||||
// from <http://www.ietf.org/rfc/rfc6668.txt>:
|
||||
'hmac-sha2-256',// RECOMMENDED HMAC-SHA256 (digest length = key length = 32)
|
||||
|
||||
'hmac-sha1-96', // RECOMMENDED first 96 bits of HMAC-SHA1 (digest length = 12, key length = 20)
|
||||
'hmac-sha1', // REQUIRED HMAC-SHA1 (digest length = key length = 20)
|
||||
'hmac-md5-96', // OPTIONAL first 96 bits of HMAC-MD5 (digest length = 12, key length = 16)
|
||||
'hmac-md5', // OPTIONAL HMAC-MD5 (digest length = key length = 16)
|
||||
//'none' // OPTIONAL no MAC; NOT RECOMMENDED
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of compression algorithms that phpseclib supports
|
||||
*
|
||||
* @return array
|
||||
* @access public
|
||||
*/
|
||||
function getSupportedCompressionAlgorithms()
|
||||
{
|
||||
return array(
|
||||
'none' // REQUIRED no compression
|
||||
//'zlib' // OPTIONAL ZLIB (LZ77) compression
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of negotiated algorithms
|
||||
*
|
||||
* Uses the same format as https://www.php.net/ssh2-methods-negotiated
|
||||
*
|
||||
* @return array
|
||||
* @access public
|
||||
*/
|
||||
function getAlgorithmsNegotiated()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return array(
|
||||
'kex' => $this->kex_algorithm,
|
||||
'hostkey' => $this->signature_format,
|
||||
'client_to_server' => array(
|
||||
'crypt' => $this->encrypt->name,
|
||||
'mac' => $this->hmac_create->name,
|
||||
'comp' => 'none',
|
||||
),
|
||||
'server_to_client' => array(
|
||||
'crypt' => $this->decrypt->name,
|
||||
'mac' => $this->hmac_check->name,
|
||||
'comp' => 'none',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts an associative array with up to four parameters as described at
|
||||
* <https://www.php.net/manual/en/function.ssh2-connect.php>
|
||||
*
|
||||
* @param array $methods
|
||||
* @access public
|
||||
*/
|
||||
function setPreferredAlgorithms($methods)
|
||||
{
|
||||
$preferred = $methods;
|
||||
|
||||
if (isset($preferred['kex'])) {
|
||||
$preferred['kex'] = array_intersect(
|
||||
$preferred['kex'],
|
||||
$this->getSupportedKEXAlgorithms()
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($preferred['hostkey'])) {
|
||||
$preferred['hostkey'] = array_intersect(
|
||||
$preferred['hostkey'],
|
||||
$this->getSupportedHostKeyAlgorithms()
|
||||
);
|
||||
}
|
||||
|
||||
$keys = array('client_to_server', 'server_to_client');
|
||||
foreach ($keys as $key) {
|
||||
if (isset($preferred[$key])) {
|
||||
$a = &$preferred[$key];
|
||||
if (isset($a['crypt'])) {
|
||||
$a['crypt'] = array_intersect(
|
||||
$a['crypt'],
|
||||
$this->getSupportedEncryptionAlgorithms()
|
||||
);
|
||||
}
|
||||
if (isset($a['comp'])) {
|
||||
$a['comp'] = array_intersect(
|
||||
$a['comp'],
|
||||
$this->getSupportedCompressionAlgorithms()
|
||||
);
|
||||
}
|
||||
if (isset($a['mac'])) {
|
||||
$a['mac'] = array_intersect(
|
||||
$a['mac'],
|
||||
$this->getSupportedMACAlgorithms()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$keys = array(
|
||||
'kex',
|
||||
'hostkey',
|
||||
'client_to_server/crypt',
|
||||
'client_to_server/comp',
|
||||
'client_to_server/mac',
|
||||
'server_to_client/crypt',
|
||||
'server_to_client/comp',
|
||||
'server_to_client/mac',
|
||||
);
|
||||
foreach ($keys as $key) {
|
||||
$p = $preferred;
|
||||
$m = $methods;
|
||||
|
||||
$subkeys = explode('/', $key);
|
||||
foreach ($subkeys as $subkey) {
|
||||
if (!isset($p[$subkey])) {
|
||||
continue 2;
|
||||
}
|
||||
$p = $p[$subkey];
|
||||
$m = $m[$subkey];
|
||||
}
|
||||
|
||||
if (count($p) != count($m)) {
|
||||
$diff = array_diff($m, $p);
|
||||
$msg = count($diff) == 1 ?
|
||||
' is not a supported algorithm' :
|
||||
' are not supported algorithms';
|
||||
user_error(implode(', ', $diff) . $msg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$this->preferred = $preferred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the banner message.
|
||||
*
|
Reference in New Issue
Block a user