Updates the phpseclib library.

This commit is contained in:
Llewellyn van der Merwe 2021-06-15 01:23:57 +02:00
parent 130235e252
commit e3aac938aa
Signed by: Llewellyn
GPG Key ID: EFC0C720A240551C
21 changed files with 650 additions and 399 deletions

View File

@ -143,7 +143,7 @@ TODO
+ *Author*: [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com) + *Author*: [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com)
+ *Name*: [Component Builder](https://github.com/vdm-io/Joomla-Component-Builder) + *Name*: [Component Builder](https://github.com/vdm-io/Joomla-Component-Builder)
+ *First Build*: 30th April, 2015 + *First Build*: 30th April, 2015
+ *Last Build*: 11th June, 2021 + *Last Build*: 14th June, 2021
+ *Version*: 2.12.10 + *Version*: 2.12.10
+ *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved. + *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved.
+ *License*: GNU General Public License version 2 or later; see LICENSE.txt + *License*: GNU General Public License version 2 or later; see LICENSE.txt

View File

@ -143,7 +143,7 @@ TODO
+ *Author*: [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com) + *Author*: [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com)
+ *Name*: [Component Builder](https://github.com/vdm-io/Joomla-Component-Builder) + *Name*: [Component Builder](https://github.com/vdm-io/Joomla-Component-Builder)
+ *First Build*: 30th April, 2015 + *First Build*: 30th April, 2015
+ *Last Build*: 11th June, 2021 + *Last Build*: 14th June, 2021
+ *Version*: 2.12.10 + *Version*: 2.12.10
+ *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved. + *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved.
+ *License*: GNU General Public License version 2 or later; see LICENSE.txt + *License*: GNU General Public License version 2 or later; see LICENSE.txt

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.2" method="upgrade"> <extension type="component" version="3.2" method="upgrade">
<name>COM_COMPONENTBUILDER</name> <name>COM_COMPONENTBUILDER</name>
<creationDate>11th June, 2021</creationDate> <creationDate>14th June, 2021</creationDate>
<author>Llewellyn van der Merwe</author> <author>Llewellyn van der Merwe</author>
<authorEmail>llewellyn@joomlacomponentbuilder.com</authorEmail> <authorEmail>llewellyn@joomlacomponentbuilder.com</authorEmail>
<authorUrl>http://www.joomlacomponentbuilder.com</authorUrl> <authorUrl>http://www.joomlacomponentbuilder.com</authorUrl>

View File

@ -1,52 +1,15 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Copyright (c) Nils Adermann, Jordi Boggiano
Upstream-Name: Composer
Upstream-Contact: Jordi Boggiano <j.boggiano@seld.be>
Source: https://github.com/composer/composer
Files: *
Copyright: 2016, Nils Adermann <naderman@naderman.de>
2016, Jordi Boggiano <j.boggiano@seld.be>
License: Expat
Files: src/Composer/Util/TlsHelper.php
Copyright: 2016, Nils Adermann <naderman@naderman.de>
2016, Jordi Boggiano <j.boggiano@seld.be>
2013, Evan Coury <me@evancoury.com>
License: Expat and BSD-2-Clause
License: BSD-2-Clause
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
.
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License: Expat
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions: to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

View File

@ -6,28 +6,4 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir); $baseDir = dirname($vendorDir);
return array( return array(
'phpseclib\\Crypt\\AES' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/AES.php',
'phpseclib\\Crypt\\Base' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Base.php',
'phpseclib\\Crypt\\Blowfish' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php',
'phpseclib\\Crypt\\DES' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/DES.php',
'phpseclib\\Crypt\\Hash' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Hash.php',
'phpseclib\\Crypt\\RC2' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RC2.php',
'phpseclib\\Crypt\\RC4' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RC4.php',
'phpseclib\\Crypt\\RSA' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RSA.php',
'phpseclib\\Crypt\\Random' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Random.php',
'phpseclib\\Crypt\\Rijndael' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php',
'phpseclib\\Crypt\\TripleDES' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php',
'phpseclib\\Crypt\\Twofish' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php',
'phpseclib\\File\\ANSI' => $vendorDir . '/phpseclib/phpseclib/phpseclib/File/ANSI.php',
'phpseclib\\File\\ASN1' => $vendorDir . '/phpseclib/phpseclib/phpseclib/File/ASN1.php',
'phpseclib\\File\\ASN1\\Element' => $vendorDir . '/phpseclib/phpseclib/phpseclib/File/ASN1/Element.php',
'phpseclib\\File\\X509' => $vendorDir . '/phpseclib/phpseclib/phpseclib/File/X509.php',
'phpseclib\\Math\\BigInteger' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Math/BigInteger.php',
'phpseclib\\Net\\SCP' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Net/SCP.php',
'phpseclib\\Net\\SFTP' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Net/SFTP.php',
'phpseclib\\Net\\SFTP\\Stream' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php',
'phpseclib\\Net\\SSH1' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Net/SSH1.php',
'phpseclib\\Net\\SSH2' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Net/SSH2.php',
'phpseclib\\System\\SSH\\Agent' => $vendorDir . '/phpseclib/phpseclib/phpseclib/System/SSH/Agent.php',
'phpseclib\\System\\SSH\\Agent\\Identity' => $vendorDir . '/phpseclib/phpseclib/phpseclib/System/SSH/Agent/Identity.php',
); );

View File

@ -13,6 +13,9 @@ class ComposerAutoloaderInit10d22a526bd476954b93748a871e7ad4
} }
} }
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader() public static function getLoader()
{ {
if (null !== self::$loader) { if (null !== self::$loader) {

View File

@ -24,39 +24,11 @@ class ComposerStaticInit10d22a526bd476954b93748a871e7ad4
), ),
); );
public static $classMap = array (
'phpseclib\\Crypt\\AES' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/AES.php',
'phpseclib\\Crypt\\Base' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Base.php',
'phpseclib\\Crypt\\Blowfish' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php',
'phpseclib\\Crypt\\DES' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/DES.php',
'phpseclib\\Crypt\\Hash' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Hash.php',
'phpseclib\\Crypt\\RC2' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RC2.php',
'phpseclib\\Crypt\\RC4' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RC4.php',
'phpseclib\\Crypt\\RSA' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RSA.php',
'phpseclib\\Crypt\\Random' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Random.php',
'phpseclib\\Crypt\\Rijndael' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php',
'phpseclib\\Crypt\\TripleDES' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php',
'phpseclib\\Crypt\\Twofish' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php',
'phpseclib\\File\\ANSI' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/File/ANSI.php',
'phpseclib\\File\\ASN1' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/File/ASN1.php',
'phpseclib\\File\\ASN1\\Element' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/File/ASN1/Element.php',
'phpseclib\\File\\X509' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/File/X509.php',
'phpseclib\\Math\\BigInteger' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Math/BigInteger.php',
'phpseclib\\Net\\SCP' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Net/SCP.php',
'phpseclib\\Net\\SFTP' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Net/SFTP.php',
'phpseclib\\Net\\SFTP\\Stream' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php',
'phpseclib\\Net\\SSH1' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Net/SSH1.php',
'phpseclib\\Net\\SSH2' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Net/SSH2.php',
'phpseclib\\System\\SSH\\Agent' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/System/SSH/Agent.php',
'phpseclib\\System\\SSH\\Agent\\Identity' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/System/SSH/Agent/Identity.php',
);
public static function getInitializer(ClassLoader $loader) public static function getInitializer(ClassLoader $loader)
{ {
return \Closure::bind(function () use ($loader) { return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit10d22a526bd476954b93748a871e7ad4::$prefixLengthsPsr4; $loader->prefixLengthsPsr4 = ComposerStaticInit10d22a526bd476954b93748a871e7ad4::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit10d22a526bd476954b93748a871e7ad4::$prefixDirsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInit10d22a526bd476954b93748a871e7ad4::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit10d22a526bd476954b93748a871e7ad4::$classMap;
}, null, ClassLoader::class); }, null, ClassLoader::class);
} }

View File

@ -1,17 +1,17 @@
[ [
{ {
"name": "phpseclib/phpseclib", "name": "phpseclib/phpseclib",
"version": "2.0.27", "version": "2.0.32",
"version_normalized": "2.0.27.0", "version_normalized": "2.0.32.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpseclib/phpseclib.git", "url": "https://github.com/phpseclib/phpseclib.git",
"reference": "34620af4df7d1988d8f0d7e91f6c8a3bf931d8dc" "reference": "f5c4c19880d45d0be3e7d24ae8ac434844a898cd"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/34620af4df7d1988d8f0d7e91f6c8a3bf931d8dc", "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/f5c4c19880d45d0be3e7d24ae8ac434844a898cd",
"reference": "34620af4df7d1988d8f0d7e91f6c8a3bf931d8dc", "reference": "f5c4c19880d45d0be3e7d24ae8ac434844a898cd",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -19,8 +19,7 @@
}, },
"require-dev": { "require-dev": {
"phing/phing": "~2.7", "phing/phing": "~2.7",
"phpunit/phpunit": "^4.8.35|^5.7|^6.0", "phpunit/phpunit": "^4.8.35|^5.7|^6.0|^9.4",
"sami/sami": "~2.0",
"squizlabs/php_codesniffer": "~2.0" "squizlabs/php_codesniffer": "~2.0"
}, },
"suggest": { "suggest": {
@ -29,7 +28,7 @@
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", "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." "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
}, },
"time": "2020-04-04T23:17:33+00:00", "time": "2021-06-12T12:12:59+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -91,6 +90,20 @@
"twofish", "twofish",
"x.509", "x.509",
"x509" "x509"
],
"funding": [
{
"url": "https://github.com/terrafrost",
"type": "github"
},
{
"url": "https://www.patreon.com/phpseclib",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib",
"type": "tidelift"
}
] ]
} }
] ]

View File

