Upgrade 1-11.38

This commit is contained in:
xesmyd
2026-03-30 14:10:30 +02:00
parent f2a7e6d1fc
commit ac648ef29d
24665 changed files with 69682 additions and 2205004 deletions
+2 -1
View File
@@ -16,4 +16,5 @@ phpseclib ongoing development is made possible by [Tidelift](https://tidelift.co
- [istiak-tridip](https://github.com/istiak-tridip)
- [Anna Filina](https://github.com/afilina)
- [blakemckeeby](https://github.com/blakemckeeby)
- [ssddanbrown](https://github.com/ssddanbrown)
- [ssddanbrown](https://github.com/ssddanbrown)
- Stefan Beck
+11 -3
View File
@@ -51,7 +51,7 @@ SSH-2, SFTP, X.509, an arbitrary-precision integer arithmetic library, Ed25519 /
* PHP4 compatible
* Composer compatible (PSR-0 autoloading)
* Install using Composer: `composer require phpseclib/phpseclib:~1.0`
* [Download 1.0.23 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.23.zip/download)
* [Download 1.0.25 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.25.zip/download)
## Security contact information
@@ -63,14 +63,22 @@ Need Support?
* [Checkout Questions and Answers on Stack Overflow](http://stackoverflow.com/questions/tagged/phpseclib)
* [Create a Support Ticket on GitHub](https://github.com/phpseclib/phpseclib/issues/new)
* [Browse the Support Forum](http://www.frostjedi.com/phpbb/viewforum.php?f=46) (no longer in use)
## Special Thanks
Special Thanks to our $50+ sponsors!:
<p align="left">
<a target="_blank" href="https://www.sovereign.tech/tech/phpseclib">
<img src="https://phpseclib.com/img/sponsors/sovereign-tech-agency.webp" alt="Sovereign Tech Agency" style="width: 200px">
</a>
</p>
## Additional Thanks
- Allan Simon
- [Anna Filina](https://afilina.com/)
- delovelady
- [ChargeOver](https://chargeover.com/)
- <a href="https://jb.gg/OpenSource"><img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg" height="20px"></a>
## Contributing
+1 -1
View File
@@ -55,7 +55,7 @@
},
"require-dev": {
"phing/phing": "~2.7",
"phpunit/phpunit": "^4.8.35|^5.7|^6.0|^9.4",
"phpunit/phpunit": "^4.8.35|^5.7|^6.0|^8.5|^9.4",
"squizlabs/php_codesniffer": "~2.0"
},
"suggest": {
+6 -1
View File
@@ -512,6 +512,11 @@ abstract class Base
if (!defined('CRYPT_BASE_USE_REG_INTVAL')) {
switch (true) {
// PHP 8.5, per https://www.php.net/manual/en/migration85.incompatible.php, now emits a warning
// "when casting floats (or strings that look like floats) to int if they cannot be represented as one"
case PHP_VERSION_ID >= 80500 && PHP_INT_SIZE == 4:
define('CRYPT_BASE_USE_REG_INTVAL', false);
break;
// PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster
case (PHP_OS & "\xDF\xDF\xDF") === 'WIN':
case !function_exists('php_uname'):
@@ -2069,7 +2074,7 @@ abstract class Base
$length = ord($text[strlen($text) - 1]);
if (!$length || $length > $this->block_size) {
if (!$length | ($length > $this->block_size)) {
return false;
}
+5 -5
View File
@@ -401,11 +401,11 @@ class Blowfish extends Base
{
parent::__construct($mode);
$this->sbox0 = array_map('intval', $this->sbox0);
$this->sbox1 = array_map('intval', $this->sbox1);
$this->sbox2 = array_map('intval', $this->sbox2);
$this->sbox3 = array_map('intval', $this->sbox3);
$this->parray = array_map('intval', $this->parray);
$this->sbox0 = array_map(array($this, 'safe_intval'), $this->sbox0);
$this->sbox1 = array_map(array($this, 'safe_intval'), $this->sbox1);
$this->sbox2 = array_map(array($this, 'safe_intval'), $this->sbox2);
$this->sbox3 = array_map(array($this, 'safe_intval'), $this->sbox3);
$this->parray = array_map(array($this, 'safe_intval'), $this->parray);
}
/**
+26 -18
View File
@@ -147,6 +147,14 @@ class DES extends Base
*/
var $keys;
/**
* Key Cache "key"
*
* @see self::setupKey()
* @var array
*/
var $kl;
/**
* Shuffle table.
*
@@ -681,14 +689,14 @@ class DES extends Base
{
static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
if (!$sbox1) {
$sbox1 = array_map("intval", $this->sbox1);
$sbox2 = array_map("intval", $this->sbox2);
$sbox3 = array_map("intval", $this->sbox3);
$sbox4 = array_map("intval", $this->sbox4);
$sbox5 = array_map("intval", $this->sbox5);
$sbox6 = array_map("intval", $this->sbox6);
$sbox7 = array_map("intval", $this->sbox7);
$sbox8 = array_map("intval", $this->sbox8);
$sbox1 = array_map(array($this, 'safe_intval'), $this->sbox1);
$sbox2 = array_map(array($this, 'safe_intval'), $this->sbox2);
$sbox3 = array_map(array($this, 'safe_intval'), $this->sbox3);
$sbox4 = array_map(array($this, 'safe_intval'), $this->sbox4);
$sbox5 = array_map(array($this, 'safe_intval'), $this->sbox5);
$sbox6 = array_map(array($this, 'safe_intval'), $this->sbox6);
$sbox7 = array_map(array($this, 'safe_intval'), $this->sbox7);
$sbox8 = array_map(array($this, 'safe_intval'), $this->sbox8);
/* Merge $shuffle with $[inv]ipmap */
for ($i = 0; $i < 256; ++$i) {
$shuffleip[] = $this->shuffle[$this->ipmap[$i]];
@@ -1252,9 +1260,9 @@ class DES extends Base
$pc2mapd3[($d >> 8) & 0xFF] | $pc2mapd4[ $d & 0xFF];
// Reorder: odd bytes/even bytes. Push the result in key schedule.
$val1 = ( $cp & intval(0xFF000000)) | (($cp << 8) & 0x00FF0000) |
$val1 = ( $cp & $this->safe_intval(0xFF000000)) | (($cp << 8) & 0x00FF0000) |
(($dp >> 16) & 0x0000FF00) | (($dp >> 8) & 0x000000FF);
$val2 = (($cp << 8) & intval(0xFF000000)) | (($cp << 16) & 0x00FF0000) |
$val2 = (($cp << 8) & $this->safe_intval(0xFF000000)) | (($cp << 16) & 0x00FF0000) |
(($dp >> 8) & 0x0000FF00) | ( $dp & 0x000000FF);
$keys[$des_round][self::ENCRYPT][ ] = $val1;
$keys[$des_round][self::DECRYPT][$ki - 1] = $val1;
@@ -1324,14 +1332,14 @@ class DES extends Base
// Init code for both, encrypt and decrypt.
$init_crypt = 'static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
if (!$sbox1) {
$sbox1 = array_map("intval", $self->sbox1);
$sbox2 = array_map("intval", $self->sbox2);
$sbox3 = array_map("intval", $self->sbox3);
$sbox4 = array_map("intval", $self->sbox4);
$sbox5 = array_map("intval", $self->sbox5);
$sbox6 = array_map("intval", $self->sbox6);
$sbox7 = array_map("intval", $self->sbox7);
$sbox8 = array_map("intval", $self->sbox8);'
$sbox1 = array_map(array($self, "safe_intval"), $self->sbox1);
$sbox2 = array_map(array($self, "safe_intval"), $self->sbox2);
$sbox3 = array_map(array($self, "safe_intval"), $self->sbox3);
$sbox4 = array_map(array($self, "safe_intval"), $self->sbox4);
$sbox5 = array_map(array($self, "safe_intval"), $self->sbox5);
$sbox6 = array_map(array($self, "safe_intval"), $self->sbox6);
$sbox7 = array_map(array($self, "safe_intval"), $self->sbox7);
$sbox8 = array_map(array($self, "safe_intval"), $self->sbox8);'
/* Merge $shuffle with $[inv]ipmap */ . '
for ($i = 0; $i < 256; ++$i) {
$shuffleip[] = $self->shuffle[$self->ipmap[$i]];
+10 -6
View File
@@ -1345,7 +1345,7 @@ class RSA
return $components;
case self::PUBLIC_FORMAT_OPENSSH:
$parts = explode(' ', $key, 3);
$parts = preg_split("#[\t ]+#", $key);
$key = isset($parts[1]) ? base64_decode($parts[1]) : false;
if ($key === false) {
@@ -1406,12 +1406,16 @@ class RSA
}
// add <xml></xml> to account for "dangling" tags like <BitStrength>...</BitStrength> that are sometimes added
if (!xml_parse($xml, '<xml>' . $key . '</xml>')) {
xml_parser_free($xml);
if (PHP_VERSION_ID < 80500 && function_exists('xml_parser_free')) {
xml_parser_free($xml);
}
unset($xml);
return false;
}
xml_parser_free($xml);
if (PHP_VERSION_ID < 80500 && function_exists('xml_parser_free')) {
xml_parser_free($xml);
}
unset($xml);
return isset($this->components['modulus']) && isset($this->components['publicExponent']) ? $this->components : false;
@@ -2829,7 +2833,7 @@ class RSA
$db = $ps . chr(1) . $salt;
$dbMask = $this->_mgf1($h, $emLen - $this->hLen - 1);
$maskedDB = $db ^ $dbMask;
$maskedDB[0] = ~chr(0xFF << ($emBits & 7)) & $maskedDB[0];
$maskedDB[0] = ~chr(256 - (1 << ($emBits & 7))) & $maskedDB[0];
$em = $maskedDB . $h . chr(0xBC);
return $em;
@@ -2865,13 +2869,13 @@ class RSA
$maskedDB = substr($em, 0, -$this->hLen - 1);
$h = substr($em, -$this->hLen - 1, $this->hLen);
$temp = chr(0xFF << ($emBits & 7));
$temp = chr(256 - (1 << ($emBits & 7)));
if ((~$maskedDB[0] & $temp) != $temp) {
return false;
}
$dbMask = $this->_mgf1($h, $emLen - $this->hLen - 1);
$db = $maskedDB ^ $dbMask;
$db[0] = ~chr(0xFF << ($emBits & 7)) & $db[0];
$db[0] = ~chr(256 - (1 << ($emBits & 7))) & $db[0];
$temp = $emLen - $this->hLen - $sLen - 2;
if (substr($db, 0, $temp) != str_repeat(chr(0), $temp) || ord($db[$temp]) != 1) {
return false;
+26 -16
View File
@@ -340,7 +340,7 @@ class Rijndael extends Base
$k = $c[2];
$l = $c[3];
while ($i < $Nb) {
$temp[$i] = ($state[$i] & intval(0xFF000000)) ^
$temp[$i] = ($state[$i] & (PHP_INT_SIZE === 8 ? 0xFF000000 : -16777216)) ^
($state[$j] & 0x00FF0000) ^
($state[$k] & 0x0000FF00) ^
($state[$l] & 0x000000FF) ^
@@ -426,7 +426,7 @@ class Rijndael extends Base
$l = $Nb - $c[3];
while ($i < $Nb) {
$word = ($state[$i] & intval(0xFF000000)) |
$word = ($state[$i] & (PHP_INT_SIZE === 8 ? 0xFF000000 : -16777216)) |
($state[$j] & 0x00FF0000) |
($state[$k] & 0x0000FF00) |
($state[$l] & 0x000000FF);
@@ -476,7 +476,7 @@ class Rijndael extends Base
0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000,
0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
);
$rcon = array_map('intval', $rcon);
$rcon = array_map(array($this, 'safe_intval'), $rcon);
}
if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) {
@@ -516,7 +516,9 @@ class Rijndael extends Base
// on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine,
// 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and'
// with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
$temp = (($temp << 8) & intval(0xFFFFFF00)) | (($temp >> 24) & 0x000000FF); // rotWord
$temp = PHP_INT_SIZE == 8 ? // rotWord
(($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF) :
($temp << 8) | (($temp >> 24) & 0x000000FF);
$temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk];
} elseif ($this->Nk > 6 && $i % $this->Nk == 4) {
$temp = $this->_subWord($temp);
@@ -608,7 +610,7 @@ class Rijndael extends Base
// according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
// precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
// those are the names we'll use.
$t3 = array_map('intval', array(
$t3 = array_map(array($this, 'safe_intval'), array(
// with array_map('intval', ...) we ensure we have only int's and not
// some slower floats converted by php automatically on high values
0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
@@ -646,9 +648,9 @@ class Rijndael extends Base
));
foreach ($t3 as $t3i) {
$t0[] = (($t3i << 24) & intval(0xFF000000)) | (($t3i >> 8) & 0x00FFFFFF);
$t1[] = (($t3i << 16) & intval(0xFFFF0000)) | (($t3i >> 16) & 0x0000FFFF);
$t2[] = (($t3i << 8) & intval(0xFFFFFF00)) | (($t3i >> 24) & 0x000000FF);
$t0[] = (($t3i << 24) & $this->safe_intval(0xFF000000)) | (($t3i >> 8) & 0x00FFFFFF);
$t1[] = (($t3i << 16) & $this->safe_intval(0xFFFF0000)) | (($t3i >> 16) & 0x0000FFFF);
$t2[] = (($t3i << 8) & $this->safe_intval(0xFFFFFF00)) | (($t3i >> 24) & 0x000000FF);
}
$tables = array(
@@ -694,7 +696,7 @@ class Rijndael extends Base
{
static $tables;
if (empty($tables)) {
$dt3 = array_map('intval', array(
$dt3 = array_map(array($this, 'safe_intval'), array(
0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
@@ -729,11 +731,19 @@ class Rijndael extends Base
0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
));
foreach ($dt3 as $dt3i) {
$dt0[] = (($dt3i << 24) & intval(0xFF000000)) | (($dt3i >> 8) & 0x00FFFFFF);
$dt1[] = (($dt3i << 16) & intval(0xFFFF0000)) | (($dt3i >> 16) & 0x0000FFFF);
$dt2[] = (($dt3i << 8) & intval(0xFFFFFF00)) | (($dt3i >> 24) & 0x000000FF);
};
if (PHP_INT_SIZE === 8) {
foreach ($dt3 as $dt3i) {
$dt0[] = (($dt3i << 24) & 0xFF000000) | (($dt3i >> 8) & 0x00FFFFFF);
$dt1[] = (($dt3i << 16) & 0xFFFF0000) | (($dt3i >> 16) & 0x0000FFFF);
$dt2[] = (($dt3i << 8) & 0xFFFFFF00) | (($dt3i >> 24) & 0x000000FF);
};
} else {
foreach ($dt3 as $dt3i) {
$dt0[] = ($dt3i << 24) | (($dt3i >> 8) & 0x00FFFFFF);
$dt1[] = ($dt3i << 16) | (($dt3i >> 16) & 0x0000FFFF);
$dt2[] = ($dt3i << 8) | (($dt3i >> 24) & 0x000000FF);
};
}
$tables = array(
// The Precomputed inverse mixColumns tables dt0 - dt3
@@ -860,7 +870,7 @@ class Rijndael extends Base
$encrypt_block .= '$in = pack("N*"'."\n";
for ($i = 0; $i < $Nb; ++$i) {
$encrypt_block.= ',
($'.$e.$i .' & '.((int)0xFF000000).') ^
($'.$e.$i .' & '.(PHP_INT_SIZE === 8 ? 0xFF000000 : -16777216).') ^
($'.$e.(($i + $c[1]) % $Nb).' & 0x00FF0000 ) ^
($'.$e.(($i + $c[2]) % $Nb).' & 0x0000FF00 ) ^
($'.$e.(($i + $c[3]) % $Nb).' & 0x000000FF ) ^
@@ -916,7 +926,7 @@ class Rijndael extends Base
$decrypt_block .= '$in = pack("N*"'."\n";
for ($i = 0; $i < $Nb; ++$i) {
$decrypt_block.= ',
($'.$e.$i. ' & '.((int)0xFF000000).') ^
($'.$e.$i. ' & '.(PHP_INT_SIZE === 8 ? 0xFF000000 : -16777216).') ^
($'.$e.(($Nb + $i - $c[1]) % $Nb).' & 0x00FF0000 ) ^
($'.$e.(($Nb + $i - $c[2]) % $Nb).' & 0x0000FF00 ) ^
($'.$e.(($Nb + $i - $c[3]) % $Nb).' & 0x000000FF ) ^
+6 -6
View File
@@ -396,12 +396,12 @@ class Twofish extends Base
{
parent::__construct($mode);
$this->m0 = array_map('intval', $this->m0);
$this->m1 = array_map('intval', $this->m1);
$this->m2 = array_map('intval', $this->m2);
$this->m3 = array_map('intval', $this->m3);
$this->q0 = array_map('intval', $this->q0);
$this->q1 = array_map('intval', $this->q1);
$this->m0 = array_map(array($this, 'safe_intval'), $this->m0);
$this->m1 = array_map(array($this, 'safe_intval'), $this->m1);
$this->m2 = array_map(array($this, 'safe_intval'), $this->m2);
$this->m3 = array_map(array($this, 'safe_intval'), $this->m3);
$this->q0 = array_map(array($this, 'safe_intval'), $this->q0);
$this->q1 = array_map(array($this, 'safe_intval'), $this->q1);
}
/**
+5 -1
View File
@@ -817,7 +817,11 @@ class ASN1
$temp = new BigInteger($decoded['content'], -256);
}
if (isset($mapping['mapping'])) {
$temp = (int) $temp->toString();
$temp = $temp->toString();
if (strlen($temp) > 1) {
return false;
}
$temp = (int) $temp;
return isset($mapping['mapping'][$temp]) ?
$mapping['mapping'][$temp] :
false;
+4
View File
@@ -1321,6 +1321,7 @@ class X509
'2.5.4.45' => 'id-at-uniqueIdentifier',
'2.5.4.72' => 'id-at-role',
'2.5.4.16' => 'id-at-postalAddress',
'2.5.4.97' => 'id-at-organizationIdentifier',
'1.3.6.1.4.1.311.60.2.1.3' => 'jurisdictionOfIncorporationCountryName',
'1.3.6.1.4.1.311.60.2.1.2' => 'jurisdictionOfIncorporationStateOrProvinceName',
'1.3.6.1.4.1.311.60.2.1.1' => 'jurisdictionLocalityName',
@@ -2653,6 +2654,9 @@ class X509
case 'organizationalunitname':
case 'ou':
return 'id-at-organizationalUnitName';
case 'id-at-organizationidentifier':
case 'organizationIdentifier':
return 'id-at-organizationIdentifier';
case 'id-at-pseudonym':
case 'pseudonym':
return 'id-at-pseudonym';
+42 -4
View File
@@ -255,7 +255,7 @@ class BigInteger
// https://github.com/php/php-src/commit/e0a0e216a909dc4ee4ea7c113a5f41d49525f02e broke GMP
// https://github.com/php/php-src/commit/424ba0f2ff9677d16b4e339e90885bd4bc49fcf1 fixed it
// see https://github.com/php/php-src/issues/16870 for more info
if (version_compare(PHP_VERSION, '8.2.26', '<')) {
if (version_compare(PHP_VERSION, '8.2.25', '<=')) {
$gmpOK = true;
} else {
$gmpOK = !in_array(PHP_VERSION_ID, array(80226, 80314, 80400, 80401));
@@ -592,7 +592,7 @@ class BigInteger
while (bccomp($current, '0', 0) > 0) {
$temp = bcmod($current, '16777216');
$value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value;
$value = chr($temp >> 16) . chr(($temp >> 8) & 0xFF) . chr($temp & 0xFF) . $value;
$current = bcdiv($current, '16777216', 0);
}
@@ -855,6 +855,44 @@ class BigInteger
}
}
/**
* __serialize() magic method
*
* __sleep / __wakeup were depreciated in PHP 8.5
* Will be called, automatically, when serialize() is called on a Math_BigInteger object.
*
* @see self::__unserialize()
* @access public
*/
function __serialize()
{
$result = array('hex' => $this->toHex(true));
if ($this->precision > 0) {
$result['precision'] = $this->precision;
}
return $result;
}
/**
* __unserialize() magic method
*
* __sleep / __wakeup were depreciated in PHP 8.5
* Will be called, automatically, when unserialize() is called on a Math_BigInteger object.
*
* @see self::__serialize()
* @access public
*/
function __unserialize($data)
{
$temp = new BigInteger($data['hex'], -16);
$this->value = $temp->value;
$this->is_negative = $temp->is_negative;
if (isset($data['precision']) && $data['precision'] > 0) {
// recalculate $this->bitmask
$this->setPrecision($data['precision']);
}
}
/**
* __debugInfo() magic method
*
@@ -3713,8 +3751,8 @@ class BigInteger
$carry = 0;
for ($i = strlen($x) - 1; $i >= 0; --$i) {
$temp = ord($x[$i]) << $shift | $carry;
$x[$i] = chr($temp);
$temp = (ord($x[$i]) << $shift) | $carry;
$x[$i] = chr($temp & 0xFF);
$carry = $temp >> 8;
}
$carry = ($carry != 0) ? chr($carry) : '';
+62 -2
View File
@@ -94,6 +94,15 @@ class SCP
*/
var $mode;
/**
* Error information
*
* @see self::getSCPErrors()
* @see self::getLastSCPError()
* @var array
*/
var $scp_errors = array();
/**
* Default Constructor.
*
@@ -155,6 +164,7 @@ class SCP
$temp = $this->_receive();
if ($temp !== chr(0)) {
$this->_close();
return false;
}
@@ -168,12 +178,14 @@ class SCP
$size = strlen($data);
} else {
if (!is_file($data)) {
$this->_close();
user_error("$data is not a valid file", E_USER_NOTICE);
return false;
}
$fp = @fopen($data, 'rb');
if (!$fp) {
$this->_close();
return false;
}
$size = filesize($data);
@@ -183,6 +195,7 @@ class SCP
$temp = $this->_receive();
if ($temp !== chr(0)) {
$this->_close();
return false;
}
@@ -229,7 +242,18 @@ class SCP
$this->_send("\0");
if (!preg_match('#(?<perms>[^ ]+) (?<size>\d+) (?<name>.+)#', rtrim($this->_receive()), $info)) {
$info = $this->_receive();
// per https://goteleport.com/blog/scp-familiar-simple-insecure-slow/ non-zero responses mean there are errors
if ($info[0] === chr(1) || $info[0] == chr(2)) {
$type = $info[0] === chr(1) ? 'warning' : 'error';
$this->scp_errors[] = "$type: " . substr($info, 1);
$this->_close();
return false;
}
if (!preg_match('#(?<perms>[^ ]+) (?<size>\d+) (?<name>.+)#', rtrim($info), $info)) {
$this->_close();
return false;
}
@@ -240,6 +264,7 @@ class SCP
if ($local_file !== false) {
$fp = @fopen($local_file, 'wb');
if (!$fp) {
$this->_close();
return false;
}
}
@@ -250,12 +275,27 @@ class SCP
// Terminate the loop in case the server repeatedly sends an empty response
if ($data === false) {
$this->_close();
user_error('No data received from server', E_USER_NOTICE);
return false;
}
// SCP usually seems to split stuff out into 16k chunks
$size+= strlen($data);
$length = strlen($data);
$size+= $length;
$end = $size > $info['size'];
if ($end) {
$diff = $size - $info['size'];
$offset = $length - $diff;
if ($data[$offset] === chr(0)) {
$data = substr($data, 0, -$diff);
} else {
$type = $data[$offset] === chr(1) ? 'warning' : 'error';
$this->scp_errors[] = "$type: " . substr($data, 1);
$this->_close();
return false;
}
}
if ($local_file === false) {
$content.= $data;
@@ -346,4 +386,24 @@ class SCP
$this->ssh->disconnect();
}
}
/**
* Returns all errors on the SCP layer
*
* @return array
*/
function getSCPErrors()
{
return $this->scp_errors;
}
/**
* Returns the last error on the SCP layer
*
* @return string
*/
function getLastSCPError()
{
return count($this->scp_errors) ? $this->scp_errors[count($this->scp_errors) - 1] : '';
}
}
+7
View File
@@ -915,6 +915,8 @@ class SFTP extends SSH2
*/
function _realpath($path)
{
$path = (string) $path;
if (!$this->canonicalize_paths) {
if ($this->pwd === true) {
return '.';
@@ -1008,6 +1010,8 @@ class SFTP extends SSH2
return false;
}
$dir = (string) $dir;
// assume current dir if $dir is empty
if ($dir === '') {
$dir = './';
@@ -1017,6 +1021,9 @@ class SFTP extends SSH2
}
$dir = $this->_realpath($dir);
if ($dir === false) {
return false;
}
// confirm that $dir is, in fact, a valid directory
if ($this->use_stat_cache && is_array($this->_query_stat_cache($dir))) {
+26 -14
View File
@@ -1441,7 +1441,8 @@ class SSH2
$this->_append_log('->', $this->identifier . "\r\n");
}
$this->server_identifier = trim($data, "\r\n");
$data = explode("\r\n", trim($data, "\r\n"));
$this->server_identifier = $data[count($data) - 1];
if (strlen($extra)) {
$this->errors[] = $data;
@@ -1925,16 +1926,21 @@ class SSH2
$this->_updateLogHistory('UNKNOWN (32)', 'NET_SSH2_MSG_KEXDH_GEX_INIT');
}
$response = $this->_get_binary_packet();
if ($response === false) {
$this->bitmap = 0;
user_error('Connection closed by server');
return false;
while (true) {
$response = $this->_get_binary_packet();
if ($response === false) {
$this->bitmap = 0;
user_error('Connection closed by server');
return false;
}
if (!strlen($response)) {
return false;
}
extract(unpack('Ctype', $this->_string_shift($response, 1)));
if ($type != NET_SSH2_MSG_IGNORE) {
break;
}
}
if (!strlen($response)) {
return false;
}
extract(unpack('Ctype', $this->_string_shift($response, 1)));
if ($type != constant($serverKexReplyMessage)) {
user_error("Expected $serverKexReplyMessage");
@@ -3977,8 +3983,9 @@ class SSH2
}
extract(unpack('Nlength', $this->_string_shift($payload, 4)));
$this->errors[] = 'SSH_MSG_GLOBAL_REQUEST: ' . $this->_string_shift($payload, $length);
$want_reply = ord($this->_string_shift($payload)) != 0;
if (!$this->_send_binary_packet(pack('C', NET_SSH2_MSG_REQUEST_FAILURE))) {
if ($want_reply && !$this->_send_binary_packet(pack('C', NET_SSH2_MSG_REQUEST_FAILURE))) {
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
}
@@ -4263,7 +4270,7 @@ class SSH2
$this->errors[count($this->errors)].= "\r\n" . $this->_string_shift($response, $length);
}
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel]));
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$channel]));
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel]));
$this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_EOF;
@@ -4281,8 +4288,13 @@ class SSH2
continue 3;
default:
// "Some systems may not implement signals, in which case they SHOULD ignore this message."
// -- http://tools.ietf.org/html/rfc4254#section-6.9
$want_reply = ord($this->_string_shift($response)) != 0;
if ($want_reply) {
// "If the request is not recognized or is not supported for the channel,
// SSH_MSG_CHANNEL_FAILURE is returned."
// -- https://datatracker.ietf.org/doc/html/rfc4254#page-10
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_FAILURE, $this->server_channels[$channel]));
}
continue 3;
}
}