@ -1,6 +1,6 @@
# phpseclib - PHP Secure Communications Library # phpseclib - PHP Secure Communications Library
[![Build Status](https://travis-ci.org/phpseclib/phpseclib.svg?branch=2.0)](https://travis-ci.org/phpseclib/phpseclib) [![Build Status](https://travis-ci.com/phpseclib/phpseclib.svg?branch=2.0)](https://travis-ci.com/phpseclib/phpseclib)
## Supporting phpseclib ## Supporting phpseclib
@ -10,16 +10,16 @@
## Introduction ## Introduction
MIT-licensed pure-PHP implementations of an arbitrary-precision integer MIT-licensed pure-PHP implementations of the following:
arithmetic library, fully PKCS#1 (v2.1) compliant RSA, DES, 3DES, RC4, Rijndael,
AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509 SSH-2, SFTP, X.509, an arbitrary-precision integer arithmetic library, Ed25519 / Ed449 / Curve25519 / Curve449, ECDSA / ECDH (with support for 66 curves), RSA (PKCS#1 v2.2 compliant), DSA / DH, DES / 3DES / RC4 / Rijndael / AES / Blowfish / Twofish / Salsa20 / ChaCha20, GCM / Poly1305
* [Browse Git](https://github.com/phpseclib/phpseclib) * [Browse Git](https://github.com/phpseclib/phpseclib)
## Documentation ## Documentation
* [Documentation / Manual](http://phpseclib.sourceforge.net/) * [Documentation / Manual](https://phpseclib.com/)
* [API Documentation](https://api.phpseclib.org/2.0/) (generated by Sami) * [API Documentation](https://api.phpseclib.com/2.0/) (generated by Doctum)
## Branches ## Branches
@ -29,6 +29,14 @@ AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509
* Unstable API * Unstable API
* Do not use in production * Do not use in production
### 3.0
* Long term support (LTS) release
* Major expansion of cryptographic primitives
* Minimum PHP version: 5.6.1
* PSR-4 autoloading with namespace rooted at `\phpseclib3`
* Install via Composer: `composer require phpseclib/phpseclib:~3.0`
### 2.0 ### 2.0
* Long term support (LTS) release * Long term support (LTS) release
@ -44,7 +52,7 @@ AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509
* Composer compatible (PSR-0 autoloading) * Composer compatible (PSR-0 autoloading)
* Install using Composer: `composer require phpseclib/phpseclib:~1.0` * Install using Composer: `composer require phpseclib/phpseclib:~1.0`
* Install using PEAR: See [phpseclib PEAR Channel Documentation](http://phpseclib.sourceforge.net/pear.htm) * Install using PEAR: See [phpseclib PEAR Channel Documentation](http://phpseclib.sourceforge.net/pear.htm)
* [Download 1.0.18 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.18.zip/download) * [Download 1.0.19 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.19.zip/download)
## Security contact information ## Security contact information

View File

@ -55,8 +55,7 @@
}, },
"require-dev": { "require-dev": {
"phing/phing": "~2.7", "phing/phing": "~2.7",
"phpunit/phpunit": "^4.8.35|^5.7|^6.0", "phpunit/phpunit": "^4.8.35|^5.7|^6.0|^9.4",
"sami/sami": "~2.0",
"squizlabs/php_codesniffer": "~2.0" "squizlabs/php_codesniffer": "~2.0"
}, },
"suggest": { "suggest": {

View File

@ -413,7 +413,7 @@ abstract class Base
* @var mixed * @var mixed
* @access private * @access private
*/ */
var $use_inline_crypt; var $use_inline_crypt = true;
/** /**
* If OpenSSL can be used in ECB but not in CTR we can emulate CTR * If OpenSSL can be used in ECB but not in CTR we can emulate CTR
@ -495,11 +495,6 @@ abstract class Base
} }
$this->_setEngine(); $this->_setEngine();
// Determining whether inline crypting can be used by the cipher
if ($this->use_inline_crypt !== false) {
$this->use_inline_crypt = version_compare(PHP_VERSION, '5.3.0') >= 0 || function_exists('create_function');
}
} }
/** /**
@ -784,12 +779,14 @@ abstract class Base
} }
if ($this->engine === self::ENGINE_MCRYPT) { if ($this->engine === self::ENGINE_MCRYPT) {
set_error_handler(array($this, 'do_nothing'));
if ($this->changed) { if ($this->changed) {
$this->_setupMcrypt(); $this->_setupMcrypt();
$this->changed = false; $this->changed = false;
} }
if ($this->enchanged) { if ($this->enchanged) {
@mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
$this->enchanged = false; $this->enchanged = false;
} }
@ -822,15 +819,15 @@ abstract class Base
if ($len >= $block_size) { if ($len >= $block_size) {
if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) { if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) {
if ($this->enbuffer['enmcrypt_init'] === true) { if ($this->enbuffer['enmcrypt_init'] === true) {
@mcrypt_generic_init($this->enmcrypt, $this->key, $iv); mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
$this->enbuffer['enmcrypt_init'] = false; $this->enbuffer['enmcrypt_init'] = false;
} }
$ciphertext.= @mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size)); $ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size));
$iv = substr($ciphertext, -$block_size); $iv = substr($ciphertext, -$block_size);
$len%= $block_size; $len%= $block_size;
} else { } else {
while ($len >= $block_size) { while ($len >= $block_size) {
$iv = @mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size); $iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size);
$ciphertext.= $iv; $ciphertext.= $iv;
$len-= $block_size; $len-= $block_size;
$i+= $block_size; $i+= $block_size;
@ -839,22 +836,26 @@ abstract class Base
} }
if ($len) { if ($len) {
$iv = @mcrypt_generic($this->ecb, $iv); $iv = mcrypt_generic($this->ecb, $iv);
$block = $iv ^ substr($plaintext, -$len); $block = $iv ^ substr($plaintext, -$len);
$iv = substr_replace($iv, $block, 0, $len); $iv = substr_replace($iv, $block, 0, $len);
$ciphertext.= $block; $ciphertext.= $block;
$pos = $len; $pos = $len;
} }
restore_error_handler();
return $ciphertext; return $ciphertext;
} }
$ciphertext = @mcrypt_generic($this->enmcrypt, $plaintext); $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
if (!$this->continuousBuffer) { if (!$this->continuousBuffer) {
@mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
} }
restore_error_handler();
return $ciphertext; return $ciphertext;
} }
@ -1123,13 +1124,14 @@ abstract class Base
} }
if ($this->engine === self::ENGINE_MCRYPT) { if ($this->engine === self::ENGINE_MCRYPT) {
set_error_handler(array($this, 'do_nothing'));
$block_size = $this->block_size; $block_size = $this->block_size;
if ($this->changed) { if ($this->changed) {
$this->_setupMcrypt(); $this->_setupMcrypt();
$this->changed = false; $this->changed = false;
} }
if ($this->dechanged) { if ($this->dechanged) {
@mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
$this->dechanged = false; $this->dechanged = false;
} }
@ -1157,26 +1159,30 @@ abstract class Base
} }
if ($len >= $block_size) { if ($len >= $block_size) {
$cb = substr($ciphertext, $i, $len - $len % $block_size); $cb = substr($ciphertext, $i, $len - $len % $block_size);
$plaintext.= @mcrypt_generic($this->ecb, $iv . $cb) ^ $cb; $plaintext.= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
$iv = substr($cb, -$block_size); $iv = substr($cb, -$block_size);
$len%= $block_size; $len%= $block_size;
} }
if ($len) { if ($len) {
$iv = @mcrypt_generic($this->ecb, $iv); $iv = mcrypt_generic($this->ecb, $iv);
$plaintext.= $iv ^ substr($ciphertext, -$len); $plaintext.= $iv ^ substr($ciphertext, -$len);
$iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len); $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
$pos = $len; $pos = $len;
} }
restore_error_handler();
return $plaintext; return $plaintext;
} }
$plaintext = @mdecrypt_generic($this->demcrypt, $ciphertext); $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
if (!$this->continuousBuffer) { if (!$this->continuousBuffer) {
@mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
} }
restore_error_handler();
return $this->paddable ? $this->_unpad($plaintext) : $plaintext; return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
} }
@ -1654,9 +1660,12 @@ abstract class Base
} }
return false; return false;
case self::ENGINE_MCRYPT: case self::ENGINE_MCRYPT:
return $this->cipher_name_mcrypt && set_error_handler(array($this, 'do_nothing'));
$result = $this->cipher_name_mcrypt &&
extension_loaded('mcrypt') && extension_loaded('mcrypt') &&
in_array($this->cipher_name_mcrypt, @mcrypt_list_algorithms()); in_array($this->cipher_name_mcrypt, mcrypt_list_algorithms());
restore_error_handler();
return $result;
case self::ENGINE_INTERNAL: case self::ENGINE_INTERNAL:
return true; return true;
} }
@ -1733,17 +1742,19 @@ abstract class Base
} }
if ($this->engine != self::ENGINE_MCRYPT && $this->enmcrypt) { if ($this->engine != self::ENGINE_MCRYPT && $this->enmcrypt) {
set_error_handler(array($this, 'do_nothing'));
// Closing the current mcrypt resource(s). _mcryptSetup() will, if needed, // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed,
// (re)open them with the module named in $this->cipher_name_mcrypt // (re)open them with the module named in $this->cipher_name_mcrypt
@mcrypt_module_close($this->enmcrypt); mcrypt_module_close($this->enmcrypt);
@mcrypt_module_close($this->demcrypt); mcrypt_module_close($this->demcrypt);
$this->enmcrypt = null; $this->enmcrypt = null;
$this->demcrypt = null; $this->demcrypt = null;
if ($this->ecb) { if ($this->ecb) {
@mcrypt_module_close($this->ecb); mcrypt_module_close($this->ecb);
$this->ecb = null; $this->ecb = null;
} }
restore_error_handler();
} }
$this->changed = true; $this->changed = true;
@ -1856,19 +1867,19 @@ abstract class Base
self::MODE_STREAM => MCRYPT_MODE_STREAM, self::MODE_STREAM => MCRYPT_MODE_STREAM,
); );
$this->demcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); $this->demcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
$this->enmcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); $this->enmcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
// we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer() // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
// to workaround mcrypt's broken ncfb implementation in buffered mode // to workaround mcrypt's broken ncfb implementation in buffered mode
// see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps} // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
if ($this->mode == self::MODE_CFB) { if ($this->mode == self::MODE_CFB) {
$this->ecb = @mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, ''); $this->ecb = mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
} }
} // else should mcrypt_generic_deinit be called? } // else should mcrypt_generic_deinit be called?
if ($this->mode == self::MODE_CFB) { if ($this->mode == self::MODE_CFB) {
@mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size)); mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size));
} }
} }
@ -2602,14 +2613,10 @@ abstract class Base
} }
// Create the $inline function and return its name as string. Ready to run! // Create the $inline function and return its name as string. Ready to run!
if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
eval('$func = function ($_action, &$self, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' } };'); eval('$func = function ($_action, &$self, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' } };');
return $func; return $func;
} }
return create_function('$_action, &$self, $_text', $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }');
}
/** /**
* Holds the lambda_functions table (classwide) * Holds the lambda_functions table (classwide)
* *
@ -2636,7 +2643,7 @@ abstract class Base
* *
* @see self::_setupInlineCrypt() * @see self::_setupInlineCrypt()
* @access private * @access private
* @param $bytes * @param string $bytes
* @return string * @return string
*/ */
function _hashInlineCryptFunction($bytes) function _hashInlineCryptFunction($bytes)
@ -2705,4 +2712,13 @@ abstract class Base
return $safeint . '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))'; return $safeint . '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))';
} }
} }
/**
* Dummy error handler to suppress mcrypt errors
*
* @access private
*/
function do_nothing()
{
}
} }

View File

@ -849,7 +849,6 @@ class Hash
* _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the * _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the
* possibility of overflow exists, care has to be taken. BigInteger could be used but this should be faster. * possibility of overflow exists, care has to be taken. BigInteger could be used but this should be faster.
* *
* @param int $...
* @return int * @return int
* @see self::_sha256() * @see self::_sha256()
* @access private * @access private

View File

@ -537,7 +537,7 @@ class RSA
* @access public * @access public
* @param int $bits * @param int $bits
* @param int $timeout * @param int $timeout
* @param array $p * @param array $partial
*/ */
function createKey($bits = 1024, $timeout = false, $partial = array()) function createKey($bits = 1024, $timeout = false, $partial = array())
{ {
@ -716,7 +716,12 @@ class RSA
* *
* @access private * @access private
* @see self::setPrivateKeyFormat() * @see self::setPrivateKeyFormat()
* @param string $RSAPrivateKey * @param Math_BigInteger $n
* @param Math_BigInteger $e
* @param Math_BigInteger $d
* @param array<int,Math_BigInteger> $primes
* @param array<int,Math_BigInteger> $exponents
* @param array<int,Math_BigInteger> $coefficients
* @return string * @return string
*/ */
function _convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients) function _convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients)
@ -997,8 +1002,9 @@ class RSA
* *
* @access private * @access private
* @see self::setPublicKeyFormat() * @see self::setPublicKeyFormat()
* @param string $RSAPrivateKey * @param Math_BigInteger $n
* @return string * @param Math_BigInteger $e
* @return string|array<string,Math_BigInteger>
*/ */
function _convertPublicKey($n, $e) function _convertPublicKey($n, $e)
{ {
@ -1213,6 +1219,7 @@ class RSA
$length = $this->_decodeLength($temp); $length = $this->_decodeLength($temp);
switch ($this->_string_shift($temp, $length)) { switch ($this->_string_shift($temp, $length)) {
case "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01": // rsaEncryption case "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01": // rsaEncryption
case "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0A": // rsaPSS
break; break;
case "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03": // pbeWithMD5AndDES-CBC case "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03": // pbeWithMD5AndDES-CBC
/* /*
@ -1539,6 +1546,8 @@ class RSA
return $components; return $components;
} }
return false;
} }
/** /**
@ -1878,7 +1887,6 @@ class RSA
* *
* @see self::getPublicKey() * @see self::getPublicKey()
* @access public * @access public
* @param string $key
* @param int $type optional * @param int $type optional
*/ */
function getPublicKey($type = self::PUBLIC_FORMAT_PKCS8) function getPublicKey($type = self::PUBLIC_FORMAT_PKCS8)
@ -1936,7 +1944,6 @@ class RSA
* *
* @see self::getPublicKey() * @see self::getPublicKey()
* @access public * @access public
* @param string $key
* @param int $type optional * @param int $type optional
* @return mixed * @return mixed
*/ */
@ -1961,8 +1968,7 @@ class RSA
* *
* @see self::getPrivateKey() * @see self::getPrivateKey()
* @access private * @access private
* @param string $key * @param int $mode optional
* @param int $type optional
*/ */
function _getPrivatePublicKey($mode = self::PUBLIC_FORMAT_PKCS8) function _getPrivatePublicKey($mode = self::PUBLIC_FORMAT_PKCS8)
{ {
@ -2179,7 +2185,7 @@ class RSA
* of the hash function Hash) and 0. * of the hash function Hash) and 0.
* *
* @access public * @access public
* @param int $format * @param int $sLen
*/ */
function setSaltLength($sLen) function setSaltLength($sLen)
{ {
@ -2212,7 +2218,7 @@ class RSA
* See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}. * See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}.
* *
* @access private * @access private
* @param string $x * @param int|string|resource $x
* @return \phpseclib\Math\BigInteger * @return \phpseclib\Math\BigInteger
*/ */
function _os2ip($x) function _os2ip($x)
@ -2439,7 +2445,7 @@ class RSA
* *
* @access private * @access private
* @param string $mgfSeed * @param string $mgfSeed
* @param int $mgfLen * @param int $maskLen
* @return string * @return string
*/ */
function _mgf1($mgfSeed, $maskLen) function _mgf1($mgfSeed, $maskLen)
@ -2574,9 +2580,9 @@ class RSA
$offset+= $patternMatch ? 0 : 1; $offset+= $patternMatch ? 0 : 1;
} }
// we do & instead of && to avoid https://en.wikipedia.org/wiki/Short-circuit_evaluation // we do | instead of || to avoid https://en.wikipedia.org/wiki/Short-circuit_evaluation
// to protect against timing attacks // to protect against timing attacks
if (!$hashesMatch & !$patternMatch) { if (!$hashesMatch | !$patternMatch) {
user_error('Decryption error'); user_error('Decryption error');
return false; return false;
} }
@ -2911,6 +2917,59 @@ class RSA
return $em; return $em;
} }
/**
* EMSA-PKCS1-V1_5-ENCODE (without NULL)
*
* Quoting https://tools.ietf.org/html/rfc8017#page-65,
*
* "The parameters field associated with id-sha1, id-sha224, id-sha256,
* id-sha384, id-sha512, id-sha512/224, and id-sha512/256 should
* generally be omitted, but if present, it shall have a value of type
* NULL"
*
* @access private
* @param string $m
* @param int $emLen
* @return string
*/
function _emsa_pkcs1_v1_5_encode_without_null($m, $emLen)
{
$h = $this->hash->hash($m);
if ($h === false) {
return false;
}
switch ($this->hashName) {
case 'sha1':
$t = pack('H*', '301f300706052b0e03021a0414');
break;
case 'sha256':
$t = pack('H*', '302f300b06096086480165030402010420');
break;
case 'sha384':
$t = pack('H*', '303f300b06096086480165030402020430');
break;
case 'sha512':
$t = pack('H*', '304f300b06096086480165030402030440');
break;
default:
return false;
}
$t.= $h;
$tLen = strlen($t);
if ($emLen < $tLen + 11) {
user_error('Intended encoded message length too short');
return false;
}
$ps = str_repeat(chr(0xFF), $emLen - $tLen - 3);
$em = "\0\1$ps\0$t";
return $em;
}
/** /**
* RSASSA-PKCS1-V1_5-SIGN * RSASSA-PKCS1-V1_5-SIGN
* *
@ -2948,6 +3007,7 @@ class RSA
* *
* @access private * @access private
* @param string $m * @param string $m
* @param string $s
* @return string * @return string
*/ */
function _rsassa_pkcs1_v1_5_verify($m, $s) function _rsassa_pkcs1_v1_5_verify($m, $s)
@ -2976,13 +3036,17 @@ class RSA
// EMSA-PKCS1-v1_5 encoding // EMSA-PKCS1-v1_5 encoding
$em2 = $this->_emsa_pkcs1_v1_5_encode($m, $this->k); $em2 = $this->_emsa_pkcs1_v1_5_encode($m, $this->k);
if ($em2 === false) { $em3 = $this->_emsa_pkcs1_v1_5_encode_without_null($m, $this->k);
if ($em2 === false && $em3 === false) {
user_error('RSA modulus too short'); user_error('RSA modulus too short');
return false; return false;
} }
// Compare // Compare
return $this->_equals($em, $em2);
return ($em2 !== false && $this->_equals($em, $em2)) ||
($em3 !== false && $this->_equals($em, $em3));
} }
/** /**
@ -3088,7 +3152,7 @@ class RSA
* *
* @see self::encrypt() * @see self::encrypt()
* @access public * @access public
* @param string $plaintext * @param string $ciphertext
* @return string * @return string
*/ */
function decrypt($ciphertext) function decrypt($ciphertext)

View File

@ -203,8 +203,7 @@ class ANSI
/** /**
* Set the number of lines that should be logged past the terminal height * Set the number of lines that should be logged past the terminal height
* *
* @param int $x * @param int $history
* @param int $y
* @access public * @access public
*/ */
function setHistory($history) function setHistory($history)
@ -272,7 +271,7 @@ class ANSI
case "\x1B[K": // Clear screen from cursor right case "\x1B[K": // Clear screen from cursor right
$this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x); $this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x);
array_splice($this->attrs[$this->y], $this->x + 1, $this->max_x - $this->x, array_fill($this->x, $this->max_x - $this->x - 1, $this->base_attr_cell)); array_splice($this->attrs[$this->y], $this->x + 1, $this->max_x - $this->x, array_fill($this->x, $this->max_x - ($this->x - 1), $this->base_attr_cell));
break; break;
case "\x1B[2K": // Clear entire line case "\x1B[2K": // Clear entire line
$this->screen[$this->y] = str_repeat(' ', $this->x); $this->screen[$this->y] = str_repeat(' ', $this->x);
@ -316,19 +315,20 @@ class ANSI
$mods = explode(';', $match[1]); $mods = explode(';', $match[1]);
foreach ($mods as $mod) { foreach ($mods as $mod) {
switch ($mod) { switch ($mod) {
case 0: // Turn off character attributes case '':
case '0': // Turn off character attributes
$attr_cell = clone $this->base_attr_cell; $attr_cell = clone $this->base_attr_cell;
break; break;
case 1: // Turn bold mode on case '1': // Turn bold mode on
$attr_cell->bold = true; $attr_cell->bold = true;
break; break;
case 4: // Turn underline mode on case '4': // Turn underline mode on
$attr_cell->underline = true; $attr_cell->underline = true;
break; break;
case 5: // Turn blinking mode on case '5': // Turn blinking mode on
$attr_cell->blink = true; $attr_cell->blink = true;
break; break;
case 7: // Turn reverse video on case '7': // Turn reverse video on
$attr_cell->reverse = !$attr_cell->reverse; $attr_cell->reverse = !$attr_cell->reverse;
$temp = $attr_cell->background; $temp = $attr_cell->background;
$attr_cell->background = $attr_cell->foreground; $attr_cell->background = $attr_cell->foreground;
@ -341,23 +341,23 @@ class ANSI
$back = &$attr_cell->{ $attr_cell->reverse ? 'foreground' : 'background' }; $back = &$attr_cell->{ $attr_cell->reverse ? 'foreground' : 'background' };
switch ($mod) { switch ($mod) {
// @codingStandardsIgnoreStart // @codingStandardsIgnoreStart
case 30: $front = 'black'; break; case '30': $front = 'black'; break;
case 31: $front = 'red'; break; case '31': $front = 'red'; break;
case 32: $front = 'green'; break; case '32': $front = 'green'; break;
case 33: $front = 'yellow'; break; case '33': $front = 'yellow'; break;
case 34: $front = 'blue'; break; case '34': $front = 'blue'; break;
case 35: $front = 'magenta'; break; case '35': $front = 'magenta'; break;
case 36: $front = 'cyan'; break; case '36': $front = 'cyan'; break;
case 37: $front = 'white'; break; case '37': $front = 'white'; break;
case 40: $back = 'black'; break; case '40': $back = 'black'; break;
case 41: $back = 'red'; break; case '41': $back = 'red'; break;
case 42: $back = 'green'; break; case '42': $back = 'green'; break;
case 43: $back = 'yellow'; break; case '43': $back = 'yellow'; break;
case 44: $back = 'blue'; break; case '44': $back = 'blue'; break;
case 45: $back = 'magenta'; break; case '45': $back = 'magenta'; break;
case 46: $back = 'cyan'; break; case '46': $back = 'cyan'; break;
case 47: $back = 'white'; break; case '47': $back = 'white'; break;
// @codingStandardsIgnoreEnd // @codingStandardsIgnoreEnd
default: default:

View File

@ -235,7 +235,7 @@ class ASN1
$current = array('start' => $start); $current = array('start' => $start);
$type = ord($encoded[$encoded_pos++]); $type = ord($encoded[$encoded_pos++]);
$start++; $startOffset = 1;
$constructed = ($type >> 5) & 1; $constructed = ($type >> 5) & 1;
@ -245,13 +245,20 @@ class ASN1
// process septets (since the eighth bit is ignored, it's not an octet) // process septets (since the eighth bit is ignored, it's not an octet)
do { do {
$temp = ord($encoded[$encoded_pos++]); $temp = ord($encoded[$encoded_pos++]);
$startOffset++;
$loop = $temp >> 7; $loop = $temp >> 7;
$tag <<= 7; $tag <<= 7;
$tag |= $temp & 0x7F; $temp &= 0x7F;
$start++; // "bits 7 to 1 of the first subsequent octet shall not all be zero"
if ($startOffset == 2 && $temp == 0) {
return false;
}
$tag |= $temp;
} while ($loop); } while ($loop);
} }
$start+= $startOffset;
// Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13 // Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13
$length = ord($encoded[$encoded_pos++]); $length = ord($encoded[$encoded_pos++]);
$start++; $start++;
@ -344,13 +351,16 @@ class ASN1
switch ($tag) { switch ($tag) {
case self::TYPE_BOOLEAN: case self::TYPE_BOOLEAN:
// "The contents octets shall consist of a single octet." -- paragraph 8.2.1 // "The contents octets shall consist of a single octet." -- paragraph 8.2.1
//if (strlen($content) != 1) { if ($constructed || strlen($content) != 1) {
// return false; return false;
//} }
$current['content'] = (bool) ord($content[$content_pos]); $current['content'] = (bool) ord($content[$content_pos]);
break; break;
case self::TYPE_INTEGER: case self::TYPE_INTEGER:
case self::TYPE_ENUMERATED: case self::TYPE_ENUMERATED:
if ($constructed) {
return false;
}
$current['content'] = new BigInteger(substr($content, $content_pos), -256); $current['content'] = new BigInteger(substr($content, $content_pos), -256);
break; break;
case self::TYPE_REAL: // not currently supported case self::TYPE_REAL: // not currently supported
@ -370,15 +380,15 @@ class ASN1
$last = count($temp) - 1; $last = count($temp) - 1;
for ($i = 0; $i < $last; $i++) { for ($i = 0; $i < $last; $i++) {
// all subtags should be bit strings // all subtags should be bit strings
//if ($temp[$i]['type'] != self::TYPE_BIT_STRING) { if ($temp[$i]['type'] != self::TYPE_BIT_STRING) {
// return false; return false;
//} }
$current['content'].= substr($temp[$i]['content'], 1); $current['content'].= substr($temp[$i]['content'], 1);
} }
// all subtags should be bit strings // all subtags should be bit strings
//if ($temp[$last]['type'] != self::TYPE_BIT_STRING) { if ($temp[$last]['type'] != self::TYPE_BIT_STRING) {
// return false; return false;
//} }
$current['content'] = $temp[$last]['content'][0] . $current['content'] . substr($temp[$i]['content'], 1); $current['content'] = $temp[$last]['content'][0] . $current['content'] . substr($temp[$i]['content'], 1);
} }
break; break;
@ -395,9 +405,9 @@ class ASN1
} }
$content_pos += $temp['length']; $content_pos += $temp['length'];
// all subtags should be octet strings // all subtags should be octet strings
//if ($temp['type'] != self::TYPE_OCTET_STRING) { if ($temp['type'] != self::TYPE_OCTET_STRING) {
// return false; return false;
//} }
$current['content'].= $temp['content']; $current['content'].= $temp['content'];
$length+= $temp['length']; $length+= $temp['length'];
} }
@ -408,12 +418,15 @@ class ASN1
break; break;
case self::TYPE_NULL: case self::TYPE_NULL:
// "The contents octets shall not contain any octets." -- paragraph 8.8.2 // "The contents octets shall not contain any octets." -- paragraph 8.8.2
//if (strlen($content)) { if ($constructed || strlen($content)) {
// return false; return false;
//} }
break; break;
case self::TYPE_SEQUENCE: case self::TYPE_SEQUENCE:
case self::TYPE_SET: case self::TYPE_SET:
if (!$constructed) {
return false;
}
$offset = 0; $offset = 0;
$current['content'] = array(); $current['content'] = array();
$content_len = strlen($content); $content_len = strlen($content);
@ -434,7 +447,13 @@ class ASN1
} }
break; break;
case self::TYPE_OBJECT_IDENTIFIER: case self::TYPE_OBJECT_IDENTIFIER:
if ($constructed) {
return false;
}
$current['content'] = $this->_decodeOID(substr($content, $content_pos)); $current['content'] = $this->_decodeOID(substr($content, $content_pos));
if ($current['content'] === false) {
return false;
}
break; break;
/* Each character string type shall be encoded as if it had been declared: /* Each character string type shall be encoded as if it had been declared:
[UNIVERSAL x] IMPLICIT OCTET STRING [UNIVERSAL x] IMPLICIT OCTET STRING
@ -464,12 +483,20 @@ class ASN1
case self::TYPE_UTF8_STRING: case self::TYPE_UTF8_STRING:
// ???? // ????
case self::TYPE_BMP_STRING: case self::TYPE_BMP_STRING:
if ($constructed) {
return false;
}
$current['content'] = substr($content, $content_pos); $current['content'] = substr($content, $content_pos);
break; break;
case self::TYPE_UTC_TIME: case self::TYPE_UTC_TIME:
case self::TYPE_GENERALIZED_TIME: case self::TYPE_GENERALIZED_TIME:
if ($constructed) {
return false;
}
$current['content'] = $this->_decodeTime(substr($content, $content_pos), $tag); $current['content'] = $this->_decodeTime(substr($content, $content_pos), $tag);
break;
default: default:
return false;
} }
$start+= $length; $start+= $length;
@ -790,7 +817,7 @@ class ASN1
* *
* @param string $source * @param string $source
* @param string $mapping * @param string $mapping
* @param int $idx * @param array $special
* @return string * @return string
* @access public * @access public
*/ */
@ -806,6 +833,7 @@ class ASN1
* @param string $source * @param string $source
* @param string $mapping * @param string $mapping
* @param int $idx * @param int $idx
* @param array $special
* @return string * @return string
* @access private * @access private
*/ */
@ -965,7 +993,10 @@ class ASN1
case self::TYPE_GENERALIZED_TIME: case self::TYPE_GENERALIZED_TIME:
$format = $mapping['type'] == self::TYPE_UTC_TIME ? 'y' : 'Y'; $format = $mapping['type'] == self::TYPE_UTC_TIME ? 'y' : 'Y';
$format.= 'mdHis'; $format.= 'mdHis';
// if $source does _not_ include timezone information within it then assume that the timezone is GMT
$date = new DateTime($source, new DateTimeZone('GMT')); $date = new DateTime($source, new DateTimeZone('GMT'));
// if $source _does_ include timezone information within it then convert the time to GMT
$date->setTimezone(new DateTimeZone('GMT'));
$value = $date->format($format) . 'Z'; $value = $date->format($format) . 'Z';
break; break;
case self::TYPE_BIT_STRING: case self::TYPE_BIT_STRING:
@ -1126,6 +1157,11 @@ class ASN1
$oid = array(); $oid = array();
$pos = 0; $pos = 0;
$len = strlen($content); $len = strlen($content);
if (ord($content[$len - 1]) & 0x80) {
return false;
}
$n = new BigInteger(); $n = new BigInteger();
while ($pos < $len) { while ($pos < $len) {
$temp = ord($content[$pos++]); $temp = ord($content[$pos++]);
@ -1161,7 +1197,7 @@ class ASN1
* Called by _encode_der() * Called by _encode_der()
* *
* @access private * @access private
* @param string $content * @param string $source
* @return string * @return string
*/ */
function _encodeOID($source) function _encodeOID($source)

View File

@ -1608,7 +1608,7 @@ class X509
* Map extension values from octet string to extension-specific internal * Map extension values from octet string to extension-specific internal
* format. * format.
* *
* @param array ref $root * @param array $root (by reference)
* @param string $path * @param string $path
* @param object $asn1 * @param object $asn1
* @access private * @access private
@ -1661,7 +1661,7 @@ class X509
* Map extension values from extension-specific internal format to * Map extension values from extension-specific internal format to
* octet string. * octet string.
* *
* @param array ref $root * @param array $root (by reference)
* @param string $path * @param string $path
* @param object $asn1 * @param object $asn1
* @access private * @access private
@ -1727,7 +1727,7 @@ class X509
* Map attribute values from ANY type to attribute-specific internal * Map attribute values from ANY type to attribute-specific internal
* format. * format.
* *
* @param array ref $root * @param array $root (by reference)
* @param string $path * @param string $path
* @param object $asn1 * @param object $asn1
* @access private * @access private
@ -1768,7 +1768,7 @@ class X509
* Map attribute values from attribute-specific internal format to * Map attribute values from attribute-specific internal format to
* ANY type. * ANY type.
* *
* @param array ref $root * @param array $root (by reference)
* @param string $path * @param string $path
* @param object $asn1 * @param object $asn1
* @access private * @access private
@ -1811,7 +1811,7 @@ class X509
* Map DN values from ANY type to DN-specific internal * Map DN values from ANY type to DN-specific internal
* format. * format.
* *
* @param array ref $root * @param array $root (by reference)
* @param string $path * @param string $path
* @param object $asn1 * @param object $asn1
* @access private * @access private
@ -1841,7 +1841,7 @@ class X509
* Map DN values from DN-specific internal format to * Map DN values from DN-specific internal format to
* ANY type. * ANY type.
* *
* @param array ref $root * @param array $root (by reference)
* @param string $path * @param string $path
* @param object $asn1 * @param object $asn1
* @access private * @access private
@ -3195,7 +3195,8 @@ class X509
/** /**
* Load a Certificate Signing Request * Load a Certificate Signing Request
* *
* @param string $csr * @param string|array $csr
* @param int $mode
* @access public * @access public
* @return mixed * @return mixed
*/ */
@ -3332,7 +3333,7 @@ class X509
* *
* https://developer.mozilla.org/en-US/docs/HTML/Element/keygen * https://developer.mozilla.org/en-US/docs/HTML/Element/keygen
* *
* @param string $csr * @param string|array $spkac
* @access public * @access public
* @return mixed * @return mixed
*/ */
@ -3403,7 +3404,7 @@ class X509
/** /**
* Save a SPKAC CSR request * Save a SPKAC CSR request
* *
* @param array $csr * @param string|array $spkac
* @param int $format optional * @param int $format optional
* @access public * @access public
* @return string * @return string
@ -3447,6 +3448,7 @@ class X509
* Load a Certificate Revocation List * Load a Certificate Revocation List
* *
* @param string $crl * @param string $crl
* @param int $mode
* @access public * @access public
* @return mixed * @return mixed
*/ */
@ -4043,8 +4045,7 @@ class X509
/** /**
* X.509 certificate signing helper function. * X.509 certificate signing helper function.
* *
* @param object $key * @param \phpseclib\File\X509 $key
* @param \phpseclib\File\X509 $subject
* @param string $signatureAlgorithm * @param string $signatureAlgorithm
* @access public * @access public
* @return mixed * @return mixed
@ -4119,7 +4120,7 @@ class X509
* Set Serial Number * Set Serial Number
* *
* @param string $serial * @param string $serial
* @param $base optional * @param int $base optional
* @access public * @access public
*/ */
function setSerialNumber($serial, $base = -256) function setSerialNumber($serial, $base = -256)
@ -4782,7 +4783,6 @@ class X509
* Set the IP Addresses's which the cert is to be valid for * Set the IP Addresses's which the cert is to be valid for
* *
* @access public * @access public
* @param string $ipAddress optional
*/ */
function setIPAddress() function setIPAddress()
{ {
@ -5054,11 +5054,16 @@ class X509
* subject=/O=organization/OU=org unit/CN=common name * subject=/O=organization/OU=org unit/CN=common name
* issuer=/O=organization/CN=common name * issuer=/O=organization/CN=common name
*/ */
if (strlen($str) > ini_get('pcre.backtrack_limit')) {
$temp = $str;
} else {
$temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1); $temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1);
// remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff $temp = preg_replace('#-+END.*[\r\n ]*.*#ms', '', $temp, 1);
$temp = preg_replace('#-+[^-]+-+#', '', $temp); }
// remove new lines // remove new lines
$temp = str_replace(array("\r", "\n", ' '), '', $temp); $temp = str_replace(array("\r", "\n", ' '), '', $temp);
// remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff
$temp = preg_replace('#^-+[^-]+-+|-+[^-]+-+$#', '', $temp);
$temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false; $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
return $temp != false ? $temp : $str; return $temp != false ? $temp : $str;
} }

View File

@ -243,7 +243,7 @@ class BigInteger
* ?> * ?>
* </code> * </code>
* *
* @param $x base-10 number or base-$base number if $base set. * @param int|string|resource $x base-10 number or base-$base number if $base set.
* @param int $base * @param int $base
* @return \phpseclib\Math\BigInteger * @return \phpseclib\Math\BigInteger
* @access public * @access public
@ -658,11 +658,11 @@ class BigInteger
{ {
$hex = $this->toHex($twos_compliment); $hex = $this->toHex($twos_compliment);
$bits = ''; $bits = '';
for ($i = strlen($hex) - 8, $start = strlen($hex) & 7; $i >= $start; $i-=8) { for ($i = strlen($hex) - 6, $start = strlen($hex) % 6; $i >= $start; $i-=6) {
$bits = str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT) . $bits; $bits = str_pad(decbin(hexdec(substr($hex, $i, 6))), 24, '0', STR_PAD_LEFT) . $bits;
} }
if ($start) { // hexdec('') == 0 if ($start) { // hexdec('') == 0
$bits = str_pad(decbin(hexdec(substr($hex, 0, $start))), 8, '0', STR_PAD_LEFT) . $bits; $bits = str_pad(decbin(hexdec(substr($hex, 0, $start))), 8 * $start, '0', STR_PAD_LEFT) . $bits;
} }
$result = $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0'); $result = $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0');
@ -1994,7 +1994,7 @@ class BigInteger
* *
* @see self::_slidingWindow() * @see self::_slidingWindow()
* @access private * @access private
* @param \phpseclib\Math\BigInteger * @param \phpseclib\Math\BigInteger $n
* @return \phpseclib\Math\BigInteger * @return \phpseclib\Math\BigInteger
*/ */
function _mod2($n) function _mod2($n)
@ -2688,7 +2688,7 @@ class BigInteger
* Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y). * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y).
* *
* @param \phpseclib\Math\BigInteger $y * @param \phpseclib\Math\BigInteger $y
* @return int < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal. * @return int that is < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
* @access public * @access public
* @see self::equals() * @see self::equals()
* @internal Could return $this->subtract($x), but that's not as fast as what we do do. * @internal Could return $this->subtract($x), but that's not as fast as what we do do.
@ -3090,7 +3090,7 @@ class BigInteger
* *
* Byte length is equal to $length. Uses \phpseclib\Crypt\Random if it's loaded and mt_rand if it's not. * Byte length is equal to $length. Uses \phpseclib\Crypt\Random if it's loaded and mt_rand if it's not.
* *
* @param int $length * @param int $size
* @return \phpseclib\Math\BigInteger * @return \phpseclib\Math\BigInteger
* @access private * @access private
*/ */
@ -3557,7 +3557,7 @@ class BigInteger
* *
* Removes leading zeros and truncates (if necessary) to maintain the appropriate precision * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision
* *
* @param \phpseclib\Math\BigInteger * @param \phpseclib\Math\BigInteger $result
* @return \phpseclib\Math\BigInteger * @return \phpseclib\Math\BigInteger
* @see self::_trim() * @see self::_trim()
* @access private * @access private
@ -3634,8 +3634,8 @@ class BigInteger
/** /**
* Array Repeat * Array Repeat
* *
* @param $input Array * @param array $input
* @param $multiplier mixed * @param mixed $multiplier
* @return array * @return array
* @access private * @access private
*/ */
@ -3649,8 +3649,8 @@ class BigInteger
* *
* Shifts binary strings $shift bits, essentially multiplying by 2**$shift. * Shifts binary strings $shift bits, essentially multiplying by 2**$shift.
* *
* @param $x String * @param string $x (by reference)
* @param $shift Integer * @param int $shift
* @return string * @return string
* @access private * @access private
*/ */
@ -3678,8 +3678,8 @@ class BigInteger
* *
* Shifts binary strings $shift bits, essentially dividing by 2**$shift and returning the remainder. * Shifts binary strings $shift bits, essentially dividing by 2**$shift and returning the remainder.
* *
* @param $x String * @param string $x (by referenc)
* @param $shift Integer * @param int $shift
* @return string * @return string
* @access private * @access private
*/ */

View File

@ -259,6 +259,26 @@ class SFTP extends SSH2
*/ */
var $requestBuffer = array(); var $requestBuffer = array();
/**
* Preserve timestamps on file downloads / uploads
*
* @see self::get()
* @see self::put()
* @var bool
* @access private
*/
var $preserveTime = false;
/**
* Was the last packet due to the channels being closed or not?
*
* @see self::get()
* @see self::get_sftp_packet()
* @var bool
* @access private
*/
var $channel_close = false;
/** /**
* Default Constructor. * Default Constructor.
* *
@ -406,7 +426,6 @@ class SFTP extends SSH2
* Login * Login
* *
* @param string $username * @param string $username
* @param string $password
* @return bool * @return bool
* @access public * @access public
*/ */
@ -416,6 +435,17 @@ class SFTP extends SSH2
return false; return false;
} }
return $this->_init_sftp_connection();
}
/**
* (Re)initializes the SFTP channel
*
* @return bool
* @access private
*/
function _init_sftp_connection()
{
$this->window_size_server_to_client[self::CHANNEL] = $this->window_size; $this->window_size_server_to_client[self::CHANNEL] = $this->window_size;
$packet = pack( $packet = pack(
@ -719,7 +749,7 @@ class SFTP extends SSH2
} }
} }
if ($path[0] != '/') { if (!strlen($path) || $path[0] != '/') {
$path = $this->pwd . '/' . $path; $path = $this->pwd . '/' . $path;
} }
@ -1015,7 +1045,7 @@ class SFTP extends SSH2
uasort($contents, array(&$this, '_comparator')); uasort($contents, array(&$this, '_comparator'));
} }
return $raw ? $contents : array_keys($contents); return $raw ? $contents : array_map('strval', array_keys($contents));
} }
/** /**
@ -1198,6 +1228,9 @@ class SFTP extends SSH2
$temp = &$this->stat_cache; $temp = &$this->stat_cache;
$max = count($dirs) - 1; $max = count($dirs) - 1;
foreach ($dirs as $i => $dir) { foreach ($dirs as $i => $dir) {
if (!is_array($temp)) {
return false;
}
if ($i === $max) { if ($i === $max) {
unset($temp[$dir]); unset($temp[$dir]);
return true; return true;
@ -1214,7 +1247,7 @@ class SFTP extends SSH2
* *
* Mainly used by file_exists * Mainly used by file_exists
* *
* @param string $dir * @param string $path
* @return mixed * @return mixed
* @access private * @access private
*/ */
@ -1224,6 +1257,9 @@ class SFTP extends SSH2
$temp = &$this->stat_cache; $temp = &$this->stat_cache;
foreach ($dirs as $dir) { foreach ($dirs as $dir) {
if (!is_array($temp)) {
return null;
}
if (!isset($temp[$dir])) { if (!isset($temp[$dir])) {
return null; return null;
} }
@ -1766,6 +1802,8 @@ class SFTP extends SSH2
* Creates a directory. * Creates a directory.
* *
* @param string $dir * @param string $dir
* @param int $mode
* @param bool $recursive
* @return bool * @return bool
* @access public * @access public
*/ */
@ -1798,6 +1836,7 @@ class SFTP extends SSH2
* Helper function for directory creation * Helper function for directory creation
* *
* @param string $dir * @param string $dir
* @param int $mode
* @return bool * @return bool
* @access private * @access private
*/ */
@ -2018,8 +2057,8 @@ class SFTP extends SSH2
$sent = 0; $sent = 0;
$size = $size < 0 ? ($size & 0x7FFFFFFF) + 0x80000000 : $size; $size = $size < 0 ? ($size & 0x7FFFFFFF) + 0x80000000 : $size;
$sftp_packet_size = 4096; // PuTTY uses 4096 $sftp_packet_size = $this->max_sftp_packet;
// make the SFTP packet be exactly 4096 bytes by including the bytes in the NET_SFTP_WRITE packets "header" // make the SFTP packet be exactly the SFTP packet size by including the bytes in the NET_SFTP_WRITE packets "header"
$sftp_packet_size-= strlen($handle) + 25; $sftp_packet_size-= strlen($handle) + 25;
$i = $j = 0; $i = $j = 0;
while ($dataCallback || ($size === 0 || $sent < $size)) { while ($dataCallback || ($size === 0 || $sent < $size)) {
@ -2069,8 +2108,15 @@ class SFTP extends SSH2
} }
if ($mode & self::SOURCE_LOCAL_FILE) { if ($mode & self::SOURCE_LOCAL_FILE) {
if ($this->preserveTime) {
$stat = fstat($fp);
$this->touch($remote_file, $stat['mtime'], $stat['atime']);
}
if (isset($fp) && is_resource($fp)) {
fclose($fp); fclose($fp);
} }
}
return $this->_close_handle($handle); return $this->_close_handle($handle);
} }
@ -2192,7 +2238,7 @@ class SFTP extends SSH2
$res_offset = $stat['size']; $res_offset = $stat['size'];
} else { } else {
$res_offset = 0; $res_offset = 0;
if ($local_file !== false) { if ($local_file !== false && !is_callable($local_file)) {
$fp = fopen($local_file, 'wb'); $fp = fopen($local_file, 'wb');
if (!$fp) { if (!$fp) {
return false; return false;
@ -2202,7 +2248,7 @@ class SFTP extends SSH2
} }
} }
$fclose_check = $local_file !== false && !is_resource($local_file); $fclose_check = $local_file !== false && !is_callable($local_file) && !is_resource($local_file);
$start = $offset; $start = $offset;
$read = 0; $read = 0;
@ -2223,9 +2269,6 @@ class SFTP extends SSH2
} }
$packet = null; $packet = null;
$read+= $packet_size; $read+= $packet_size;
if (is_callable($progressCallback)) {
call_user_func($progressCallback, $read);
}
$i++; $i++;
} }
@ -2252,9 +2295,14 @@ class SFTP extends SSH2
$offset+= strlen($temp); $offset+= strlen($temp);
if ($local_file === false) { if ($local_file === false) {
$content.= $temp; $content.= $temp;
} elseif (is_callable($local_file)) {
$local_file($temp);
} else { } else {
fputs($fp, $temp); fputs($fp, $temp);
} }
if (is_callable($progressCallback)) {
call_user_func($progressCallback, $offset);
}
$temp = null; $temp = null;
break; break;
case NET_SFTP_STATUS: case NET_SFTP_STATUS:
@ -2266,8 +2314,14 @@ class SFTP extends SSH2
if ($fclose_check) { if ($fclose_check) {
fclose($fp); fclose($fp);
} }
// maybe the file was successfully transferred, maybe it wasn't
if ($this->channel_close) {
$this->_init_sftp_connection();
return false;
} else {
user_error('Expected SSH_FX_DATA or SSH_FXP_STATUS'); user_error('Expected SSH_FX_DATA or SSH_FXP_STATUS');
} }
}
$response = null; $response = null;
} }
@ -2286,6 +2340,11 @@ class SFTP extends SSH2
if ($fclose_check) { if ($fclose_check) {
fclose($fp); fclose($fp);
if ($this->preserveTime) {
$stat = $this->stat($remote_file);
touch($local_file, $stat['mtime'], $stat['atime']);
}
} }
if (!$this->_close_handle($handle)) { if (!$this->_close_handle($handle)) {
@ -2707,6 +2766,7 @@ class SFTP extends SSH2
* *
* @param string $path * @param string $path
* @param string $prop * @param string $prop
* @param mixed $type
* @return mixed * @return mixed
* @access private * @access private
*/ */
@ -2947,6 +3007,7 @@ class SFTP extends SSH2
* *
* @param int $type * @param int $type
* @param string $data * @param string $data
* @param int $request_id
* @see self::_get_sftp_packet() * @see self::_get_sftp_packet()
* @see self::_send_channel_packet() * @see self::_send_channel_packet()
* @return bool * @return bool
@ -2954,6 +3015,10 @@ class SFTP extends SSH2
*/ */
function _send_sftp_packet($type, $data, $request_id = 1) function _send_sftp_packet($type, $data, $request_id = 1)
{ {
// in SSH2.php the timeout is cumulative per function call. eg. exec() will
// timeout after 10s. but for SFTP.php it's cumulative per packet
$this->curTimeout = $this->timeout;
$packet = $this->use_request_id ? $packet = $this->use_request_id ?
pack('NCNa*', strlen($data) + 5, $type, $request_id, $data) : pack('NCNa*', strlen($data) + 5, $type, $request_id, $data) :
pack('NCa*', strlen($data) + 1, $type, $data); pack('NCa*', strlen($data) + 1, $type, $data);
@ -2966,9 +3031,17 @@ class SFTP extends SSH2
$packet_type = '-> ' . $this->packet_types[$type] . $packet_type = '-> ' . $this->packet_types[$type] .
' (' . round($stop - $start, 4) . 's)'; ' (' . round($stop - $start, 4) . 's)';
if (NET_SFTP_LOGGING == self::LOG_REALTIME) { if (NET_SFTP_LOGGING == self::LOG_REALTIME) {
echo "<pre>\r\n" . $this->_format_log(array($data), array($packet_type)) . "\r\n</pre>\r\n"; switch (PHP_SAPI) {
flush(); case 'cli':
ob_flush(); $start = $stop = "\r\n";
break;
default:
$start = '<pre>';
$stop = '</pre>';
}
echo $start . $this->_format_log(array($data), array($packet_type)) . $stop;
@flush();
@ob_flush();
} else { } else {
$this->packet_type_log[] = $packet_type; $this->packet_type_log[] = $packet_type;
if (NET_SFTP_LOGGING == self::LOG_COMPLEX) { if (NET_SFTP_LOGGING == self::LOG_COMPLEX) {
@ -3009,6 +3082,8 @@ class SFTP extends SSH2
*/ */
function _get_sftp_packet($request_id = null) function _get_sftp_packet($request_id = null)
{ {
$this->channel_close = false;
if (isset($request_id) && isset($this->requestBuffer[$request_id])) { if (isset($request_id) && isset($this->requestBuffer[$request_id])) {
$this->packet_type = $this->requestBuffer[$request_id]['packet_type']; $this->packet_type = $this->requestBuffer[$request_id]['packet_type'];
$temp = $this->requestBuffer[$request_id]['packet']; $temp = $this->requestBuffer[$request_id]['packet'];
@ -3025,7 +3100,10 @@ class SFTP extends SSH2
// SFTP packet length // SFTP packet length
while (strlen($this->packet_buffer) < 4) { while (strlen($this->packet_buffer) < 4) {
$temp = $this->_get_channel_packet(self::CHANNEL, true); $temp = $this->_get_channel_packet(self::CHANNEL, true);
if (is_bool($temp)) { if ($temp === true) {
if ($this->channel_status[self::CHANNEL] === NET_SSH2_MSG_CHANNEL_CLOSE) {
$this->channel_close = true;
}
$this->packet_type = false; $this->packet_type = false;
$this->packet_buffer = ''; $this->packet_buffer = '';
return false; return false;
@ -3075,9 +3153,17 @@ class SFTP extends SSH2
$packet_type = '<- ' . $this->packet_types[$this->packet_type] . $packet_type = '<- ' . $this->packet_types[$this->packet_type] .
' (' . round($stop - $start, 4) . 's)'; ' (' . round($stop - $start, 4) . 's)';
if (NET_SFTP_LOGGING == self::LOG_REALTIME) { if (NET_SFTP_LOGGING == self::LOG_REALTIME) {
echo "<pre>\r\n" . $this->_format_log(array($packet), array($packet_type)) . "\r\n</pre>\r\n"; switch (PHP_SAPI) {
flush(); case 'cli':
ob_flush(); $start = $stop = "\r\n";
break;
default:
$start = '<pre>';
$stop = '</pre>';
}
echo $start . $this->_format_log(array($packet), array($packet_type)) . $stop;
@flush();
@ob_flush();
} else { } else {
$this->packet_type_log[] = $packet_type; $this->packet_type_log[] = $packet_type;
if (NET_SFTP_LOGGING == self::LOG_COMPLEX) { if (NET_SFTP_LOGGING == self::LOG_COMPLEX) {
@ -3170,4 +3256,24 @@ class SFTP extends SSH2
$this->pwd = false; $this->pwd = false;
parent::_disconnect($reason); parent::_disconnect($reason);
} }
/**
* Enable Date Preservation
*
* @access public
*/
function enableDatePreservation()
{
$this->preserveTime = true;
}
/**
* Disable Date Preservation
*
* @access public
*/
function disableDatePreservation()
{
$this->preserveTime = false;
}
} }

View File

@ -410,7 +410,7 @@ class Stream
{ {
switch ($whence) { switch ($whence) {
case SEEK_SET: case SEEK_SET:
if ($offset >= $this->size || $offset < 0) { if ($offset < 0) {
return false; return false;
} }
break; break;
@ -447,7 +447,9 @@ class Stream
// and https://github.com/php/php-src/blob/master/main/php_streams.h#L592 // and https://github.com/php/php-src/blob/master/main/php_streams.h#L592
switch ($option) { switch ($option) {
case 1: // PHP_STREAM_META_TOUCH case 1: // PHP_STREAM_META_TOUCH
return $this->sftp->touch($path, $var[0], $var[1]); $time = isset($var[0]) ? $var[0] : null;
$atime = isset($var[1]) ? $var[1] : null;
return $this->sftp->touch($path, $time, $atime);
case 2: // PHP_STREAM_OWNER_NAME case 2: // PHP_STREAM_OWNER_NAME
case 3: // PHP_STREAM_GROUP_NAME case 3: // PHP_STREAM_GROUP_NAME
return false; return false;
@ -626,7 +628,6 @@ class Stream
* $options. What does 8 correspond to? * $options. What does 8 correspond to?
* *
* @param string $path * @param string $path
* @param int $mode
* @param int $options * @param int $options
* @return bool * @return bool
* @access public * @access public
@ -768,8 +769,8 @@ class Stream
* If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not * If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not
* NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method. * NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method.
* *
* @param string * @param string $name
* @param array * @param array $arguments
* @return mixed * @return mixed
* @access public * @access public
*/ */

View File

@ -812,6 +812,7 @@ class SSH1
* @see self::interactiveRead() * @see self::interactiveRead()
* @see self::interactiveWrite() * @see self::interactiveWrite()
* @param string $cmd * @param string $cmd
* @param bool $block
* @return mixed * @return mixed
* @access public * @access public
*/ */
@ -1385,7 +1386,6 @@ class SSH1
* named constants from it, using the value as the name of the constant and the index as the value of the constant. * named constants from it, using the value as the name of the constant and the index as the value of the constant.
* If any of the constants that would be defined already exists, none of the constants will be defined. * If any of the constants that would be defined already exists, none of the constants will be defined.
* *
* @param array $array
* @access private * @access private
*/ */
function _define_array() function _define_array()
@ -1584,7 +1584,8 @@ class SSH1
* *
* Makes sure that only the last 1MB worth of packets will be logged * Makes sure that only the last 1MB worth of packets will be logged
* *
* @param string $data * @param int $protocol_flags
* @param string $message
* @access private * @access private
*/ */
function _append_log($protocol_flags, $message) function _append_log($protocol_flags, $message)

View File

@ -687,6 +687,14 @@ class SSH2
*/ */
var $curTimeout; var $curTimeout;
/**
* Keep Alive Interval
*
* @see self::setKeepAlive()
* @access private
*/
var $keepAlive;
/** /**
* Real-time log file pointer * Real-time log file pointer
* *
@ -962,6 +970,14 @@ class SSH2
*/ */
var $auth = array(); var $auth = array();
/**
* The authentication methods that may productively continue authentication.
*
* @see https://tools.ietf.org/html/rfc4252#section-5.1
* @var array|null
*/
private $auth_methods_to_continue = null;
/** /**
* Default Constructor. * Default Constructor.
* *
@ -1339,6 +1355,7 @@ class SSH2
function _key_exchange($kexinit_payload_server = false) function _key_exchange($kexinit_payload_server = false)
{ {
$preferred = $this->preferred; $preferred = $this->preferred;
$send_kex = true;
$kex_algorithms = isset($preferred['kex']) ? $kex_algorithms = isset($preferred['kex']) ?
$preferred['kex'] : $preferred['kex'] :
@ -1422,7 +1439,7 @@ class SSH2
0 0
); );
if ($this->send_kex_first) { if ($kexinit_payload_server === false) {
if (!$this->_send_binary_packet($kexinit_payload_client)) { if (!$this->_send_binary_packet($kexinit_payload_client)) {
return false; return false;
} }
@ -1438,6 +1455,8 @@ class SSH2
user_error('Expected SSH_MSG_KEXINIT'); user_error('Expected SSH_MSG_KEXINIT');
return false; return false;
} }
$send_kex = false;
} }
$response = $kexinit_payload_server; $response = $kexinit_payload_server;
@ -1510,7 +1529,7 @@ class SSH2
extract(unpack('Cfirst_kex_packet_follows', $this->_string_shift($response, 1))); extract(unpack('Cfirst_kex_packet_follows', $this->_string_shift($response, 1)));
$first_kex_packet_follows = $first_kex_packet_follows != 0; $first_kex_packet_follows = $first_kex_packet_follows != 0;
if (!$this->send_kex_first && !$this->_send_binary_packet($kexinit_payload_client)) { if ($send_kex && !$this->_send_binary_packet($kexinit_payload_client)) {
return false; return false;
} }
@ -1538,6 +1557,32 @@ class SSH2
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
$server_host_key_algorithm = $this->_array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms);
if ($server_host_key_algorithm === false) {
user_error('No compatible server host key algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
$mac_algorithm_in = $this->_array_intersect_first($s2c_mac_algorithms, $this->mac_algorithms_server_to_client);
if ($mac_algorithm_in === false) {
user_error('No compatible server to client message authentication algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
$compression_algorithm_out = $this->_array_intersect_first($c2s_compression_algorithms, $this->compression_algorithms_client_to_server);
if ($compression_algorithm_out === false) {
user_error('No compatible client to server compression algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
//$this->decompress = $compression_algorithm_out == 'zlib';
$compression_algorithm_in = $this->_array_intersect_first($s2c_compression_algorithms, $this->compression_algorithms_client_to_server);
if ($compression_algorithm_in === false) {
user_error('No compatible server to client compression algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
//$this->compress = $compression_algorithm_in == 'zlib';
// 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 = '';
@ -1773,12 +1818,6 @@ class SSH2
$this->session_id = $this->exchange_hash; $this->session_id = $this->exchange_hash;
} }
$server_host_key_algorithm = $this->_array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms);
if ($server_host_key_algorithm === false) {
user_error('No compatible server host key algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
switch ($server_host_key_algorithm) { switch ($server_host_key_algorithm) {
case 'ssh-dss': case 'ssh-dss':
$expected_key_format = 'ssh-dss'; $expected_key_format = 'ssh-dss';
@ -1903,14 +1942,14 @@ class SSH2
$this->decrypt->decrypt(str_repeat("\0", 1536)); $this->decrypt->decrypt(str_repeat("\0", 1536));
} }
$mac_algorithm = $this->_array_intersect_first($c2s_mac_algorithms, $this->mac_algorithms_client_to_server); $mac_algorithm_out = $this->_array_intersect_first($c2s_mac_algorithms, $this->mac_algorithms_client_to_server);
if ($mac_algorithm === false) { if ($mac_algorithm_out === false) {
user_error('No compatible client to server message authentication algorithms found'); user_error('No compatible client to server message authentication algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
$createKeyLength = 0; // ie. $mac_algorithm == 'none' $createKeyLength = 0; // ie. $mac_algorithm == 'none'
switch ($mac_algorithm) { switch ($mac_algorithm_out) {
case 'hmac-sha2-256': case 'hmac-sha2-256':
$this->hmac_create = new Hash('sha256'); $this->hmac_create = new Hash('sha256');
$createKeyLength = 32; $createKeyLength = 32;
@ -1931,17 +1970,11 @@ class SSH2
$this->hmac_create = new Hash('md5-96'); $this->hmac_create = new Hash('md5-96');
$createKeyLength = 16; $createKeyLength = 16;
} }
$this->hmac_create->name = $mac_algorithm; $this->hmac_create->name = $mac_algorithm_out;
$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);
}
$checkKeyLength = 0; $checkKeyLength = 0;
$this->hmac_size = 0; $this->hmac_size = 0;
switch ($mac_algorithm) { switch ($mac_algorithm_in) {
case 'hmac-sha2-256': case 'hmac-sha2-256':
$this->hmac_check = new Hash('sha256'); $this->hmac_check = new Hash('sha256');
$checkKeyLength = 32; $checkKeyLength = 32;
@ -1967,7 +2000,7 @@ class SSH2
$checkKeyLength = 16; $checkKeyLength = 16;
$this->hmac_size = 12; $this->hmac_size = 12;
} }
$this->hmac_check->name = $mac_algorithm; $this->hmac_check->name = $mac_algorithm_in;
$key = $kexHash->hash($keyBytes . $this->exchange_hash . 'E' . $this->session_id); $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'E' . $this->session_id);
while ($createKeyLength > strlen($key)) { while ($createKeyLength > strlen($key)) {
@ -1981,20 +2014,6 @@ class SSH2
} }
$this->hmac_check->setKey(substr($key, 0, $checkKeyLength)); $this->hmac_check->setKey(substr($key, 0, $checkKeyLength));
$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->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; return true;
} }
@ -2112,8 +2131,6 @@ class SSH2
* The $password parameter can be a plaintext password, a \phpseclib\Crypt\RSA object or an array * The $password parameter can be a plaintext password, a \phpseclib\Crypt\RSA object or an array
* *
* @param string $username * @param string $username
* @param mixed $password
* @param mixed $...
* @return bool * @return bool
* @see self::_login() * @see self::_login()
* @access public * @access public
@ -2125,12 +2142,14 @@ class SSH2
// try logging with 'none' as an authentication method first since that's what // try logging with 'none' as an authentication method first since that's what
// PuTTY does // PuTTY does
if (substr($this->server_identifier, 0, 13) != 'SSH-2.0-CoreFTP' && $this->auth_methods_to_continue === null) {
if ($this->_login($username)) { if ($this->_login($username)) {
return true; return true;
} }
if (count($args) == 1) { if (count($args) == 1) {
return false; return false;
} }
}
return call_user_func_array(array(&$this, '_login'), $args); return call_user_func_array(array(&$this, '_login'), $args);
} }
@ -2138,8 +2157,6 @@ class SSH2
* Login Helper * Login Helper
* *
* @param string $username * @param string $username
* @param mixed $password
* @param mixed $...
* @return bool * @return bool
* @see self::_login_helper() * @see self::_login_helper()
* @access private * @access private
@ -2269,7 +2286,9 @@ class SSH2
case NET_SSH2_MSG_USERAUTH_SUCCESS: case NET_SSH2_MSG_USERAUTH_SUCCESS:
$this->bitmap |= self::MASK_LOGIN; $this->bitmap |= self::MASK_LOGIN;
return true; return true;
//case NET_SSH2_MSG_USERAUTH_FAILURE: case NET_SSH2_MSG_USERAUTH_FAILURE:
extract(unpack('Nmethodlistlen', $this->_string_shift($response, 4)));
$this->auth_methods_to_continue = explode(',', $this->_string_shift($response, $methodlistlen));
default: default:
return false; return false;
} }
@ -2341,6 +2360,7 @@ class SSH2
} }
extract(unpack('Nlength', $this->_string_shift($response, 4))); extract(unpack('Nlength', $this->_string_shift($response, 4)));
$auth_methods = explode(',', $this->_string_shift($response, $length)); $auth_methods = explode(',', $this->_string_shift($response, $length));
$this->auth_methods_to_continue = $auth_methods;
if (!strlen($response)) { if (!strlen($response)) {
return false; return false;
} }
@ -2400,7 +2420,6 @@ class SSH2
/** /**
* Handle the keyboard-interactive requests / responses. * Handle the keyboard-interactive requests / responses.
* *
* @param string $responses...
* @return bool * @return bool
* @access private * @access private
*/ */
@ -2514,6 +2533,8 @@ class SSH2
case NET_SSH2_MSG_USERAUTH_SUCCESS: case NET_SSH2_MSG_USERAUTH_SUCCESS:
return true; return true;
case NET_SSH2_MSG_USERAUTH_FAILURE: case NET_SSH2_MSG_USERAUTH_FAILURE:
extract(unpack('Nmethodlistlen', $this->_string_shift($response, 4)));
$this->auth_methods_to_continue = explode(',', $this->_string_shift($response, $methodlistlen));
return false; return false;
} }
@ -2545,7 +2566,7 @@ class SSH2
* Login with an RSA private key * Login with an RSA private key
* *
* @param string $username * @param string $username
* @param \phpseclib\Crypt\RSA $password * @param \phpseclib\Crypt\RSA $privatekey
* @return bool * @return bool
* @access private * @access private
* @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis} * @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
@ -2622,13 +2643,21 @@ class SSH2
if (strlen($response) < 4) { if (strlen($response) < 4) {
return false; return false;
} }
extract(unpack('Nlength', $this->_string_shift($response, 4))); extract(unpack('Nmethodlistlen', $this->_string_shift($response, 4)));
$this->errors[] = 'SSH_MSG_USERAUTH_FAILURE: ' . $this->_string_shift($response, $length); $this->auth_methods_to_continue = explode(',', $this->_string_shift($response, $methodlistlen));
$this->errors[] = 'SSH_MSG_USERAUTH_FAILURE';
return false; return false;
case NET_SSH2_MSG_USERAUTH_PK_OK: case NET_SSH2_MSG_USERAUTH_PK_OK:
// we'll just take it on faith that the public key blob and the public key algorithm name are as // we'll just take it on faith that the public key blob and the public key algorithm name are as
// they should be // they should be
$this->_updateLogHistory('UNKNOWN (60)', 'NET_SSH2_MSG_USERAUTH_PK_OK'); $this->_updateLogHistory('UNKNOWN (60)', 'NET_SSH2_MSG_USERAUTH_PK_OK');
break;
case NET_SSH2_MSG_USERAUTH_SUCCESS:
$this->bitmap |= self::MASK_LOGIN;
return true;
default:
user_error('Unexpected response to publickey authentication pt 1');
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
} }
$packet = $part1 . chr(1) . $part2; $packet = $part1 . chr(1) . $part2;
@ -2657,13 +2686,16 @@ class SSH2
switch ($type) { switch ($type) {
case NET_SSH2_MSG_USERAUTH_FAILURE: case NET_SSH2_MSG_USERAUTH_FAILURE:
// either the login is bad or the server employs multi-factor authentication // either the login is bad or the server employs multi-factor authentication
extract(unpack('Nmethodlistlen', $this->_string_shift($response, 4)));
$this->auth_methods_to_continue = explode(',', $this->_string_shift($response, $methodlistlen));
return false; return false;
case NET_SSH2_MSG_USERAUTH_SUCCESS: case NET_SSH2_MSG_USERAUTH_SUCCESS:
$this->bitmap |= self::MASK_LOGIN; $this->bitmap |= self::MASK_LOGIN;
return true; return true;
} }
return false; user_error('Unexpected response to publickey authentication pt 2');
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
} }
/** /**
@ -2680,6 +2712,19 @@ class SSH2
$this->timeout = $this->curTimeout = $timeout; $this->timeout = $this->curTimeout = $timeout;
} }
/**
* Set Keep Alive
*
* Sends an SSH2_MSG_IGNORE message every x seconds, if x is a positive non-zero number.
*
* @param int $interval
* @access public
*/
function setKeepAlive($interval)
{
$this->keepAlive = $interval;
}
/** /**
* Get the output from stdError * Get the output from stdError
* *
@ -2909,28 +2954,6 @@ class SSH2
return false; return false;
} }
$response = $this->_get_binary_packet();
if ($response === false) {
$this->bitmap = 0;
user_error('Connection closed by server');
return false;
}
if (!strlen($response)) {
return false;
}
list(, $type) = unpack('C', $this->_string_shift($response, 1));
switch ($type) {
case NET_SSH2_MSG_CHANNEL_SUCCESS:
// if a pty can't be opened maybe commands can still be executed
case NET_SSH2_MSG_CHANNEL_FAILURE:
break;
default:
user_error('Unable to request pseudo-terminal');
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
}
$packet = pack( $packet = pack(
'CNNa*C', 'CNNa*C',
NET_SSH2_MSG_CHANNEL_REQUEST, NET_SSH2_MSG_CHANNEL_REQUEST,
@ -2943,14 +2966,7 @@ class SSH2
return false; return false;
} }
$this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_REQUEST; $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_IGNORE;
$response = $this->_get_channel_packet(self::CHANNEL_SHELL);
if ($response === false) {
return false;
}
$this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_DATA;
$this->bitmap |= self::MASK_SHELL; $this->bitmap |= self::MASK_SHELL;
@ -3004,7 +3020,7 @@ class SSH2
* @see self::write() * @see self::write()
* @param string $expect * @param string $expect
* @param int $mode * @param int $mode
* @return string * @return string|bool
* @access public * @access public
*/ */
function read($expect = '', $mode = self::READ_SIMPLE) function read($expect = '', $mode = self::READ_SIMPLE)
@ -3318,6 +3334,54 @@ class SSH2
*/ */
function _get_binary_packet($skip_channel_filter = false) function _get_binary_packet($skip_channel_filter = false)
{ {
if ($skip_channel_filter) {
$read = array($this->fsock);
$write = $except = null;
if (!$this->curTimeout) {
if ($this->keepAlive <= 0) {
@stream_select($read, $write, $except, null);
} else {
if (!@stream_select($read, $write, $except, $this->keepAlive) && !count($read)) {
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0));
return $this->_get_binary_packet(true);
}
}
} else {
if ($this->curTimeout < 0) {
$this->is_timeout = true;
return true;
}
$read = array($this->fsock);
$write = $except = null;
$start = microtime(true);
if ($this->keepAlive > 0 && $this->keepAlive < $this->curTimeout) {
if (!@stream_select($read, $write, $except, $this->keepAlive) && !count($read)) {
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0));
$elapsed = microtime(true) - $start;
$this->curTimeout-= $elapsed;
return $this->_get_binary_packet(true);
}
$elapsed = microtime(true) - $start;
$this->curTimeout-= $elapsed;
}
$sec = floor($this->curTimeout);
$usec = 1000000 * ($this->curTimeout - $sec);
// on windows this returns a "Warning: Invalid CRT parameters detected" error
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
$this->is_timeout = true;
return true;
}
$elapsed = microtime(true) - $start;
$this->curTimeout-= $elapsed;
}
}
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 prematurely'); user_error('Connection closed prematurely');
@ -3468,10 +3532,24 @@ class SSH2
// only called when we've already logged in // only called when we've already logged in
if (($this->bitmap & self::MASK_CONNECTED) && $this->isAuthenticated()) { if (($this->bitmap & self::MASK_CONNECTED) && $this->isAuthenticated()) {
if (is_bool($payload)) {
return $payload;
}
switch (ord($payload[0])) { switch (ord($payload[0])) {
case NET_SSH2_MSG_CHANNEL_REQUEST:
if (strlen($payload) == 31) {
extract(unpack('cpacket_type/Nchannel/Nlength', $payload));
if (substr($payload, 9, $length) == 'keepalive@openssh.com' && isset($this->server_channels[$channel])) {
if (ord(substr($payload, 9 + $length))) { // want reply
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_SUCCESS, $this->server_channels[$channel]));
}
$payload = $this->_get_binary_packet($skip_channel_filter);
}
}
break;
case NET_SSH2_MSG_CHANNEL_DATA: case NET_SSH2_MSG_CHANNEL_DATA:
case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA: case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
case NET_SSH2_MSG_CHANNEL_REQUEST:
case NET_SSH2_MSG_CHANNEL_CLOSE: case NET_SSH2_MSG_CHANNEL_CLOSE:
case NET_SSH2_MSG_CHANNEL_EOF: case NET_SSH2_MSG_CHANNEL_EOF:
if (!$skip_channel_filter && !empty($this->server_channels)) { if (!$skip_channel_filter && !empty($this->server_channels)) {
@ -3651,8 +3729,9 @@ class SSH2
* *
* Returns the data as a string if it's available and false if not. * Returns the data as a string if it's available and false if not.
* *
* @param $client_channel * @param int $client_channel
* @return mixed * @param bool $skip_extended
* @return mixed|bool
* @access private * @access private
*/ */
function _get_channel_packet($client_channel, $skip_extended = false) function _get_channel_packet($client_channel, $skip_extended = false)
@ -3666,36 +3745,13 @@ class SSH2
$response = $this->binary_packet_buffer; $response = $this->binary_packet_buffer;
$this->binary_packet_buffer = false; $this->binary_packet_buffer = false;
} else { } else {
$read = array($this->fsock); $response = $this->_get_binary_packet(true);
$write = $except = null; if ($response === true && $this->is_timeout) {
if (!$this->curTimeout) {
@stream_select($read, $write, $except, null);
} else {
if ($this->curTimeout < 0) {
$this->is_timeout = true;
return true;
}
$read = array($this->fsock);
$write = $except = null;
$start = microtime(true);
$sec = floor($this->curTimeout);
$usec = 1000000 * ($this->curTimeout - $sec);
// on windows this returns a "Warning: Invalid CRT parameters detected" error
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
$this->is_timeout = true;
if ($client_channel == self::CHANNEL_EXEC && !$this->request_pty) { if ($client_channel == self::CHANNEL_EXEC && !$this->request_pty) {
$this->_close_channel($client_channel); $this->_close_channel($client_channel);
} }
return true; return true;
} }
$elapsed = microtime(true) - $start;
$this->curTimeout-= $elapsed;
}
$response = $this->_get_binary_packet(true);
if ($response === false) { if ($response === false) {
$this->bitmap = 0; $this->bitmap = 0;
user_error('Connection closed by server'); user_error('Connection closed by server');
@ -3843,6 +3899,16 @@ class SSH2
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
} }
break; break;
case NET_SSH2_MSG_IGNORE:
switch ($type) {
case NET_SSH2_MSG_CHANNEL_SUCCESS:
//$this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_DATA;
continue 3;
case NET_SSH2_MSG_CHANNEL_FAILURE:
user_error('Error opening channel');
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
}
break;
case NET_SSH2_MSG_CHANNEL_REQUEST: case NET_SSH2_MSG_CHANNEL_REQUEST:
switch ($type) { switch ($type) {
case NET_SSH2_MSG_CHANNEL_SUCCESS: case NET_SSH2_MSG_CHANNEL_SUCCESS:
@ -3862,6 +3928,10 @@ class SSH2
switch ($type) { switch ($type) {
case NET_SSH2_MSG_CHANNEL_DATA: case NET_SSH2_MSG_CHANNEL_DATA:
//if ($this->channel_status[$channel] == NET_SSH2_MSG_IGNORE) {
// $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_DATA;
//}
/* /*
if ($channel == self::CHANNEL_EXEC) { if ($channel == self::CHANNEL_EXEC) {
// SCP requires null packets, such as this, be sent. further, in the case of the ssh.com SSH server // SCP requires null packets, such as this, be sent. further, in the case of the ssh.com SSH server
@ -3894,7 +3964,7 @@ class SSH2
$this->channel_buffers[$channel][] = $data; $this->channel_buffers[$channel][] = $data;
break; break;
case NET_SSH2_MSG_CHANNEL_CLOSE: case NET_SSH2_MSG_CHANNEL_CLOSE:
$this->curTimeout = 0; $this->curTimeout = 5;
if ($this->bitmap & self::MASK_SHELL) { if ($this->bitmap & self::MASK_SHELL) {
$this->bitmap&= ~self::MASK_SHELL; $this->bitmap&= ~self::MASK_SHELL;
@ -3962,7 +4032,7 @@ class SSH2
$packet.= $hmac; $packet.= $hmac;
$start = microtime(true); $start = microtime(true);
$result = strlen($packet) == fputs($this->fsock, $packet); $result = strlen($packet) == @fputs($this->fsock, $packet);
$stop = microtime(true); $stop = microtime(true);
if (defined('NET_SSH2_LOGGING')) { if (defined('NET_SSH2_LOGGING')) {
@ -3982,7 +4052,8 @@ class SSH2
* *
* Makes sure that only the last 1MB worth of packets will be logged * Makes sure that only the last 1MB worth of packets will be logged
* *
* @param string $data * @param string $message_number
* @param string $message
* @access private * @access private
*/ */
function _append_log($message_number, $message) function _append_log($message_number, $message)
@ -4123,11 +4194,15 @@ class SSH2
$this->channel_status[$client_channel] = NET_SSH2_MSG_CHANNEL_CLOSE; $this->channel_status[$client_channel] = NET_SSH2_MSG_CHANNEL_CLOSE;
$this->curTimeout = 0; $this->curTimeout = 5;
while (!is_bool($this->_get_channel_packet($client_channel))) { while (!is_bool($this->_get_channel_packet($client_channel))) {
} }
if ($this->is_timeout) {
$this->disconnect();
}
if ($want_reply) { if ($want_reply) {
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel])); $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel]));
} }
@ -4183,7 +4258,6 @@ class SSH2
* named constants from it, using the value as the name of the constant and the index as the value of the constant. * named constants from it, using the value as the name of the constant and the index as the value of the constant.
* If any of the constants that would be defined already exists, none of the constants will be defined. * If any of the constants that would be defined already exists, none of the constants will be defined.
* *
* @param array $array
* @access private * @access private
*/ */
function _define_array() function _define_array()
@ -4599,11 +4673,15 @@ class SSH2
//'none' // OPTIONAL no encryption; NOT RECOMMENDED //'none' // OPTIONAL no encryption; NOT RECOMMENDED
); );
if ($this->crypto_engine) {
$engines = array($this->crypto_engine);
} else {
$engines = array( $engines = array(
Base::ENGINE_OPENSSL, Base::ENGINE_OPENSSL,
Base::ENGINE_MCRYPT, Base::ENGINE_MCRYPT,
Base::ENGINE_INTERNAL Base::ENGINE_INTERNAL
); );
}
$ciphers = array(); $ciphers = array();
foreach ($engines as $engine) { foreach ($engines as $engine) {
@ -5088,4 +5166,15 @@ class SSH2
); );
} }
} }
/**
* Return the list of authentication methods that may productively continue authentication.
*
* @see https://tools.ietf.org/html/rfc4252#section-5.1
* @return array|null
*/
public function getAuthMethodsToContinue()
{
return $this->auth_methods_to_continue;
}
} }