diff --git a/.travis.yml b/.travis.yml index 3fb1d730..452b9a0e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,12 @@ language: php -# When adding environments here, the number of runs specified in .scrutinizer.yml -# may have to be adjusted. php: - 5.3.3 - 5.3 - 5.4 - 5.5 - 5.6 + - 7.0 - hhvm env: @@ -22,7 +21,7 @@ install: - sudo apt-get install parallel - eval `ssh-agent -s` - travis/setup-secure-shell.sh - - sh -c "if [ '$TRAVIS_PHP_VERSION' != 'hhvm' ]; then travis/install-php-extensions.sh; fi" + - sh -c "if [ '$TRAVIS_PHP_VERSION' != 'hhvm' -a '$TRAVIS_PHP_VERSION' != '7.0' ]; then travis/install-php-extensions.sh; fi" - travis/setup-composer.sh script: @@ -31,3 +30,8 @@ script: after_success: - sh -c "if $TRAVIS_SECURE_ENV_VARS; then travis/upload-code-coverage-html.sh; fi" + +matrix: + allow_failures: + - php: 7.0 + fast_finish: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 2dd2c096..f0b03dc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## 1.0.0 - 2015-08-02 + +- OpenSSL support for symmetric ciphers ([#507](https://github.com/phpseclib/phpseclib/pull/507)) +- rewritten vt100 terminal emulator (File_ANSI) ([#689](https://github.com/phpseclib/phpseclib/pull/689)) +- agent-forwarding support (System_SSH_Agent) ([#592](https://github.com/phpseclib/phpseclib/pull/592)) +- Net_SSH2 improvements + - diffie-hellman-group-exchange-sha1/sha256 support ([#714](https://github.com/phpseclib/phpseclib/pull/714)) + - window size handling updates ([#717](https://github.com/phpseclib/phpseclib/pull/717)) +- Net_SFTP improvements + - add callback support to put() ([#655](https://github.com/phpseclib/phpseclib/pull/655)) + - stat cache fixes ([#743](https://github.com/phpseclib/phpseclib/issues/743), [#730](https://github.com/phpseclib/phpseclib/issues/730), [#709](https://github.com/phpseclib/phpseclib/issues/709), [#726](https://github.com/phpseclib/phpseclib/issues/726)) +- add "none" encryption mode to Crypt_RSA ([#692](https://github.com/phpseclib/phpseclib/pull/692)) +- misc ASN.1 / X.509 parsing fixes ([#721](https://github.com/phpseclib/phpseclib/pull/721), [#627](https://github.com/phpseclib/phpseclib/pull/627)) +- use a random serial number for new X509 certs ([#740](https://github.com/phpseclib/phpseclib/pull/740)) +- add getPublicKeyFingerprint() to Crypt_RSA ([#677](https://github.com/phpseclib/phpseclib/pull/677)) + ## 0.3.10 - 2015-02-04 - simplify SSH2 window size handling ([#538](https://github.com/phpseclib/phpseclib/pull/538)) diff --git a/README.md b/README.md index bb738a57..b75a6b66 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ MIT-licensed pure-PHP implementations of an arbitrary-precision integer arithmetic library, fully PKCS#1 (v2.1) compliant RSA, DES, 3DES, RC4, Rijndael, AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509 -* [Download (0.3.10)](http://sourceforge.net/projects/phpseclib/files/phpseclib0.3.10.zip/download) +* [Download (1.0.0)](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.0.zip/download) * [Browse Git](https://github.com/phpseclib/phpseclib) * [Code Coverage Report](http://phpseclib.bantux.org/code_coverage/php5/latest/) diff --git a/build/code-sniffer-ruleset-tests.xml b/build/code-sniffer-ruleset-tests.xml index f30722f7..7169012e 100644 --- a/build/code-sniffer-ruleset-tests.xml +++ b/build/code-sniffer-ruleset-tests.xml @@ -5,20 +5,12 @@ - + - - - - - - - - - + + + diff --git a/build/code-sniffer-ruleset.xml b/build/code-sniffer-ruleset.xml index f6bf92c7..2e399139 100644 --- a/build/code-sniffer-ruleset.xml +++ b/build/code-sniffer-ruleset.xml @@ -3,35 +3,25 @@ phpseclib coding standard - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + @@ -42,46 +32,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/composer.json b/composer.json index a81b0caf..db9e3031 100644 --- a/composer.json +++ b/composer.json @@ -52,13 +52,14 @@ "phing/phing": "~2.7", "phpunit/phpunit": "~4.0", "sami/sami": "~2.0", - "squizlabs/php_codesniffer": "~1.5" + "squizlabs/php_codesniffer": "~2.0" }, "suggest": { - "ext-mcrypt": "Install the Mcrypt extension in order to speed up a wide variety of cryptographic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations." }, - "include-path": ["phpseclib/"], "autoload": { "psr-4": { "phpseclib\\": "phpseclib/" diff --git a/composer.lock b/composer.lock index 7561de0f..daed47bf 100644 --- a/composer.lock +++ b/composer.lock @@ -1,10 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "1973a3fc1c8f678a9cd0ff646f7a8bee", + "hash": "3c1701cdae74c93eba5311e59f11cdb6", "packages": [], "packages-dev": [ { @@ -1201,32 +1201,31 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "1.5.6", + "version": "2.3.3", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5" + "reference": "c1a26c729508f73560c1a4f767f60b8ab6b4a666" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/6f3e42d311b882b25b4d409d23a289f4d3b803d5", - "reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/c1a26c729508f73560c1a4f767f60b8ab6b4a666", + "reference": "c1a26c729508f73560c1a4f767f60b8ab6b4a666", "shasum": "" }, "require": { "ext-tokenizer": "*", + "ext-xmlwriter": "*", "php": ">=5.1.2" }, - "suggest": { - "phpunit/php-timer": "dev-master" - }, "bin": [ - "scripts/phpcs" + "scripts/phpcs", + "scripts/phpcbf" ], "type": "library", "extra": { "branch-alias": { - "dev-phpcs-fixer": "2.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1235,12 +1234,12 @@ "CodeSniffer/CLI.php", "CodeSniffer/Exception.php", "CodeSniffer/File.php", + "CodeSniffer/Fixer.php", "CodeSniffer/Report.php", "CodeSniffer/Reporting.php", "CodeSniffer/Sniff.php", "CodeSniffer/Tokens.php", "CodeSniffer/Reports/", - "CodeSniffer/CommentParser/", "CodeSniffer/Tokenizers/", "CodeSniffer/DocGenerators/", "CodeSniffer/Standards/AbstractPatternSniff.php", @@ -1266,13 +1265,13 @@ "role": "lead" } ], - "description": "PHP_CodeSniffer tokenises PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", "homepage": "http://www.squizlabs.com/php-codesniffer", "keywords": [ "phpcs", "standards" ], - "time": "2014-12-04 22:32:15" + "time": "2015-06-24 03:16:23" }, { "name": "symfony/console", diff --git a/phpseclib/Crypt/AES.php b/phpseclib/Crypt/AES.php index e206653a..2696e0ab 100644 --- a/phpseclib/Crypt/AES.php +++ b/phpseclib/Crypt/AES.php @@ -7,7 +7,7 @@ * * PHP version 5 * - * NOTE: Since AES.php is (for compatibility and phpseclib-historical reasons) virtually + * NOTE: Since AES.php is (for compatibility and phpseclib-historical reasons) virtually * just a wrapper to Rijndael.php you may consider using Rijndael.php instead of * to save one include_once(). * diff --git a/phpseclib/Crypt/Base.php b/phpseclib/Crypt/Base.php index 2021c00c..7096b662 100644 --- a/phpseclib/Crypt/Base.php +++ b/phpseclib/Crypt/Base.php @@ -707,7 +707,7 @@ abstract class Base $iv = substr_replace($iv, $block, 0, $overflow); $ciphertext.= $block; $pos = $overflow; - } else if ($len) { + } elseif ($len) { $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv); $iv = substr($ciphertext, -$this->block_size); } @@ -1014,7 +1014,7 @@ abstract class Base $plaintext.= $iv ^ substr($ciphertext, -$overflow); $iv = substr_replace($iv, substr($ciphertext, -$overflow), 0, $overflow); $pos = $overflow; - } else if ($len) { + } elseif ($len) { $plaintext.= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv); $iv = substr($ciphertext, -$this->block_size); } @@ -1290,7 +1290,7 @@ abstract class Base $buffer['ciphertext'] = substr($temp, $overflow); $encryptIV = $temp; } - } else if (!strlen($buffer['ciphertext'])) { + } elseif (!strlen($buffer['ciphertext'])) { $ciphertext.= openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV); $temp = $this->_string_pop($ciphertext, $block_size); if ($this->continuousBuffer) { diff --git a/phpseclib/Crypt/DES.php b/phpseclib/Crypt/DES.php index b8169f7a..d748f1a5 100644 --- a/phpseclib/Crypt/DES.php +++ b/phpseclib/Crypt/DES.php @@ -1378,7 +1378,6 @@ class DES extends Base // Creating code for en- and decryption. $crypt_block = array(); foreach (array(self::ENCRYPT, self::DECRYPT) as $c) { - /* Do the initial IP permutation. */ $crypt_block[$c] = ' $in = unpack("N*", $in); diff --git a/phpseclib/Crypt/Hash.php b/phpseclib/Crypt/Hash.php index 647ca969..14b8a32a 100644 --- a/phpseclib/Crypt/Hash.php +++ b/phpseclib/Crypt/Hash.php @@ -139,7 +139,7 @@ class Hash */ function __construct($hash = 'sha1') { - if ( !defined('CRYPT_HASH_MODE') ) { + if (!defined('CRYPT_HASH_MODE')) { switch (true) { case extension_loaded('hash'): define('CRYPT_HASH_MODE', self::MODE_HASH); @@ -228,7 +228,7 @@ class Hash $mode = CRYPT_HASH_MODE; } - switch ( $mode ) { + switch ($mode) { case self::MODE_MHASH: switch ($hash) { case 'md5': @@ -262,26 +262,26 @@ class Hash switch ($hash) { case 'md2': - $this->b = 16; - $this->hash = array($this, '_md2'); - break; + $this->b = 16; + $this->hash = array($this, '_md2'); + break; case 'md5': - $this->b = 64; - $this->hash = array($this, '_md5'); - break; + $this->b = 64; + $this->hash = array($this, '_md5'); + break; case 'sha256': - $this->b = 64; - $this->hash = array($this, '_sha256'); - break; + $this->b = 64; + $this->hash = array($this, '_sha256'); + break; case 'sha384': case 'sha512': - $this->b = 128; - $this->hash = array($this, '_sha512'); - break; + $this->b = 128; + $this->hash = array($this, '_sha512'); + break; case 'sha1': default: - $this->b = 64; - $this->hash = array($this, '_sha1'); + $this->b = 64; + $this->hash = array($this, '_sha1'); } $this->ipad = str_repeat(chr(0x36), $this->b); @@ -300,7 +300,7 @@ class Hash $mode = is_array($this->hash) ? self::MODE_INTERNAL : CRYPT_HASH_MODE; if (!empty($this->key) || is_string($this->key)) { - switch ( $mode ) { + switch ($mode) { case self::MODE_MHASH: $output = mhash($this->hash, $text, $this->key); break; @@ -323,7 +323,7 @@ class Hash $output = call_user_func($this->hash, $output); // step 7 } } else { - switch ( $mode ) { + switch ($mode) { case self::MODE_MHASH: $output = mhash($this->hash, $text); break; @@ -497,12 +497,14 @@ class Hash // Extend the sixteen 32-bit words into sixty-four 32-bit words for ($i = 16; $i < 64; $i++) { + // @codingStandardsIgnoreStart $s0 = $this->_rightRotate($w[$i - 15], 7) ^ $this->_rightRotate($w[$i - 15], 18) ^ $this->_rightShift( $w[$i - 15], 3); $s1 = $this->_rightRotate($w[$i - 2], 17) ^ $this->_rightRotate($w[$i - 2], 19) ^ $this->_rightShift( $w[$i - 2], 10); + // @codingStandardsIgnoreEnd $w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1); } diff --git a/phpseclib/Crypt/RC2.php b/phpseclib/Crypt/RC2.php index 1a0c53d6..58351759 100644 --- a/phpseclib/Crypt/RC2.php +++ b/phpseclib/Crypt/RC2.php @@ -316,7 +316,7 @@ class RC2 extends Base if ($t1 <= 0) { $t1 = $this->default_key_length; - } else if ($t1 > 1024) { + } elseif ($t1 > 1024) { $t1 = 1024; } $this->current_key_length = $t1; diff --git a/phpseclib/Crypt/RSA.php b/phpseclib/Crypt/RSA.php index 86b89dbc..9edb9f61 100644 --- a/phpseclib/Crypt/RSA.php +++ b/phpseclib/Crypt/RSA.php @@ -465,7 +465,7 @@ class RSA { $this->configFile = dirname(__FILE__) . '/../openssl.cnf'; - if ( !defined('CRYPT_RSA_MODE') ) { + if (!defined('CRYPT_RSA_MODE')) { switch (true) { // Math/BigInteger's openssl requirements are a little less stringent than Crypt/RSA's. in particular, // Math/BigInteger doesn't require an openssl.cfg file whereas Crypt/RSA does. so if Math/BigInteger @@ -558,7 +558,7 @@ class RSA } // OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum - if ( CRYPT_RSA_MODE == self::MODE_OPENSSL && $bits >= 384 && CRYPT_RSA_EXPONENT == 65537) { + if (CRYPT_RSA_MODE == self::MODE_OPENSSL && $bits >= 384 && CRYPT_RSA_EXPONENT == 65537) { $config = array(); if (isset($this->configFile)) { $config['config'] = $this->configFile; @@ -572,7 +572,8 @@ class RSA $publickey = call_user_func_array(array($this, '_convertPublicKey'), array_values($this->_parseKey($publickey, self::PUBLIC_FORMAT_PKCS1))); // clear the buffer of error strings stemming from a minimalistic openssl.cnf - while (openssl_error_string() !== false); + while (openssl_error_string() !== false) { + } return array( 'privatekey' => $privatekey, @@ -762,19 +763,39 @@ class RSA $encryption = (!empty($this->password) || is_string($this->password)) ? 'aes256-cbc' : 'none'; $key.= $encryption; $key.= "\r\nComment: " . $this->comment . "\r\n"; - $public = pack('Na*Na*Na*', - strlen('ssh-rsa'), 'ssh-rsa', strlen($raw['publicExponent']), $raw['publicExponent'], strlen($raw['modulus']), $raw['modulus'] + $public = pack( + 'Na*Na*Na*', + strlen('ssh-rsa'), + 'ssh-rsa', + strlen($raw['publicExponent']), + $raw['publicExponent'], + strlen($raw['modulus']), + $raw['modulus'] ); - $source = pack('Na*Na*Na*Na*', - strlen('ssh-rsa'), 'ssh-rsa', strlen($encryption), $encryption, - strlen($this->comment), $this->comment, strlen($public), $public + $source = pack( + 'Na*Na*Na*Na*', + strlen('ssh-rsa'), + 'ssh-rsa', + strlen($encryption), + $encryption, + strlen($this->comment), + $this->comment, + strlen($public), + $public ); $public = base64_encode($public); $key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n"; $key.= chunk_split($public, 64); - $private = pack('Na*Na*Na*Na*', - strlen($raw['privateExponent']), $raw['privateExponent'], strlen($raw['prime1']), $raw['prime1'], - strlen($raw['prime2']), $raw['prime2'], strlen($raw['coefficient']), $raw['coefficient'] + $private = pack( + 'Na*Na*Na*Na*', + strlen($raw['privateExponent']), + $raw['privateExponent'], + strlen($raw['prime1']), + $raw['prime1'], + strlen($raw['prime2']), + $raw['prime2'], + strlen($raw['coefficient']), + $raw['coefficient'] ); if (empty($this->password) && !is_string($this->password)) { $source.= pack('Na*', strlen($private), $private); @@ -835,8 +856,14 @@ class RSA if ($this->privateKeyFormat == self::PRIVATE_FORMAT_PKCS8) { $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA - $RSAPrivateKey = pack('Ca*a*Ca*a*', - self::ASN1_INTEGER, "\01\00", $rsaOID, 4, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey + $RSAPrivateKey = pack( + 'Ca*a*Ca*a*', + self::ASN1_INTEGER, + "\01\00", + $rsaOID, + 4, + $this->_encodeLength(strlen($RSAPrivateKey)), + $RSAPrivateKey ); $RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); if (!empty($this->password) || is_string($this->password)) { @@ -847,20 +874,35 @@ class RSA $crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount); $RSAPrivateKey = $crypto->encrypt($RSAPrivateKey); - $parameters = pack('Ca*a*Ca*N', - self::ASN1_OCTETSTRING, $this->_encodeLength(strlen($salt)), $salt, - self::ASN1_INTEGER, $this->_encodeLength(4), $iterationCount + $parameters = pack( + 'Ca*a*Ca*N', + self::ASN1_OCTETSTRING, + $this->_encodeLength(strlen($salt)), + $salt, + self::ASN1_INTEGER, + $this->_encodeLength(4), + $iterationCount ); $pbeWithMD5AndDES_CBC = "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03"; - $encryptionAlgorithm = pack('Ca*a*Ca*a*', - self::ASN1_OBJECT, $this->_encodeLength(strlen($pbeWithMD5AndDES_CBC)), $pbeWithMD5AndDES_CBC, - self::ASN1_SEQUENCE, $this->_encodeLength(strlen($parameters)), $parameters + $encryptionAlgorithm = pack( + 'Ca*a*Ca*a*', + self::ASN1_OBJECT, + $this->_encodeLength(strlen($pbeWithMD5AndDES_CBC)), + $pbeWithMD5AndDES_CBC, + self::ASN1_SEQUENCE, + $this->_encodeLength(strlen($parameters)), + $parameters ); - $RSAPrivateKey = pack('Ca*a*Ca*a*', - self::ASN1_SEQUENCE, $this->_encodeLength(strlen($encryptionAlgorithm)), $encryptionAlgorithm, - self::ASN1_OCTETSTRING, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey + $RSAPrivateKey = pack( + 'Ca*a*Ca*a*', + self::ASN1_SEQUENCE, + $this->_encodeLength(strlen($encryptionAlgorithm)), + $encryptionAlgorithm, + self::ASN1_OCTETSTRING, + $this->_encodeLength(strlen($RSAPrivateKey)), + $RSAPrivateKey ); $RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); @@ -944,9 +986,12 @@ class RSA 'publicExponent' => pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($publicExponent)), $publicExponent) ); - $RSAPublicKey = pack('Ca*a*a*', - self::ASN1_SEQUENCE, $this->_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])), - $components['modulus'], $components['publicExponent'] + $RSAPublicKey = pack( + 'Ca*a*a*', + self::ASN1_SEQUENCE, + $this->_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])), + $components['modulus'], + $components['publicExponent'] ); if ($this->publicKeyFormat == self::PUBLIC_FORMAT_PKCS1_RAW) { @@ -959,8 +1004,11 @@ class RSA $RSAPublicKey = chr(0) . $RSAPublicKey; $RSAPublicKey = chr(3) . $this->_encodeLength(strlen($RSAPublicKey)) . $RSAPublicKey; - $RSAPublicKey = pack('Ca*a*', - self::ASN1_SEQUENCE, $this->_encodeLength(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey + $RSAPublicKey = pack( + 'Ca*a*', + self::ASN1_SEQUENCE, + $this->_encodeLength(strlen($rsaOID . $RSAPublicKey)), + $rsaOID . $RSAPublicKey ); $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" . @@ -1734,8 +1782,7 @@ class RSA $RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus); - switch($algorithm) - { + switch ($algorithm) { case 'sha256': $hash = new Hash('sha256'); $base = base64_encode($hash->hash($RSAPublicKey)); @@ -1861,7 +1908,7 @@ class RSA function _decodeLength(&$string) { $length = ord($this->_string_shift($string)); - if ( $length & 0x80 ) { // definite length, long form + if ($length & 0x80) { // definite length, long form $length&= 0x7F; $temp = $this->_string_shift($string, $length); list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)); @@ -2518,7 +2565,7 @@ class RSA // be output. $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8) - $sLen = $this->sLen === false ? $this->hLen : $this->sLen; + $sLen = $this->sLen ? $this->sLen : $this->hLen; $mHash = $this->hash->hash($m); if ($emLen < $this->hLen + $sLen + 2) { @@ -2555,7 +2602,7 @@ class RSA // be output. $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8); - $sLen = $this->sLen === false ? $this->hLen : $this->sLen; + $sLen = $this->sLen ? $this->sLen : $this->hLen; $mHash = $this->hash->hash($m); if ($emLen < $this->hLen + $sLen + 2) { diff --git a/phpseclib/Crypt/Random.php b/phpseclib/Crypt/Random.php index 1bcffe4d..e6269035 100644 --- a/phpseclib/Crypt/Random.php +++ b/phpseclib/Crypt/Random.php @@ -158,9 +158,9 @@ class Random ini_set('session.use_cookies', $old_use_cookies); session_cache_limiter($old_session_cache_limiter); } else { - if ($_OLD_SESSION !== false) { - $_SESSION = $_OLD_SESSION; - unset($_OLD_SESSION); + if ($_OLD_SESSION !== false) { + $_SESSION = $_OLD_SESSION; + unset($_OLD_SESSION); } else { unset($_SESSION); } diff --git a/phpseclib/Crypt/Rijndael.php b/phpseclib/Crypt/Rijndael.php index 29d37f25..90c75d83 100644 --- a/phpseclib/Crypt/Rijndael.php +++ b/phpseclib/Crypt/Rijndael.php @@ -311,7 +311,7 @@ class Rijndael extends Base $length >>= 5; if ($length > 8) { $length = 8; - } else if ($length < 4) { + } elseif ($length < 4) { $length = 4; } $this->Nb = $length; @@ -614,7 +614,7 @@ class Rijndael extends Base // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is. $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord $temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk]; - } else if ($this->Nk > 6 && $i % $this->Nk == 4) { + } elseif ($this->Nk > 6 && $i % $this->Nk == 4) { $temp = $this->_subWord($temp); } $w[$i] = $w[$i - $this->Nk] ^ $temp; diff --git a/phpseclib/Crypt/Twofish.php b/phpseclib/Crypt/Twofish.php index 517aeb49..9c32de67 100644 --- a/phpseclib/Crypt/Twofish.php +++ b/phpseclib/Crypt/Twofish.php @@ -533,7 +533,9 @@ class Twofish extends Base $u^= 0x7fffffff & ($t >> 1); // Add the modular polynomial on underflow. - if ($t & 0x01) $u^= 0xa6 ; + if ($t & 0x01) { + $u^= 0xa6 ; + } // Remove t * (a + 1/a) * (x^3 + x). $B^= ($u << 24) | ($u << 8); diff --git a/phpseclib/File/ANSI.php b/phpseclib/File/ANSI.php index 2d03a199..1daf787a 100644 --- a/phpseclib/File/ANSI.php +++ b/phpseclib/File/ANSI.php @@ -337,6 +337,7 @@ class ANSI //$back = $attr_cell->reverse ? &$attr_cell->foreground : &$attr_cell->background; $back = &$attr_cell->{ $attr_cell->reverse ? 'foreground' : 'background' }; switch ($mod) { + // @codingStandardsIgnoreStart case 30: $front = 'black'; break; case 31: $front = 'red'; break; case 32: $front = 'green'; break; @@ -354,6 +355,7 @@ class ANSI case 45: $back = 'magenta'; break; case 46: $back = 'cyan'; break; case 47: $back = 'white'; break; + // @codingStandardsIgnoreEnd default: //user_error('Unsupported attribute: ' . $mod); diff --git a/phpseclib/File/ASN1.php b/phpseclib/File/ASN1.php index acfa5be8..fa58ec7f 100644 --- a/phpseclib/File/ASN1.php +++ b/phpseclib/File/ASN1.php @@ -245,17 +245,17 @@ class ASN1 $tag <<= 7; $tag |= ord($this->_string_shift($encoded)) & 0x7F; $start++; - } while ( $loop ); + } while ($loop); } // Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13 $length = ord($this->_string_shift($encoded)); $start++; - if ( $length == 0x80 ) { // indefinite length + if ($length == 0x80) { // indefinite length // "[A sender shall] use the indefinite form (see 8.1.3.6) if the encoding is constructed and is not all // immediately available." -- paragraph 8.1.3.2.c $length = strlen($encoded); - } elseif ( $length & 0x80 ) { // definite length, long form + } elseif ($length & 0x80) { // definite length, long form // technically, the long form of the length can be represented by up to 126 octets (bytes), but we'll only // support it up to four. $length&= 0x7F; @@ -1028,7 +1028,7 @@ class ASN1 if ($outtype !== false) { return $this->_encode_der($source[$typename], array('type' => $outtype) + $mapping, null, $special); } - } + } $filters = $this->filters; foreach ($loc as $part) { diff --git a/phpseclib/File/X509.php b/phpseclib/File/X509.php index b50e7247..cbe16bae 100644 --- a/phpseclib/File/X509.php +++ b/phpseclib/File/X509.php @@ -28,6 +28,7 @@ namespace phpseclib\File; use phpseclib\Crypt\Hash; use phpseclib\Crypt\RSA; +use phpseclib\Crypt\Random; use phpseclib\File\ASN1; use phpseclib\File\ASN1\Element; use phpseclib\Math\BigInteger; @@ -2502,7 +2503,7 @@ class X509 $asn1->loadFilters($filters); $result = ''; foreach ($dn['rdnSequence'] as $rdn) { - foreach ($rdn as $i=>$attr) { + foreach ($rdn as $i => $attr) { $attr = &$rdn[$i]; if (is_array($attr['value'])) { foreach ($attr['value'] as $type => $v) { @@ -2723,7 +2724,7 @@ class X509 break; } } - foreach ($chain as $key=>$value) { + foreach ($chain as $key => $value) { $chain[$key] = new X509(); $chain[$key]->loadX509($value); } @@ -3179,9 +3180,9 @@ class X509 { $year = @gmdate("Y", @strtotime($date)); // the same way ASN1.php parses this if ($year < 2050) { - return array('utcTime' => $date); + return array('utcTime' => $date); } else { - return array('generalTime' => $date); + return array('generalTime' => $date); } } @@ -3235,7 +3236,7 @@ class X509 if (isset($subject->domains)) { $this->removeExtension('id-ce-subjectAltName'); } - } else if (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertList'])) { + } elseif (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertList'])) { return false; } else { if (!isset($subject->publicKey)) { @@ -3244,7 +3245,16 @@ class X509 $startDate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O'); $endDate = !empty($this->endDate) ? $this->endDate : @date('D, d M Y H:i:s O', strtotime('+1 year')); - $serialNumber = !empty($this->serialNumber) ? $this->serialNumber : new BigInteger(); + /* "The serial number MUST be a positive integer" + "Conforming CAs MUST NOT use serialNumber values longer than 20 octets." + -- https://tools.ietf.org/html/rfc5280#section-4.1.2.2 + + for the integer to be positive the leading bit needs to be 0 hence the + application of a bitmap + */ + $serialNumber = !empty($this->serialNumber) ? + $this->serialNumber : + new BigInteger(Random::string(20) & ("\x7F" . str_repeat("\xFF", 19)), 256); $this->currentCert = array( 'tbsCertificate' => @@ -3260,8 +3270,8 @@ class X509 'subject' => $subject->dn, 'subjectPublicKeyInfo' => $subjectPublicKey ), - 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm), - 'signature' => false // this is going to be overwritten later + 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm), + 'signature' => false // this is going to be overwritten later ); // Copy extensions from CSR. @@ -3282,8 +3292,7 @@ class X509 // ) //), 'keyIdentifier' => $issuer->currentKeyIdentifier - ) - ); + )); //$extensions = &$this->currentCert['tbsCertificate']['extensions']; //if (isset($issuer->serialNumber)) { // $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber; @@ -3326,7 +3335,8 @@ class X509 $keyUsage = array(); } - $this->setExtension('id-ce-keyUsage', + $this->setExtension( + 'id-ce-keyUsage', array_values(array_unique(array_merge($keyUsage, array('cRLSign', 'keyCertSign')))) ); @@ -3335,8 +3345,11 @@ class X509 $basicConstraints = array(); } - $this->setExtension('id-ce-basicConstraints', - array_unique(array_merge(array('cA' => true), $basicConstraints)), true); + $this->setExtension( + 'id-ce-basicConstraints', + array_unique(array_merge(array('cA' => true), $basicConstraints)), + true + ); if (!isset($subject->currentKeyIdentifier)) { $this->setExtension('id-ce-subjectKeyIdentifier', base64_encode($this->computeKeyIdentifier($this->currentCert)), false, false); @@ -3396,8 +3409,8 @@ class X509 'subject' => $this->dn, 'subjectPKInfo' => $publicKey ), - 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm), - 'signature' => false // this is going to be overwritten later + 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm), + 'signature' => false // this is going to be overwritten later ); } @@ -3461,8 +3474,8 @@ class X509 // Random::string(8) & str_repeat("\x7F", 8) 'challenge' => !empty($this->challenge) ? $this->challenge : '' ), - 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm), - 'signature' => false // this is going to be overwritten later + 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm), + 'signature' => false // this is going to be overwritten later ); } @@ -3514,8 +3527,8 @@ class X509 'issuer' => false, // this is going to be overwritten later 'thisUpdate' => $this->_timeField($thisUpdate) // $this->setStartDate() ), - 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm), - 'signature' => false // this is going to be overwritten later + 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm), + 'signature' => false // this is going to be overwritten later ); } @@ -3533,6 +3546,11 @@ class X509 $crlNumber = $this->serialNumber; } else { $crlNumber = $this->getExtension('id-ce-cRLNumber'); + // "The CRL number is a non-critical CRL extension that conveys a + // monotonically increasing sequence number for a given CRL scope and + // CRL issuer. This extension allows users to easily determine when a + // particular CRL supersedes another CRL." + // -- https://tools.ietf.org/html/rfc5280#section-5.2.3 $crlNumber = $crlNumber !== false ? $crlNumber->add(new BigInteger(1)) : null; } @@ -3571,8 +3589,7 @@ class X509 // ) //), 'keyIdentifier' => $issuer->currentKeyIdentifier - ) - ); + )); //$extensions = &$tbsCertList['crlExtensions']; //if (isset($issuer->serialNumber)) { // $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber; @@ -4354,7 +4371,6 @@ class X509 if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) { if ($this->_revokedCertificate($rclist, $serial) === false) { // If not yet revoked if (($i = $this->_revokedCertificate($rclist, $serial, true)) !== false) { - if (!empty($date)) { $rclist[$i]['revocationDate'] = $this->_timeField($date); } diff --git a/phpseclib/Math/BigInteger.php b/phpseclib/Math/BigInteger.php index 21e0fafc..bc7b2269 100644 --- a/phpseclib/Math/BigInteger.php +++ b/phpseclib/Math/BigInteger.php @@ -258,7 +258,7 @@ class BigInteger */ function __construct($x = 0, $base = 10) { - if ( !defined('MATH_BIGINTEGER_MODE') ) { + if (!defined('MATH_BIGINTEGER_MODE')) { switch (true) { case extension_loaded('gmp'): define('MATH_BIGINTEGER_MODE', self::MODE_GMP); @@ -334,7 +334,7 @@ class BigInteger } } - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: switch (true) { case is_resource($x) && get_resource_type($x) == 'GMP integer': @@ -364,8 +364,8 @@ class BigInteger $x = ~$x; $this->is_negative = true; } - case 256: - switch ( MATH_BIGINTEGER_MODE ) { + case 256: + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: $sign = $this->is_negative ? '-' : ''; $this->value = gmp_init($sign . '0x' . bin2hex($x)); @@ -401,7 +401,7 @@ class BigInteger $this->value = $temp->value; } break; - case 16: + case 16: case -16: if ($base > 0 && $x[0] == '-') { $this->is_negative = true; @@ -416,7 +416,7 @@ class BigInteger $x = bin2hex(~pack('H*', $x)); } - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: $temp = $this->is_negative ? '-0x' . $x : '0x' . $x; $this->value = gmp_init($temp); @@ -439,14 +439,14 @@ class BigInteger $this->value = $temp->value; } break; - case 10: + case 10: case -10: // (?value = gmp_init($x); break; @@ -476,7 +476,7 @@ class BigInteger $this->value = $temp->value; } break; - case 2: // base-2 support originally implemented by Lluis Pamies - thanks! + case 2: // base-2 support originally implemented by Lluis Pamies - thanks! case -2: if ($base > 0 && $x[0] == '-') { $this->is_negative = true; @@ -549,7 +549,7 @@ class BigInteger return $comparison < 0 ? ~$bytes : $bytes; } - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: if (gmp_cmp($this->value, gmp_init(0)) == 0) { return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; @@ -684,7 +684,7 @@ class BigInteger */ function toString() { - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: return gmp_strval($this->value); case self::MODE_BCMATH: @@ -838,7 +838,7 @@ class BigInteger */ function add($y) { - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: $temp = new static(); $temp->value = gmp_add($this->value, $y->value); @@ -880,7 +880,7 @@ class BigInteger self::VALUE => $y_value, self::SIGN => $y_negative ); - } else if ($y_size == 0) { + } elseif ($y_size == 0) { return array( self::VALUE => $x_value, self::SIGN => $x_negative @@ -888,8 +888,8 @@ class BigInteger } // subtract, if appropriate - if ( $x_negative != $y_negative ) { - if ( $x_value == $y_value ) { + if ($x_negative != $y_negative) { + if ($x_value == $y_value) { return array( self::VALUE => array(), self::SIGN => false @@ -967,7 +967,7 @@ class BigInteger */ function subtract($y) { - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: $temp = new static(); $temp->value = gmp_sub($this->value, $y->value); @@ -1009,7 +1009,7 @@ class BigInteger self::VALUE => $y_value, self::SIGN => !$y_negative ); - } else if ($y_size == 0) { + } elseif ($y_size == 0) { return array( self::VALUE => $x_value, self::SIGN => $x_negative @@ -1017,7 +1017,7 @@ class BigInteger } // add, if appropriate (ie. -$x - +$y or +$x - -$y) - if ( $x_negative != $y_negative ) { + if ($x_negative != $y_negative) { $temp = $this->_add($x_value, false, $y_value, false); $temp[self::SIGN] = $x_negative; @@ -1026,7 +1026,7 @@ class BigInteger $diff = $this->_compare($x_value, $x_negative, $y_value, $y_negative); - if ( !$diff ) { + if (!$diff) { return array( self::VALUE => array(), self::SIGN => false @@ -1034,7 +1034,7 @@ class BigInteger } // switch $x and $y around, if appropriate. - if ( (!$x_negative && $diff < 0) || ($x_negative && $diff > 0) ) { + if ((!$x_negative && $diff < 0) || ($x_negative && $diff > 0)) { $temp = $x_value; $x_value = $y_value; $y_value = $temp; @@ -1100,7 +1100,7 @@ class BigInteger */ function multiply($x) { - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: $temp = new static(); $temp->value = gmp_mul($this->value, $x->value); @@ -1144,7 +1144,7 @@ class BigInteger $x_length = count($x_value); $y_length = count($y_value); - if ( !$x_length || !$y_length ) { // a 0 is being multiplied + if (!$x_length || !$y_length) { // a 0 is being multiplied return array( self::VALUE => array(), self::SIGN => false @@ -1174,11 +1174,11 @@ class BigInteger $x_length = count($x_value); $y_length = count($y_value); - if ( !$x_length || !$y_length ) { // a 0 is being multiplied + if (!$x_length || !$y_length) { // a 0 is being multiplied return array(); } - if ( $x_length < $y_length ) { + if ($x_length < $y_length) { $temp = $x_value; $x_value = $y_value; $y_value = $temp; @@ -1291,7 +1291,7 @@ class BigInteger */ function _baseSquare($value) { - if ( empty($value) ) { + if (empty($value)) { return array(); } $square_value = $this->_array_repeat(0, 2 * count($value)); @@ -1385,7 +1385,7 @@ class BigInteger */ function divide($y) { - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: $quotient = new static(); $remainder = new static(); @@ -1422,7 +1422,7 @@ class BigInteger } static $zero; - if ( !isset($zero) ) { + if (!isset($zero)) { $zero = new static(); } @@ -1436,16 +1436,16 @@ class BigInteger $diff = $x->compare($y); - if ( !$diff ) { + if (!$diff) { $temp = new static(); $temp->value = array(1); $temp->is_negative = $x_sign != $y_sign; return array($this->_normalize($temp), $this->_normalize(new static())); } - if ( $diff < 0 ) { + if ($diff < 0) { // if $x is negative, "add" $y. - if ( $x_sign ) { + if ($x_sign) { $x = $y->subtract($x); } return array($this->_normalize(new static()), $this->_normalize($x)); @@ -1479,7 +1479,7 @@ class BigInteger // $temp = $y << ($x_max - $y_max-1) in base 2**26 $temp_value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y_value); - while ( $x->compare($temp) >= 0 ) { + while ($x->compare($temp) >= 0) { // calculate the "common residue" ++$quotient_value[$x_max - $y_max]; $x = $x->subtract($temp); @@ -1515,7 +1515,7 @@ class BigInteger $rhs_value = array($x_window[2], $x_window[1], $x_window[0]); - while ( $lhs->compare($rhs) > 0 ) { + while ($lhs->compare($rhs) > 0) { --$quotient_value[$q_index]; $lhs->value = array($quotient_value[$q_index]); @@ -1546,7 +1546,7 @@ class BigInteger $quotient->is_negative = $x_sign != $y_sign; // calculate the "common residue", if appropriate - if ( $x_sign ) { + if ($x_sign) { $y->_rshift($shift); $x = $y->subtract($x); } @@ -1633,7 +1633,7 @@ class BigInteger return $this->_normalize($temp->modPow($e, $n)); } - if ( MATH_BIGINTEGER_MODE == self::MODE_GMP ) { + if (MATH_BIGINTEGER_MODE == self::MODE_GMP) { $temp = new static(); $temp->value = gmp_powm($this->value, $e->value, $n->value); @@ -1656,17 +1656,23 @@ class BigInteger 'publicExponent' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['publicExponent'])), $components['publicExponent']) ); - $RSAPublicKey = pack('Ca*a*a*', - 48, $this->_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])), - $components['modulus'], $components['publicExponent'] + $RSAPublicKey = pack( + 'Ca*a*a*', + 48, + $this->_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])), + $components['modulus'], + $components['publicExponent'] ); $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA $RSAPublicKey = chr(0) . $RSAPublicKey; $RSAPublicKey = chr(3) . $this->_encodeASN1Length(strlen($RSAPublicKey)) . $RSAPublicKey; - $encapsulated = pack('Ca*a*', - 48, $this->_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey + $encapsulated = pack( + 'Ca*a*', + 48, + $this->_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)), + $rsaOID . $RSAPublicKey ); $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" . @@ -1680,25 +1686,25 @@ class BigInteger } } - if ( MATH_BIGINTEGER_MODE == self::MODE_BCMATH ) { + if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) { $temp = new static(); $temp->value = bcpowmod($this->value, $e->value, $n->value, 0); return $this->_normalize($temp); } - if ( empty($e->value) ) { + if (empty($e->value)) { $temp = new static(); $temp->value = array(1); return $this->_normalize($temp); } - if ( $e->value == array(1) ) { + if ($e->value == array(1)) { list(, $temp) = $this->divide($n); return $this->_normalize($temp); } - if ( $e->value == array(2) ) { + if ($e->value == array(2)) { $temp = new static(); $temp->value = $this->_square($this->value); list(, $temp) = $temp->divide($n); @@ -1713,14 +1719,14 @@ class BigInteger // made uncallable // is the modulo odd? - if ( $n->value[0] & 1 ) { + if ($n->value[0] & 1) { return $this->_normalize($this->_slidingWindow($e, $n, self::MONTGOMERY)); } // if it's not, it's even // find the lowest set bit (eg. the max pow of 2 that divides $n) for ($i = 0; $i < count($n->value); ++$i) { - if ( $n->value[$i] ) { + if ($n->value[$i]) { $temp = decbin($n->value[$i]); $j = strlen($temp) - strrpos($temp, '1') - 1; $j+= 26 * $i; @@ -1798,7 +1804,8 @@ class BigInteger // calculate the appropriate window size. // $window_size == 3 if $window_ranges is between 25 and 81, for example. - for ($i = 0, $window_size = 1; $e_length > $window_ranges[$i] && $i < count($window_ranges); ++$window_size, ++$i); + for ($i = 0, $window_size = 1; $e_length > $window_ranges[$i] && $i < count($window_ranges); ++$window_size, ++$i) { + } $n_value = $n->value; @@ -1818,13 +1825,13 @@ class BigInteger $result = array(1); $result = $this->_prepareReduce($result, $n_value, $mode); - for ($i = 0; $i < $e_length; ) { - if ( !$e_bits[$i] ) { + for ($i = 0; $i < $e_length;) { + if (!$e_bits[$i]) { $result = $this->_squareReduce($result, $n_value, $mode); ++$i; } else { for ($j = $window_size - 1; $j > 0; --$j) { - if ( !empty($e_bits[$i + $j]) ) { + if (!empty($e_bits[$i + $j])) { break; } } @@ -2008,7 +2015,7 @@ class BigInteger // n = 2 * m.length - if ( ($key = array_search($m, $cache[self::VARIABLE])) === false ) { + if (($key = array_search($m, $cache[self::VARIABLE])) === false) { $key = count($cache[self::VARIABLE]); $cache[self::VARIABLE][] = $m; @@ -2097,7 +2104,7 @@ class BigInteger return $temp->value; } - if ( ($key = array_search($n, $cache[self::VARIABLE])) === false ) { + if (($key = array_search($n, $cache[self::VARIABLE])) === false) { $key = count($cache[self::VARIABLE]); $cache[self::VARIABLE][] = $n; $lhs = new static(); @@ -2158,14 +2165,14 @@ class BigInteger $x_length = count($x_value); $y_length = count($y_value); - if ( !$x_length || !$y_length ) { // a 0 is being multiplied + if (!$x_length || !$y_length) { // a 0 is being multiplied return array( self::VALUE => array(), self::SIGN => false ); } - if ( $x_length < $y_length ) { + if ($x_length < $y_length) { $temp = $x_value; $x_value = $y_value; $y_value = $temp; @@ -2239,7 +2246,7 @@ class BigInteger self::DATA => array() ); - if ( ($key = array_search($n, $cache[self::VARIABLE])) === false ) { + if (($key = array_search($n, $cache[self::VARIABLE])) === false) { $key = count($cache[self::VARIABLE]); $cache[self::VARIABLE][] = $x; $cache[self::DATA][] = $this->_modInverse67108864($n); @@ -2295,7 +2302,7 @@ class BigInteger self::DATA => array() ); - if ( ($key = array_search($m, $cache[self::VARIABLE])) === false ) { + if (($key = array_search($m, $cache[self::VARIABLE])) === false) { $key = count($cache[self::VARIABLE]); $cache[self::VARIABLE][] = $m; $cache[self::DATA][] = $this->_modInverse67108864($m); @@ -2408,7 +2415,7 @@ class BigInteger */ function modInverse($n) { - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: $temp = new static(); $temp->value = gmp_invert($this->value, $n->value); @@ -2472,7 +2479,7 @@ class BigInteger */ function extendedGCD($n) { - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: extract(gmp_gcdext($this->value, $n->value)); @@ -2522,7 +2529,7 @@ class BigInteger $g = new static(); $g->value = array(1); - while ( !(($x->value[0] & 1)|| ($y->value[0] & 1)) ) { + while (!(($x->value[0] & 1)|| ($y->value[0] & 1))) { $x->_rshift(1); $y->_rshift(1); $g->_lshift(1); @@ -2539,10 +2546,10 @@ class BigInteger $a->value = $d->value = $g->value = array(1); $b->value = $c->value = array(); - while ( !empty($u->value) ) { - while ( !($u->value[0] & 1) ) { + while (!empty($u->value)) { + while (!($u->value[0] & 1)) { $u->_rshift(1); - if ( (!empty($a->value) && ($a->value[0] & 1)) || (!empty($b->value) && ($b->value[0] & 1)) ) { + if ((!empty($a->value) && ($a->value[0] & 1)) || (!empty($b->value) && ($b->value[0] & 1))) { $a = $a->add($y); $b = $b->subtract($x); } @@ -2550,9 +2557,9 @@ class BigInteger $b->_rshift(1); } - while ( !($v->value[0] & 1) ) { + while (!($v->value[0] & 1)) { $v->_rshift(1); - if ( (!empty($d->value) && ($d->value[0] & 1)) || (!empty($c->value) && ($c->value[0] & 1)) ) { + if ((!empty($d->value) && ($d->value[0] & 1)) || (!empty($c->value) && ($c->value[0] & 1))) { $c = $c->add($y); $d = $d->subtract($x); } @@ -2615,7 +2622,7 @@ class BigInteger { $temp = new static(); - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: $temp->value = gmp_abs($this->value); break; @@ -2649,7 +2656,7 @@ class BigInteger */ function compare($y) { - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: return gmp_cmp($this->value, $y->value); case self::MODE_BCMATH: @@ -2672,13 +2679,13 @@ class BigInteger */ function _compare($x_value, $x_negative, $y_value, $y_negative) { - if ( $x_negative != $y_negative ) { + if ($x_negative != $y_negative) { return ( !$x_negative && $y_negative ) ? 1 : -1; } $result = $x_negative ? -1 : 1; - if ( count($x_value) != count($y_value) ) { + if (count($x_value) != count($y_value)) { return ( count($x_value) > count($y_value) ) ? $result : -$result; } $size = max(count($x_value), count($y_value)); @@ -2707,7 +2714,7 @@ class BigInteger */ function equals($x) { - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: return gmp_cmp($this->value, $x->value) == 0; default: @@ -2727,7 +2734,7 @@ class BigInteger function setPrecision($bits) { $this->precision = $bits; - if ( MATH_BIGINTEGER_MODE != self::MODE_BCMATH ) { + if (MATH_BIGINTEGER_MODE != self::MODE_BCMATH) { $this->bitmask = new static(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xFF), $bits >> 3), 256); } else { $this->bitmask = new static(bcpow('2', $bits, 0)); @@ -2747,7 +2754,7 @@ class BigInteger */ function bitwise_and($x) { - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: $temp = new static(); $temp->value = gmp_and($this->value, $x->value); @@ -2788,7 +2795,7 @@ class BigInteger */ function bitwise_or($x) { - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: $temp = new static(); $temp->value = gmp_or($this->value, $x->value); @@ -2828,7 +2835,7 @@ class BigInteger */ function bitwise_xor($x) { - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: $temp = new static(); $temp->value = gmp_xor($this->value, $x->value); @@ -2908,7 +2915,7 @@ class BigInteger { $temp = new static(); - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: static $two; @@ -2946,7 +2953,7 @@ class BigInteger { $temp = new static(); - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: static $two; @@ -2985,7 +2992,7 @@ class BigInteger if ($this->precision > 0) { $precision = $this->precision; - if ( MATH_BIGINTEGER_MODE == self::MODE_BCMATH ) { + if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) { $mask = $this->bitmask->subtract(new static(1)); $mask = $mask->toBytes(); } else { @@ -2993,7 +3000,8 @@ class BigInteger } } else { $temp = ord($bits[0]); - for ($i = 0; $temp >> $i; ++$i); + for ($i = 0; $temp >> $i; ++$i) { + } $precision = 8 * strlen($bits) - 8 + $i; $mask = chr((1 << ($precision & 0x7)) - 1) . str_repeat(chr(0xFF), $precision >> 3); } @@ -3092,7 +3100,7 @@ class BigInteger if (!$compare) { return $this->_normalize($min); - } else if ($compare < 0) { + } elseif ($compare < 0) { // if $min is bigger then $max, swap $min and $max $temp = $max; $max = $min; @@ -3173,7 +3181,7 @@ class BigInteger if (!$compare) { return $min->isPrime() ? $min : false; - } else if ($compare < 0) { + } elseif ($compare < 0) { // if $min is bigger then $max, swap $min and $max $temp = $max; $max = $min; @@ -3191,7 +3199,7 @@ class BigInteger $x = $this->random($min, $max); // gmp_nextprime() requires PHP 5 >= 5.2.0 per . - if ( MATH_BIGINTEGER_MODE == self::MODE_GMP && function_exists('gmp_nextprime') ) { + if (MATH_BIGINTEGER_MODE == self::MODE_GMP && function_exists('gmp_nextprime')) { $p = new static(); $p->value = gmp_nextprime($x->value); @@ -3257,7 +3265,7 @@ class BigInteger */ function _make_odd() { - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: gmp_setbit($this->value, 0); break; @@ -3309,7 +3317,7 @@ class BigInteger // ie. gmp_testbit($this, 0) // ie. isEven() or !isOdd() - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: return gmp_prob_prime($this->value, $t) != 0; case self::MODE_BCMATH: @@ -3346,7 +3354,7 @@ class BigInteger 953, 967, 971, 977, 983, 991, 997 ); - if ( MATH_BIGINTEGER_MODE != self::MODE_INTERNAL ) { + if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) { for ($i = 0; $i < count($primes); ++$i) { $primes[$i] = new static($primes[$i]); } @@ -3362,7 +3370,7 @@ class BigInteger } // see HAC 4.4.1 "Random search for probable primes" - if ( MATH_BIGINTEGER_MODE != self::MODE_INTERNAL ) { + if (MATH_BIGINTEGER_MODE != self::MODE_INTERNAL) { foreach ($primes as $prime) { list(, $r) = $this->divide($prime); if ($r->equals($zero)) { @@ -3386,7 +3394,7 @@ class BigInteger $r = $n_1->copy(); $r_value = $r->value; // ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s)); - if ( MATH_BIGINTEGER_MODE == self::MODE_BCMATH ) { + if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) { $s = 0; // if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals($one) check earlier while ($r->value[strlen($r->value) - 1] % 2 == 0) { @@ -3396,7 +3404,8 @@ class BigInteger } else { for ($i = 0, $r_length = count($r_value); $i < $r_length; ++$i) { $temp = ~$r_value[$i] & 0xFFFFFF; - for ($j = 1; ($temp >> $j) & 1; ++$j); + for ($j = 1; ($temp >> $j) & 1; ++$j) { + } if ($j != 25) { break; } @@ -3435,7 +3444,7 @@ class BigInteger */ function _lshift($shift) { - if ( $shift == 0 ) { + if ($shift == 0) { return; } @@ -3451,7 +3460,7 @@ class BigInteger $this->value[$i] = (int) ($temp - $carry * self::$baseFull); } - if ( $carry ) { + if ($carry) { $this->value[count($this->value)] = $carry; } @@ -3479,7 +3488,7 @@ class BigInteger $carry_shift = self::$base - $shift; $carry_mask = (1 << $shift) - 1; - if ( $num_digits ) { + if ($num_digits) { $this->value = array_slice($this->value, $num_digits); } @@ -3509,7 +3518,7 @@ class BigInteger $result->precision = $this->precision; $result->bitmask = $this->bitmask; - switch ( MATH_BIGINTEGER_MODE ) { + switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: if (!empty($result->bitmask->value)) { $result->value = gmp_and($result->value, $result->bitmask->value); @@ -3526,7 +3535,7 @@ class BigInteger $value = &$result->value; - if ( !count($value) ) { + if (!count($value)) { return $result; } @@ -3556,7 +3565,7 @@ class BigInteger function _trim($value) { for ($i = count($value) - 1; $i >= 0; --$i) { - if ( $value[$i] ) { + if ($value[$i]) { break; } unset($value[$i]); diff --git a/phpseclib/Net/SCP.php b/phpseclib/Net/SCP.php index 6853e072..ebfa999a 100644 --- a/phpseclib/Net/SCP.php +++ b/phpseclib/Net/SCP.php @@ -283,7 +283,7 @@ class SCP case self::MODE_SSH1: $data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($data), $data); $this->ssh->_send_binary_packet($data); - } + } } /** @@ -319,7 +319,7 @@ class SCP throw new \UnexpectedValueException('Unknown packet received'); } } - } + } } /** @@ -335,6 +335,6 @@ class SCP break; case self::MODE_SSH1: $this->ssh->disconnect(); - } + } } } diff --git a/phpseclib/Net/SFTP.php b/phpseclib/Net/SFTP.php index e22a6ae5..8460a1c9 100644 --- a/phpseclib/Net/SFTP.php +++ b/phpseclib/Net/SFTP.php @@ -397,8 +397,15 @@ class SFTP extends SSH2 $this->window_size_server_to_client[self::CHANNEL] = $this->window_size; - $packet = pack('CNa*N3', - NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', self::CHANNEL, $this->window_size, 0x4000); + $packet = pack( + 'CNa*N3', + NET_SSH2_MSG_CHANNEL_OPEN, + strlen('session'), + 'session', + self::CHANNEL, + $this->window_size, + 0x4000 + ); if (!$this->_send_binary_packet($packet)) { return false; @@ -411,8 +418,16 @@ class SFTP extends SSH2 return false; } - $packet = pack('CNNa*CNa*', - NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL], strlen('subsystem'), 'subsystem', 1, strlen('sftp'), 'sftp'); + $packet = pack( + 'CNNa*CNa*', + NET_SSH2_MSG_CHANNEL_REQUEST, + $this->server_channels[self::CHANNEL], + strlen('subsystem'), + 'subsystem', + 1, + strlen('sftp'), + 'sftp' + ); if (!$this->_send_binary_packet($packet)) { return false; } @@ -427,8 +442,16 @@ class SFTP extends SSH2 "exec sftp-server"; // we don't do $this->exec($command, false) because exec() operates on a different channel and plus the SSH_MSG_CHANNEL_OPEN that exec() does // is redundant - $packet = pack('CNNa*CNa*', - NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL], strlen('exec'), 'exec', 1, strlen($command), $command); + $packet = pack( + 'CNNa*CNa*', + NET_SSH2_MSG_CHANNEL_REQUEST, + $this->server_channels[self::CHANNEL], + strlen('exec'), + 'exec', + 1, + strlen($command), + $command + ); if (!$this->_send_binary_packet($packet)) { return false; } @@ -768,7 +791,7 @@ class SFTP extends SSH2 static $depth = 0; - foreach ($files as $key=>$value) { + foreach ($files as $key => $value) { if ($depth != 0 && $key == '..') { unset($files[$key]); continue; @@ -863,7 +886,7 @@ class SFTP extends SSH2 } else { $temp = $dir . '/' . $shortname; } - $this->_update_stat_cache($temp, (object) array('stat' => $attributes)); + $this->_update_stat_cache($temp, (object) array('lstat' => $attributes)); } // SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the // final SSH_FXP_STATUS packet should tell us that, already. @@ -1032,7 +1055,13 @@ class SFTP extends SSH2 $temp = &$this->stat_cache; $max = count($dirs) - 1; - foreach ($dirs as $i=>$dir) { + foreach ($dirs as $i => $dir) { + // if $temp is an object that means one of two things. + // 1. a file was deleted and changed to a directory behind phpseclib's back + // 2. it's a symlink. when lstat is done it's unclear what it's a symlink to + if (is_object($temp)) { + $temp = array(); + } if (!isset($temp[$dir])) { $temp[$dir] = array(); } @@ -1065,7 +1094,7 @@ class SFTP extends SSH2 $temp = &$this->stat_cache; $max = count($dirs) - 1; - foreach ($dirs as $i=>$dir) { + foreach ($dirs as $i => $dir) { if ($i === $max) { unset($temp[$dir]); return true; @@ -1122,7 +1151,7 @@ class SFTP extends SSH2 if ($this->use_stat_cache) { $result = $this->_query_stat_cache($filename); - if (is_array($result) && isset($result['.'])) { + if (is_array($result) && isset($result['.']) && isset($result['.']->stat)) { return $result['.']->stat; } if (is_object($result) && isset($result->stat)) { @@ -1495,7 +1524,7 @@ class SFTP extends SSH2 } unset($entries['.'], $entries['..']); - foreach ($entries as $filename=>$props) { + foreach ($entries as $filename => $props) { if (!isset($props['type'])) { return false; } @@ -2167,7 +2196,7 @@ class SFTP extends SSH2 } unset($entries['.'], $entries['..']); - foreach ($entries as $filename=>$props) { + foreach ($entries as $filename => $props) { if (!isset($props['type'])) { return false; } @@ -2369,13 +2398,20 @@ class SFTP extends SSH2 } switch ($type) { - case NET_SFTP_TYPE_BLOCK_DEVICE: return 'block'; - case NET_SFTP_TYPE_CHAR_DEVICE: return 'char'; - case NET_SFTP_TYPE_DIRECTORY: return 'dir'; - case NET_SFTP_TYPE_FIFO: return 'fifo'; - case NET_SFTP_TYPE_REGULAR: return 'file'; - case NET_SFTP_TYPE_SYMLINK: return 'link'; - default: return false; + case NET_SFTP_TYPE_BLOCK_DEVICE: + return 'block'; + case NET_SFTP_TYPE_CHAR_DEVICE: + return 'char'; + case NET_SFTP_TYPE_DIRECTORY: + return 'dir'; + case NET_SFTP_TYPE_FIFO: + return 'fifo'; + case NET_SFTP_TYPE_REGULAR: + return 'file'; + case NET_SFTP_TYPE_SYMLINK: + return 'link'; + default: + return false; } } diff --git a/phpseclib/Net/SSH1.php b/phpseclib/Net/SSH1.php index 5a504659..918c791e 100644 --- a/phpseclib/Net/SSH1.php +++ b/phpseclib/Net/SSH1.php @@ -597,7 +597,7 @@ class SSH1 // get a list of the supported ciphers extract(unpack('Nsupported_ciphers_mask', $this->_string_shift($response[self::RESPONSE_DATA], 4))); - foreach ($this->supported_ciphers as $mask=>$name) { + foreach ($this->supported_ciphers as $mask => $name) { if (($supported_ciphers_mask & (1 << $mask)) == 0) { unset($this->supported_ciphers[$mask]); } @@ -605,7 +605,7 @@ class SSH1 // get a list of the supported authentications extract(unpack('Nsupported_authentications_mask', $this->_string_shift($response[self::RESPONSE_DATA], 4))); - foreach ($this->supported_authentications as $mask=>$name) { + foreach ($this->supported_authentications as $mask => $name) { if (($supported_authentications_mask & (1 << $mask)) == 0) { unset($this->supported_authentications[$mask]); } @@ -727,7 +727,7 @@ class SSH1 if ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) { $this->bitmap |= self::MASK_LOGIN; return true; - } else if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) { + } elseif ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) { user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE'); return false; } @@ -753,7 +753,7 @@ class SSH1 if ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) { $this->bitmap |= self::MASK_LOGIN; return true; - } else if ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) { + } elseif ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) { return false; } else { user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE'); @@ -1266,7 +1266,7 @@ class SSH1 $crc = 0x00000000; $length = strlen($data); - for ($i=0;$i<$length;$i++) { + for ($i=0; $i<$length; $i++) { // We AND $crc >> 8 with 0x00FFFFFF because we want the eight newly added bits to all // be zero. PHP, unfortunately, doesn't always do this. 0x80000000 >> 8, as an example, // yields 0xFF800000 - not 0x00800000. The following link elaborates: @@ -1361,7 +1361,7 @@ class SSH1 { $args = func_get_args(); foreach ($args as $arg) { - foreach ($arg as $key=>$value) { + foreach ($arg as $key => $value) { if (!defined($value)) { define($value, $key); } else { diff --git a/phpseclib/Net/SSH2.php b/phpseclib/Net/SSH2.php index c4aa704c..0daf81dc 100644 --- a/phpseclib/Net/SSH2.php +++ b/phpseclib/Net/SSH2.php @@ -870,7 +870,9 @@ class SSH2 /** * Default Constructor. * - * @param String $host + * $host can either be a string, representing the host, or a stream resource. + * + * @param Mixed $host * @param optional Integer $port * @param optional Integer $timeout * @see \phpseclib\Net\SSH2::login() @@ -952,12 +954,22 @@ class SSH2 31 => 'NET_SSH2_MSG_KEXDH_GEX_GROUP', 32 => 'NET_SSH2_MSG_KEXDH_GEX_INIT', 33 => 'NET_SSH2_MSG_KEXDH_GEX_REPLY', - 34 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST') + 34 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST'), + // RFC 5656 - Elliptic Curves (for curve25519-sha256@libssh.org) + array(30 => 'NET_SSH2_MSG_KEX_ECDH_INIT', + 31 => 'NET_SSH2_MSG_KEX_ECDH_REPLY') ); - $this->host = $host; - $this->port = $port; - $this->timeout = $timeout; + if (is_resource($host)) { + $this->fsock = $host; + return; + } + + if (is_string($host)) { + $this->host = $host; + $this->port = $port; + $this->timeout = $timeout; + } } /** @@ -992,22 +1004,23 @@ class SSH2 $this->curTimeout = $this->timeout; - $host = $this->host . ':' . $this->port; - $this->last_packet = microtime(true); - $start = microtime(true); - $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout); - if (!$this->fsock) { - throw new \RuntimeException(rtrim("Cannot connect to $host. Error $errno. $errstr"))_; - } - $elapsed = microtime(true) - $start; + if (!is_resource($this->fsock)) { + $start = microtime(true); + $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout); + if (!$this->fsock) { + $host = $this->host . ':' . $this->port; + throw new \RuntimeException(rtrim("Cannot connect to $host. Error $errno. $errstr")); + } + $elapsed = microtime(true) - $start; - $this->curTimeout-= $elapsed; + $this->curTimeout-= $elapsed; - if ($this->curTimeout <= 0) { - $this->is_timeout = true; - return false; + if ($this->curTimeout <= 0) { + $this->is_timeout = true; + return false; + } } /* According to the SSH2 specs, @@ -1098,9 +1111,13 @@ class SSH2 */ function _generate_identifier() { - $identifier = 'SSH-2.0-phpseclib_0.3'; + $identifier = 'SSH-2.0-phpseclib_2.0'; $ext = array(); + if (extension_loaded('libsodium')) { + $ext[] = 'libsodium'; + } + if (extension_loaded('openssl')) { $ext[] = 'openssl'; } elseif (extension_loaded('mcrypt')) { @@ -1131,98 +1148,108 @@ class SSH2 */ function _key_exchange($kexinit_payload_server) { - static $kex_algorithms = array( + $kex_algorithms = array( + // Elliptic Curve Diffie-Hellman Key Agreement (ECDH) using + // Curve25519. See doc/curve25519-sha256@libssh.org.txt in the + // libssh repository for more information. + 'curve25519-sha256@libssh.org', + + // Diffie-Hellman Key Agreement (DH) using integer modulo prime + // groups. 'diffie-hellman-group1-sha1', // REQUIRED 'diffie-hellman-group14-sha1', // REQUIRED 'diffie-hellman-group-exchange-sha1', // RFC 4419 'diffie-hellman-group-exchange-sha256', // RFC 4419 ); + if (!class_exists('\Sodium')) { + $kex_algorithms = array_diff( + $kex_algorithms, + array('curve25519-sha256@libssh.org') + ); + } - static $server_host_key_algorithms = array( + $server_host_key_algorithms = array( 'ssh-rsa', // RECOMMENDED sign Raw RSA Key 'ssh-dss' // REQUIRED sign Raw DSS Key ); - static $encryption_algorithms = false; - if ($encryption_algorithms === false) { - $encryption_algorithms = array( - // from : - 'arcfour256', - 'arcfour128', + $encryption_algorithms = array( + // from : + 'arcfour256', + 'arcfour128', - //'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key + //'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key - // CTR modes from : - 'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key - 'aes192-ctr', // RECOMMENDED AES with 192-bit key - 'aes256-ctr', // RECOMMENDED AES with 256-bit key + // CTR modes from : + 'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key + 'aes192-ctr', // RECOMMENDED AES with 192-bit key + 'aes256-ctr', // RECOMMENDED AES with 256-bit key - 'twofish128-ctr', // OPTIONAL Twofish in SDCTR mode, with 128-bit key - 'twofish192-ctr', // OPTIONAL Twofish with 192-bit key - 'twofish256-ctr', // OPTIONAL Twofish with 256-bit key + 'twofish128-ctr', // OPTIONAL Twofish in SDCTR mode, with 128-bit key + 'twofish192-ctr', // OPTIONAL Twofish with 192-bit key + 'twofish256-ctr', // OPTIONAL Twofish with 256-bit key - 'aes128-cbc', // RECOMMENDED AES with a 128-bit key - 'aes192-cbc', // OPTIONAL AES with a 192-bit key - 'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key + 'aes128-cbc', // RECOMMENDED AES with a 128-bit key + 'aes192-cbc', // OPTIONAL AES with a 192-bit key + 'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key - 'twofish128-cbc', // OPTIONAL Twofish with a 128-bit key - 'twofish192-cbc', // OPTIONAL Twofish with a 192-bit key - 'twofish256-cbc', - 'twofish-cbc', // OPTIONAL alias for "twofish256-cbc" - // (this is being retained for historical reasons) + 'twofish128-cbc', // OPTIONAL Twofish with a 128-bit key + 'twofish192-cbc', // OPTIONAL Twofish with a 192-bit key + 'twofish256-cbc', + 'twofish-cbc', // OPTIONAL alias for "twofish256-cbc" + // (this is being retained for historical reasons) - 'blowfish-ctr', // OPTIONAL Blowfish in SDCTR mode + 'blowfish-ctr', // OPTIONAL Blowfish in SDCTR mode - 'blowfish-cbc', // OPTIONAL Blowfish in CBC mode + 'blowfish-cbc', // OPTIONAL Blowfish in CBC mode - '3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode + '3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode - '3des-cbc', // REQUIRED three-key 3DES in CBC mode - //'none' // OPTIONAL no encryption; NOT RECOMMENDED + '3des-cbc', // REQUIRED three-key 3DES in CBC mode + //'none' // OPTIONAL no encryption; NOT RECOMMENDED + ); + + if (extension_loaded('openssl') && !extension_loaded('mcrypt')) { + // OpenSSL does not support arcfour256 in any capacity and arcfour128 / arcfour support is limited to + // instances that do not use continuous buffers + $encryption_algorithms = array_diff( + $encryption_algorithms, + array('arcfour256', 'arcfour128', 'arcfour') ); - - if (extension_loaded('openssl') && !extension_loaded('mcrypt')) { - // OpenSSL does not support arcfour256 in any capacity and arcfour128 / arcfour support is limited to - // instances that do not use continuous buffers - $encryption_algorithms = array_diff( - $encryption_algorithms, - array('arcfour256', 'arcfour128', 'arcfour') - ); - } - - if (class_exists('\phpseclib\Crypt\RC4') === false) { - $encryption_algorithms = array_diff( - $encryption_algorithms, - array('arcfour256', 'arcfour128', 'arcfour') - ); - } - if (class_exists('\phpseclib\Crypt\Rijndael') === false) { - $encryption_algorithms = array_diff( - $encryption_algorithms, - array('aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc') - ); - } - if (class_exists('\phpseclib\Crypt\Twofish') === false) { - $encryption_algorithms = array_diff( - $encryption_algorithms, - array('twofish128-ctr', 'twofish192-ctr', 'twofish256-ctr', 'twofish128-cbc', 'twofish192-cbc', 'twofish256-cbc', 'twofish-cbc') - ); - } - if (class_exists('\phpseclib\Crypt\Blowfish') === false) { - $encryption_algorithms = array_diff( - $encryption_algorithms, - array('blowfish-ctr', 'blowfish-cbc') - ); - } - if (class_exists('\phpseclib\Crypt\TripleDES') === false) { - $encryption_algorithms = array_diff( - $encryption_algorithms, - array('3des-ctr', '3des-cbc') - ); - } - $encryption_algorithms = array_values($encryption_algorithms); } + if (class_exists('\phpseclib\Crypt\RC4') === false) { + $encryption_algorithms = array_diff( + $encryption_algorithms, + array('arcfour256', 'arcfour128', 'arcfour') + ); + } + if (class_exists('\phpseclib\Crypt\Rijndael') === false) { + $encryption_algorithms = array_diff( + $encryption_algorithms, + array('aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc') + ); + } + if (class_exists('\phpseclib\Crypt\Twofish') === false) { + $encryption_algorithms = array_diff( + $encryption_algorithms, + array('twofish128-ctr', 'twofish192-ctr', 'twofish256-ctr', 'twofish128-cbc', 'twofish192-cbc', 'twofish256-cbc', 'twofish-cbc') + ); + } + if (class_exists('\phpseclib\Crypt\Blowfish') === false) { + $encryption_algorithms = array_diff( + $encryption_algorithms, + array('blowfish-ctr', 'blowfish-cbc') + ); + } + if (class_exists('\phpseclib\Crypt\TripleDES') === false) { + $encryption_algorithms = array_diff( + $encryption_algorithms, + array('3des-ctr', '3des-cbc') + ); + } + $encryption_algorithms = array_values($encryption_algorithms); + $mac_algorithms = array( // from : 'hmac-sha2-256',// RECOMMENDED HMAC-SHA256 (digest length = key length = 32) @@ -1234,7 +1261,7 @@ class SSH2 //'none' // OPTIONAL no MAC; NOT RECOMMENDED ); - static $compression_algorithms = array( + $compression_algorithms = array( 'none' // REQUIRED no compression //'zlib' // OPTIONAL ZLIB (LZ77) compression ); @@ -1248,17 +1275,11 @@ class SSH2 )); } - static $str_kex_algorithms, $str_server_host_key_algorithms, - $encryption_algorithms_server_to_client, $mac_algorithms_server_to_client, $compression_algorithms_server_to_client, - $encryption_algorithms_client_to_server, $mac_algorithms_client_to_server, $compression_algorithms_client_to_server; - - if (empty($str_kex_algorithms)) { - $str_kex_algorithms = implode(',', $kex_algorithms); - $str_server_host_key_algorithms = implode(',', $server_host_key_algorithms); - $encryption_algorithms_server_to_client = $encryption_algorithms_client_to_server = implode(',', $encryption_algorithms); - $mac_algorithms_server_to_client = $mac_algorithms_client_to_server = implode(',', $mac_algorithms); - $compression_algorithms_server_to_client = $compression_algorithms_client_to_server = implode(',', $compression_algorithms); - } + $str_kex_algorithms = implode(',', $kex_algorithms); + $str_server_host_key_algorithms = implode(',', $server_host_key_algorithms); + $encryption_algorithms_server_to_client = $encryption_algorithms_client_to_server = implode(',', $encryption_algorithms); + $mac_algorithms_server_to_client = $mac_algorithms_client_to_server = implode(',', $mac_algorithms); + $compression_algorithms_server_to_client = $compression_algorithms_client_to_server = implode(',', $compression_algorithms); $client_cookie = Random::string(16); @@ -1300,14 +1321,32 @@ class SSH2 $first_kex_packet_follows = $first_kex_packet_follows != 0; // the sending of SSH2_MSG_KEXINIT could go in one of two places. this is the second place. - $kexinit_payload_client = pack('Ca*Na*Na*Na*Na*Na*Na*Na*Na*Na*Na*CN', - NET_SSH2_MSG_KEXINIT, $client_cookie, strlen($str_kex_algorithms), $str_kex_algorithms, - strlen($str_server_host_key_algorithms), $str_server_host_key_algorithms, strlen($encryption_algorithms_client_to_server), - $encryption_algorithms_client_to_server, strlen($encryption_algorithms_server_to_client), $encryption_algorithms_server_to_client, - strlen($mac_algorithms_client_to_server), $mac_algorithms_client_to_server, strlen($mac_algorithms_server_to_client), - $mac_algorithms_server_to_client, strlen($compression_algorithms_client_to_server), $compression_algorithms_client_to_server, - strlen($compression_algorithms_server_to_client), $compression_algorithms_server_to_client, 0, '', 0, '', - 0, 0 + $kexinit_payload_client = pack( + 'Ca*Na*Na*Na*Na*Na*Na*Na*Na*Na*Na*CN', + NET_SSH2_MSG_KEXINIT, + $client_cookie, + strlen($str_kex_algorithms), + $str_kex_algorithms, + strlen($str_server_host_key_algorithms), + $str_server_host_key_algorithms, + strlen($encryption_algorithms_client_to_server), + $encryption_algorithms_client_to_server, + strlen($encryption_algorithms_server_to_client), + $encryption_algorithms_server_to_client, + strlen($mac_algorithms_client_to_server), + $mac_algorithms_client_to_server, + strlen($mac_algorithms_server_to_client), + $mac_algorithms_server_to_client, + strlen($compression_algorithms_client_to_server), + $compression_algorithms_client_to_server, + strlen($compression_algorithms_server_to_client), + $compression_algorithms_server_to_client, + 0, + '', + 0, + '', + 0, + 0 ); if (!$this->_send_binary_packet($kexinit_payload_client)) { @@ -1316,199 +1355,141 @@ class SSH2 // here ends the second place. // we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange - for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_server_to_client); $i++); - if ($i == count($encryption_algorithms)) { - $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new \RuntimeException('No compatible server to client encryption algorithms found'); - } // we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the // diffie-hellman key exchange as fast as possible - $decrypt = $encryption_algorithms[$i]; - switch ($decrypt) { - case '3des-cbc': - case '3des-ctr': - $decryptKeyLength = 24; // eg. 192 / 8 - break; - case 'aes256-cbc': - case 'aes256-ctr': - case 'twofish-cbc': - case 'twofish256-cbc': - case 'twofish256-ctr': - $decryptKeyLength = 32; // eg. 256 / 8 - break; - case 'aes192-cbc': - case 'aes192-ctr': - case 'twofish192-cbc': - case 'twofish192-ctr': - $decryptKeyLength = 24; // eg. 192 / 8 - break; - case 'aes128-cbc': - case 'aes128-ctr': - case 'twofish128-cbc': - case 'twofish128-ctr': - case 'blowfish-cbc': - case 'blowfish-ctr': - $decryptKeyLength = 16; // eg. 128 / 8 - break; - case 'arcfour': - case 'arcfour128': - $decryptKeyLength = 16; // eg. 128 / 8 - break; - case 'arcfour256': - $decryptKeyLength = 32; // eg. 128 / 8 - break; - case 'none': - $decryptKeyLength = 0; + $decrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_server_to_client); + $decryptKeyLength = $this->_encryption_algorithm_to_key_size($decrypt); + if ($decryptKeyLength === null) { + $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); + throw new NoSupportedAlgorithmsException('No compatible server to client encryption algorithms found'); } - for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_client_to_server); $i++); - if ($i == count($encryption_algorithms)) { + $encrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_client_to_server); + $encryptKeyLength = $this->_encryption_algorithm_to_key_size($encrypt); + if ($encryptKeyLength === null) { $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); throw new NoSupportedAlgorithmsException('No compatible client to server encryption algorithms found'); } - $encrypt = $encryption_algorithms[$i]; - switch ($encrypt) { - case '3des-cbc': - case '3des-ctr': - $encryptKeyLength = 24; - break; - case 'aes256-cbc': - case 'aes256-ctr': - case 'twofish-cbc': - case 'twofish256-cbc': - case 'twofish256-ctr': - $encryptKeyLength = 32; - break; - case 'aes192-cbc': - case 'aes192-ctr': - case 'twofish192-cbc': - case 'twofish192-ctr': - $encryptKeyLength = 24; - break; - case 'aes128-cbc': - case 'aes128-ctr': - case 'twofish128-cbc': - case 'twofish128-ctr': - case 'blowfish-cbc': - case 'blowfish-ctr': - $encryptKeyLength = 16; - break; - case 'arcfour': - case 'arcfour128': - $encryptKeyLength = 16; - break; - case 'arcfour256': - $encryptKeyLength = 32; - break; - case 'none': - $encryptKeyLength = 0; - } - - $keyLength = $decryptKeyLength > $encryptKeyLength ? $decryptKeyLength : $encryptKeyLength; - // through diffie-hellman key exchange a symmetric key is obtained - for ($i = 0; $i < count($kex_algorithms) && !in_array($kex_algorithms[$i], $this->kex_algorithms); $i++); - if ($i == count($kex_algorithms)) { + $kex_algorithm = $this->_array_intersect_first($kex_algorithms, $this->kex_algorithms); + if ($kex_algorithm === false) { $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); throw new NoSupportedAlgorithmsException('No compatible key exchange algorithms found'); } - if (strpos($kex_algorithms[$i], 'diffie-hellman-group-exchange') === 0) { - $dh_group_sizes_packed = pack('NNN', - $this->kex_dh_group_size_min, - $this->kex_dh_group_size_preferred, - $this->kex_dh_group_size_max - ); - $packet = pack('Ca*', - NET_SSH2_MSG_KEXDH_GEX_REQUEST, - $dh_group_sizes_packed - ); - if (!$this->_send_binary_packet($packet)) { - return false; - } + // Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty. + $exchange_hash_rfc4419 = ''; - $response = $this->_get_binary_packet(); - if ($response === false) { - throw new \RuntimeException('Connection closed by server'); - } - extract(unpack('Ctype', $this->_string_shift($response, 1))); - if ($type != NET_SSH2_MSG_KEXDH_GEX_GROUP) { - throw new \UnexpectedValueException('Expected SSH_MSG_KEX_DH_GEX_GROUP'); - } - - extract(unpack('NprimeLength', $this->_string_shift($response, 4))); - $primeBytes = $this->_string_shift($response, $primeLength); - $prime = new BigInteger($primeBytes, -256); - - extract(unpack('NgLength', $this->_string_shift($response, 4))); - $gBytes = $this->_string_shift($response, $gLength); - $g = new BigInteger($gBytes, -256); - - $exchange_hash_rfc4419 = pack('a*Na*Na*', - $dh_group_sizes_packed, - $primeLength, $primeBytes, - $gLength, $gBytes - ); - - $clientKexInitMessage = NET_SSH2_MSG_KEXDH_GEX_INIT; - $serverKexReplyMessage = NET_SSH2_MSG_KEXDH_GEX_REPLY; + if ($kex_algorithm === 'curve25519-sha256@libssh.org') { + $x = Random::string(32); + $eBytes = \Sodium::crypto_box_publickey_from_secretkey($x); + $clientKexInitMessage = NET_SSH2_MSG_KEX_ECDH_INIT; + $serverKexReplyMessage = NET_SSH2_MSG_KEX_ECDH_REPLY; + $kexHash = new Hash('sha256'); } else { - switch ($kex_algorithms[$i]) { - // see http://tools.ietf.org/html/rfc2409#section-6.2 and - // http://tools.ietf.org/html/rfc2412, appendex E - case 'diffie-hellman-group1-sha1': - $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . - '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . - '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . - 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF'; - break; - // see http://tools.ietf.org/html/rfc3526#section-3 - case 'diffie-hellman-group14-sha1': - $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . - '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . - '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . - 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' . - '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' . - '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' . - 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' . - '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF'; - break; + if (strpos($kex_algorithm, 'diffie-hellman-group-exchange') === 0) { + $dh_group_sizes_packed = pack( + 'NNN', + $this->kex_dh_group_size_min, + $this->kex_dh_group_size_preferred, + $this->kex_dh_group_size_max + ); + $packet = pack( + 'Ca*', + NET_SSH2_MSG_KEXDH_GEX_REQUEST, + $dh_group_sizes_packed + ); + if (!$this->_send_binary_packet($packet)) { + return false; + } + + $response = $this->_get_binary_packet(); + if ($response === false) { + user_error('Connection closed by server'); + return false; + } + extract(unpack('Ctype', $this->_string_shift($response, 1))); + if ($type != NET_SSH2_MSG_KEXDH_GEX_GROUP) { + user_error('Expected SSH_MSG_KEX_DH_GEX_GROUP'); + return false; + } + + extract(unpack('NprimeLength', $this->_string_shift($response, 4))); + $primeBytes = $this->_string_shift($response, $primeLength); + $prime = new BigInteger($primeBytes, -256); + + extract(unpack('NgLength', $this->_string_shift($response, 4))); + $gBytes = $this->_string_shift($response, $gLength); + $g = new BigInteger($gBytes, -256); + + $exchange_hash_rfc4419 = pack( + 'a*Na*Na*', + $dh_group_sizes_packed, + $primeLength, + $primeBytes, + $gLength, + $gBytes + ); + + $clientKexInitMessage = NET_SSH2_MSG_KEXDH_GEX_INIT; + $serverKexReplyMessage = NET_SSH2_MSG_KEXDH_GEX_REPLY; + } else { + switch ($kex_algorithm) { + // see http://tools.ietf.org/html/rfc2409#section-6.2 and + // http://tools.ietf.org/html/rfc2412, appendex E + case 'diffie-hellman-group1-sha1': + $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . + '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . + '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . + 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF'; + break; + // see http://tools.ietf.org/html/rfc3526#section-3 + case 'diffie-hellman-group14-sha1': + $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . + '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . + '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . + 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' . + '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' . + '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' . + 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' . + '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF'; + break; + } + // For both diffie-hellman-group1-sha1 and diffie-hellman-group14-sha1 + // the generator field element is 2 (decimal) and the hash function is sha1. + $g = new BigInteger(2); + $prime = new BigInteger($prime, 16); + $clientKexInitMessage = NET_SSH2_MSG_KEXDH_INIT; + $serverKexReplyMessage = NET_SSH2_MSG_KEXDH_REPLY; } - // For both diffie-hellman-group1-sha1 and diffie-hellman-group14-sha1 - // the generator field element is 2 (decimal) and the hash function is sha1. - $g = new BigInteger(2); - $prime = new BigInteger($prime, 16); - $exchange_hash_rfc4419 = ''; - $clientKexInitMessage = NET_SSH2_MSG_KEXDH_INIT; - $serverKexReplyMessage = NET_SSH2_MSG_KEXDH_REPLY; + + switch ($kex_algorithm) { + case 'diffie-hellman-group-exchange-sha256': + $kexHash = new Hash('sha256'); + break; + default: + $kexHash = new Hash('sha1'); + } + + /* To increase the speed of the key exchange, both client and server may + reduce the size of their private exponents. It should be at least + twice as long as the key material that is generated from the shared + secret. For more details, see the paper by van Oorschot and Wiener + [VAN-OORSCHOT]. + + -- http://tools.ietf.org/html/rfc4419#section-6.2 */ + $one = new BigInteger(1); + $keyLength = min($kexHash->getLength(), max($encryptKeyLength, $decryptKeyLength)); + $max = $one->bitwise_leftShift(16 * $keyLength); // 2 * 8 * $keyLength + $max = $max->subtract($one); + + $x = $one->random($one, $max); + $e = $g->modPow($x, $prime); + + $eBytes = $e->toBytes(true); } - - switch ($kex_algorithms[$i]) { - case 'diffie-hellman-group-exchange-sha256': - $kexHash = new Hash('sha256'); - break; - default: - $kexHash = new Hash('sha1'); - } - - /* To increase the speed of the key exchange, both client and server may - reduce the size of their private exponents. It should be at least - twice as long as the key material that is generated from the shared - secret. For more details, see the paper by van Oorschot and Wiener - [VAN-OORSCHOT]. - - -- http://tools.ietf.org/html/rfc4419#section-6.2 */ - $one = new BigInteger(1); - $keyLength = min($keyLength, $kexHash->getLength()); - $max = $one->bitwise_leftShift(16 * $keyLength); // 2 * 8 * $keyLength - $max = $max->subtract($one); - - $x = $one->random($one, $max); - $e = $g->modPow($x, $prime); - - $eBytes = $e->toBytes(true); $data = pack('CNa*', $clientKexInitMessage, strlen($eBytes), $eBytes); if (!$this->_send_binary_packet($data)) { @@ -1533,7 +1514,6 @@ class SSH2 $temp = unpack('Nlength', $this->_string_shift($response, 4)); $fBytes = $this->_string_shift($response, $temp['length']); - $f = new BigInteger($fBytes, -256); $temp = unpack('Nlength', $this->_string_shift($response, 4)); $this->signature = $this->_string_shift($response, $temp['length']); @@ -1541,19 +1521,38 @@ class SSH2 $temp = unpack('Nlength', $this->_string_shift($this->signature, 4)); $this->signature_format = $this->_string_shift($this->signature, $temp['length']); - $key = $f->modPow($x, $prime); + if ($kex_algorithm === 'curve25519-sha256@libssh.org') { + if (strlen($fBytes) !== 32) { + user_error('Received curve25519 public key of invalid length.'); + return false; + } + $key = new BigInteger(\Sodium::crypto_scalarmult($x, $fBytes), 256); + \Sodium::sodium_memzero($x); + } else { + $f = new BigInteger($fBytes, -256); + $key = $f->modPow($x, $prime); + } $keyBytes = $key->toBytes(true); - $this->exchange_hash = pack('Na*Na*Na*Na*Na*a*Na*Na*Na*', - strlen($this->identifier), $this->identifier, - strlen($this->server_identifier), $this->server_identifier, - strlen($kexinit_payload_client), $kexinit_payload_client, - strlen($kexinit_payload_server), $kexinit_payload_server, - strlen($this->server_public_host_key), $this->server_public_host_key, + $this->exchange_hash = pack( + 'Na*Na*Na*Na*Na*a*Na*Na*Na*', + strlen($this->identifier), + $this->identifier, + strlen($this->server_identifier), + $this->server_identifier, + strlen($kexinit_payload_client), + $kexinit_payload_client, + strlen($kexinit_payload_server), + $kexinit_payload_server, + strlen($this->server_public_host_key), + $this->server_public_host_key, $exchange_hash_rfc4419, - strlen($eBytes), $eBytes, - strlen($fBytes), $fBytes, - strlen($keyBytes), $keyBytes + strlen($eBytes), + $eBytes, + strlen($fBytes), + $fBytes, + strlen($keyBytes), + $keyBytes ); $this->exchange_hash = $kexHash->hash($this->exchange_hash); @@ -1562,18 +1561,19 @@ class SSH2 $this->session_id = $this->exchange_hash; } - for ($i = 0; $i < count($server_host_key_algorithms) && !in_array($server_host_key_algorithms[$i], $this->server_host_key_algorithms); $i++); - if ($i == count($server_host_key_algorithms)) { + $server_host_key_algorithm = $this->_array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms); + if ($server_host_key_algorithm === false) { $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); throw new NoSupportedAlgorithmsException('No compatible server host key algorithms found'); } - if ($public_key_format != $server_host_key_algorithms[$i] || $this->signature_format != $server_host_key_algorithms[$i]) { + if ($public_key_format != $server_host_key_algorithm || $this->signature_format != $server_host_key_algorithm) { $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); throw new \RuntimeException('Server Host Key Algorithm Mismatch'); } - $packet = pack('C', + $packet = pack( + 'C', NET_SSH2_MSG_NEWKEYS ); @@ -1593,112 +1593,16 @@ class SSH2 throw new \UnexpectedValueException('Expected SSH_MSG_NEWKEYS'); } - switch ($encrypt) { - case '3des-cbc': - $this->encrypt = new TripleDES(); - // $this->encrypt_block_size = 64 / 8 == the default - break; - case '3des-ctr': - $this->encrypt = new TripleDES(Base::MODE_CTR); - // $this->encrypt_block_size = 64 / 8 == the default - break; - case 'aes256-cbc': - case 'aes192-cbc': - case 'aes128-cbc': - $this->encrypt = new Rijndael(); - $this->encrypt_block_size = 16; // eg. 128 / 8 - break; - case 'aes256-ctr': - case 'aes192-ctr': - case 'aes128-ctr': - $this->encrypt = new Rijndael(Base::MODE_CTR); - $this->encrypt_block_size = 16; // eg. 128 / 8 - break; - case 'blowfish-cbc': - $this->encrypt = new Blowfish(); - $this->encrypt_block_size = 8; - break; - case 'blowfish-ctr': - $this->encrypt = new Blowfish(Base::MODE_CTR); - $this->encrypt_block_size = 8; - break; - case 'twofish128-cbc': - case 'twofish192-cbc': - case 'twofish256-cbc': - case 'twofish-cbc': - $this->encrypt = new Twofish(); - $this->encrypt_block_size = 16; - break; - case 'twofish128-ctr': - case 'twofish192-ctr': - case 'twofish256-ctr': - $this->encrypt = new Twofish(Base::MODE_CTR); - $this->encrypt_block_size = 16; - break; - case 'arcfour': - case 'arcfour128': - case 'arcfour256': - $this->encrypt = new RC4(); - break; - case 'none': - //$this->encrypt = new Null(); - } - - switch ($decrypt) { - case '3des-cbc': - $this->decrypt = new TripleDES(); - break; - case '3des-ctr': - $this->decrypt = new TripleDES(Base::MODE_CTR); - break; - case 'aes256-cbc': - case 'aes192-cbc': - case 'aes128-cbc': - $this->decrypt = new Rijndael(); - $this->decrypt_block_size = 16; - break; - case 'aes256-ctr': - case 'aes192-ctr': - case 'aes128-ctr': - $this->decrypt = new Rijndael(Base::MODE_CTR); - $this->decrypt_block_size = 16; - break; - case 'blowfish-cbc': - $this->decrypt = new Blowfish(); - $this->decrypt_block_size = 8; - break; - case 'blowfish-ctr': - $this->decrypt = new Blowfish(Base::MODE_CTR); - $this->decrypt_block_size = 8; - break; - case 'twofish128-cbc': - case 'twofish192-cbc': - case 'twofish256-cbc': - case 'twofish-cbc': - $this->decrypt = new Twofish(); - $this->decrypt_block_size = 16; - break; - case 'twofish128-ctr': - case 'twofish192-ctr': - case 'twofish256-ctr': - $this->decrypt = new Twofish(Base::MODE_CTR); - $this->decrypt_block_size = 16; - break; - case 'arcfour': - case 'arcfour128': - case 'arcfour256': - $this->decrypt = new RC4(); - break; - case 'none': - //$this->decrypt = new Null(); - } - $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes); + $this->encrypt = $this->_encryption_algorithm_to_crypt_instance($encrypt); if ($this->encrypt) { if ($this->crypto_engine) { $this->encrypt->setEngine($this->crypto_engine); } + if ($this->encrypt->block_size) { + $this->encrypt_block_size = $this->encrypt->block_size; + } $this->encrypt->enableContinuousBuffer(); $this->encrypt->disablePadding(); @@ -1715,10 +1619,14 @@ class SSH2 $this->encrypt->setKey(substr($key, 0, $encryptKeyLength)); } + $this->decrypt = $this->_encryption_algorithm_to_crypt_instance($decrypt); if ($this->decrypt) { if ($this->crypto_engine) { $this->decrypt->setEngine($this->crypto_engine); } + if ($this->decrypt->block_size) { + $this->decrypt_block_size = $this->decrypt->block_size; + } $this->decrypt->enableContinuousBuffer(); $this->decrypt->disablePadding(); @@ -1749,14 +1657,14 @@ class SSH2 $this->decrypt->decrypt(str_repeat("\0", 1536)); } - for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_client_to_server); $i++); - if ($i == count($mac_algorithms)) { + $mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_client_to_server); + if ($mac_algorithm === false) { $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); throw new NoSupportedAlgorithmsException('No compatible client to server message authentication algorithms found'); } - $createKeyLength = 0; // ie. $mac_algorithms[$i] == 'none' - switch ($mac_algorithms[$i]) { + $createKeyLength = 0; // ie. $mac_algorithm == 'none' + switch ($mac_algorithm) { case 'hmac-sha2-256': $this->hmac_create = new Hash('sha256'); $createKeyLength = 32; @@ -1778,15 +1686,15 @@ class SSH2 $createKeyLength = 16; } - for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_server_to_client); $i++); - if ($i == count($mac_algorithms)) { + $mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_server_to_client); + if ($mac_algorithm === false) { $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); throw new NoSupportedAlgorithmsException('No compatible server to client message authentication algorithms found'); } $checkKeyLength = 0; $this->hmac_size = 0; - switch ($mac_algorithms[$i]) { + switch ($mac_algorithm) { case 'hmac-sha2-256': $this->hmac_check = new Hash('sha256'); $checkKeyLength = 32; @@ -1825,23 +1733,106 @@ class SSH2 } $this->hmac_check->setKey(substr($key, 0, $checkKeyLength)); - for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_server_to_client); $i++); - if ($i == count($compression_algorithms)) { + $compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_server_to_client); + if ($compression_algorithm === false) { $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); throw new NoSupportedAlgorithmsException('No compatible server to client compression algorithms found'); } - $this->decompress = $compression_algorithms[$i] == 'zlib'; + $this->decompress = $compression_algorithm == 'zlib'; - for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_client_to_server); $i++); - if ($i == count($compression_algorithms)) { + $compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_client_to_server); + if ($compression_algorithm === false) { $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); throw new NoSupportedAlgorithmsException('No compatible client to server compression algorithms found'); } - $this->compress = $compression_algorithms[$i] == 'zlib'; + $this->compress = $compression_algorithm == 'zlib'; return true; } + /** + * Maps an encryption algorithm name to the number of key bytes. + * + * @param String $algorithm Name of the encryption algorithm + * @return Mixed Number of bytes as an integer or null for unknown + * @access private + */ + function _encryption_algorithm_to_key_size($algorithm) + { + switch ($algorithm) { + case 'none': + return 0; + case 'aes128-cbc': + case 'aes128-ctr': + case 'arcfour': + case 'arcfour128': + case 'blowfish-cbc': + case 'blowfish-ctr': + case 'twofish128-cbc': + case 'twofish128-ctr': + return 16; + case '3des-cbc': + case '3des-ctr': + case 'aes192-cbc': + case 'aes192-ctr': + case 'twofish192-cbc': + case 'twofish192-ctr': + return 24; + case 'aes256-cbc': + case 'aes256-ctr': + case 'arcfour256': + case 'twofish-cbc': + case 'twofish256-cbc': + case 'twofish256-ctr': + return 32; + } + return null; + } + + /** + * Maps an encryption algorithm name to an instance of a subclass of + * \phpseclib\Crypt\Base. + * + * @param String $algorithm Name of the encryption algorithm + * @return Mixed Instance of \phpseclib\Crypt\Base or null for unknown + * @access private + */ + function _encryption_algorithm_to_crypt_instance($algorithm) + { + switch ($algorithm) { + case '3des-cbc': + return new TripleDES(); + case '3des-ctr': + return new TripleDES(Base::MODE_CTR); + case 'aes256-cbc': + case 'aes192-cbc': + case 'aes128-cbc': + return new Rijndael(); + case 'aes256-ctr': + case 'aes192-ctr': + case 'aes128-ctr': + return new Rijndael(Base::MODE_CTR); + case 'blowfish-cbc': + return new Blowfish(); + case 'blowfish-ctr': + return new Blowfish(Base::MODE_CTR); + case 'twofish128-cbc': + case 'twofish192-cbc': + case 'twofish256-cbc': + case 'twofish-cbc': + return new Twofish(); + case 'twofish128-ctr': + case 'twofish192-ctr': + case 'twofish256-ctr': + return new Twofish(Base::MODE_CTR); + case 'arcfour': + case 'arcfour128': + case 'arcfour256': + return new RC4(); + } + return null; + } + /** * Login * @@ -1910,8 +1901,11 @@ class SSH2 } if (!($this->bitmap & self::MASK_LOGIN_REQ)) { - $packet = pack('CNa*', - NET_SSH2_MSG_SERVICE_REQUEST, strlen('ssh-userauth'), 'ssh-userauth' + $packet = pack( + 'CNa*', + NET_SSH2_MSG_SERVICE_REQUEST, + strlen('ssh-userauth'), + 'ssh-userauth' ); if (!$this->_send_binary_packet($packet)) { @@ -1950,9 +1944,15 @@ class SSH2 } if (!isset($password)) { - $packet = pack('CNa*Na*Na*', - NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection', - strlen('none'), 'none' + $packet = pack( + 'CNa*Na*Na*', + NET_SSH2_MSG_USERAUTH_REQUEST, + strlen($username), + $username, + strlen('ssh-connection'), + 'ssh-connection', + strlen('none'), + 'none' ); if (!$this->_send_binary_packet($packet)) { @@ -1976,18 +1976,36 @@ class SSH2 } } - $packet = pack('CNa*Na*Na*CNa*', - NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection', - strlen('password'), 'password', 0, strlen($password), $password + $packet = pack( + 'CNa*Na*Na*CNa*', + NET_SSH2_MSG_USERAUTH_REQUEST, + strlen($username), + $username, + strlen('ssh-connection'), + 'ssh-connection', + strlen('password'), + 'password', + 0, + strlen($password), + $password ); // remove the username and password from the logged packet if (!defined('NET_SSH2_LOGGING')) { $logged = null; } else { - $logged = pack('CNa*Na*Na*CNa*', - NET_SSH2_MSG_USERAUTH_REQUEST, strlen('username'), 'username', strlen('ssh-connection'), 'ssh-connection', - strlen('password'), 'password', 0, strlen('password'), 'password' + $logged = pack( + 'CNa*Na*Na*CNa*', + NET_SSH2_MSG_USERAUTH_REQUEST, + strlen('username'), + 'username', + strlen('ssh-connection'), + 'ssh-connection', + strlen('password'), + 'password', + 0, + strlen('password'), + 'password' ); } @@ -2046,9 +2064,19 @@ class SSH2 */ function _keyboard_interactive_login($username, $password) { - $packet = pack('CNa*Na*Na*Na*Na*', - NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection', - strlen('keyboard-interactive'), 'keyboard-interactive', 0, '', 0, '' + $packet = pack( + 'CNa*Na*Na*Na*Na*', + NET_SSH2_MSG_USERAUTH_REQUEST, + strlen($username), + $username, + strlen('ssh-connection'), + 'ssh-connection', + strlen('keyboard-interactive'), + 'keyboard-interactive', + 0, + '', + 0, + '' ); if (!$this->_send_binary_packet($packet)) { @@ -2119,7 +2147,7 @@ class SSH2 // see http://tools.ietf.org/html/rfc4256#section-3.2 if (strlen($this->last_interactive_response)) { $this->last_interactive_response = ''; - } else if (defined('NET_SSH2_LOGGING')) { + } elseif (defined('NET_SSH2_LOGGING')) { $this->message_number_log[count($this->message_number_log) - 1] = str_replace( 'UNKNOWN', 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST', @@ -2216,13 +2244,25 @@ class SSH2 'e' => $publickey['e']->toBytes(true), 'n' => $publickey['n']->toBytes(true) ); - $publickey = pack('Na*Na*Na*', - strlen('ssh-rsa'), 'ssh-rsa', strlen($publickey['e']), $publickey['e'], strlen($publickey['n']), $publickey['n'] + $publickey = pack( + 'Na*Na*Na*', + strlen('ssh-rsa'), + 'ssh-rsa', + strlen($publickey['e']), + $publickey['e'], + strlen($publickey['n']), + $publickey['n'] ); - $part1 = pack('CNa*Na*Na*', - NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection', - strlen('publickey'), 'publickey' + $part1 = pack( + 'CNa*Na*Na*', + NET_SSH2_MSG_USERAUTH_REQUEST, + strlen($username), + $username, + strlen('ssh-connection'), + 'ssh-connection', + strlen('publickey'), + 'publickey' ); $part2 = pack('Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publickey), $publickey); @@ -2339,8 +2379,15 @@ class SSH2 // uses 0x4000, that's what will be used here, as well. $packet_size = 0x4000; - $packet = pack('CNa*N3', - NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', self::CHANNEL_EXEC, $this->window_size_server_to_client[self::CHANNEL_EXEC], $packet_size); + $packet = pack( + 'CNa*N3', + NET_SSH2_MSG_CHANNEL_OPEN, + strlen('session'), + 'session', + self::CHANNEL_EXEC, + $this->window_size_server_to_client[self::CHANNEL_EXEC], + $packet_size + ); if (!$this->_send_binary_packet($packet)) { return false; @@ -2355,9 +2402,22 @@ class SSH2 if ($this->request_pty === true) { $terminal_modes = pack('C', NET_SSH2_TTY_OP_END); - $packet = pack('CNNa*CNa*N5a*', - NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL_EXEC], strlen('pty-req'), 'pty-req', 1, strlen('vt100'), 'vt100', - $this->windowColumns, $this->windowRows, 0, 0, strlen($terminal_modes), $terminal_modes); + $packet = pack( + 'CNNa*CNa*N5a*', + NET_SSH2_MSG_CHANNEL_REQUEST, + $this->server_channels[self::CHANNEL_EXEC], + strlen('pty-req'), + 'pty-req', + 1, + strlen('vt100'), + 'vt100', + $this->windowColumns, + $this->windowRows, + 0, + 0, + strlen($terminal_modes), + $terminal_modes + ); if (!$this->_send_binary_packet($packet)) { return false; @@ -2390,8 +2450,16 @@ class SSH2 // although, in theory, the size of SSH_MSG_CHANNEL_REQUEST could exceed the maximum packet size established by // SSH_MSG_CHANNEL_OPEN_CONFIRMATION, RFC4254#section-5.1 states that the "maximum packet size" refers to the // "maximum size of an individual data packet". ie. SSH_MSG_CHANNEL_DATA. RFC4254#section-5.2 corroborates. - $packet = pack('CNNa*CNa*', - NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL_EXEC], strlen('exec'), 'exec', 1, strlen($command), $command); + $packet = pack( + 'CNNa*CNa*', + NET_SSH2_MSG_CHANNEL_REQUEST, + $this->server_channels[self::CHANNEL_EXEC], + strlen('exec'), + 'exec', + 1, + strlen($command), + $command + ); if (!$this->_send_binary_packet($packet)) { return false; } @@ -2449,8 +2517,15 @@ class SSH2 $this->window_size_server_to_client[self::CHANNEL_SHELL] = $this->window_size; $packet_size = 0x4000; - $packet = pack('CNa*N3', - NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', self::CHANNEL_SHELL, $this->window_size_server_to_client[self::CHANNEL_SHELL], $packet_size); + $packet = pack( + 'CNa*N3', + NET_SSH2_MSG_CHANNEL_OPEN, + strlen('session'), + 'session', + self::CHANNEL_SHELL, + $this->window_size_server_to_client[self::CHANNEL_SHELL], + $packet_size + ); if (!$this->_send_binary_packet($packet)) { return false; @@ -2464,9 +2539,22 @@ class SSH2 } $terminal_modes = pack('C', NET_SSH2_TTY_OP_END); - $packet = pack('CNNa*CNa*N5a*', - NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL_SHELL], strlen('pty-req'), 'pty-req', 1, strlen('vt100'), 'vt100', - $this->windowColumns, $this->windowRows, 0, 0, strlen($terminal_modes), $terminal_modes); + $packet = pack( + 'CNNa*CNa*N5a*', + NET_SSH2_MSG_CHANNEL_REQUEST, + $this->server_channels[self::CHANNEL_SHELL], + strlen('pty-req'), + 'pty-req', + 1, + strlen('vt100'), + 'vt100', + $this->windowColumns, + $this->windowRows, + 0, + 0, + strlen($terminal_modes), + $terminal_modes + ); if (!$this->_send_binary_packet($packet)) { return false; @@ -2489,8 +2577,14 @@ class SSH2 throw new \UnexpectedValueException('Unable to request pseudo-terminal'); } - $packet = pack('CNNa*C', - NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL_SHELL], strlen('shell'), 'shell', 1); + $packet = pack( + 'CNNa*C', + NET_SSH2_MSG_CHANNEL_REQUEST, + $this->server_channels[self::CHANNEL_SHELL], + strlen('shell'), + 'shell', + 1 + ); if (!$this->_send_binary_packet($packet)) { return false; } @@ -2578,7 +2672,7 @@ class SSH2 $match = $expect; while (true) { if ($mode == self::READ_REGEX) { - preg_match($expect, $this->interactiveBuffer, $matches); + preg_match($expect, substr($this->interactiveBuffer, -1024), $matches); $match = isset($matches[0]) ? $matches[0] : ''; } $pos = strlen($match) ? strpos($this->interactiveBuffer, $match) : false; @@ -2635,8 +2729,15 @@ class SSH2 { $this->window_size_server_to_client[self::CHANNEL_SUBSYSTEM] = $this->window_size; - $packet = pack('CNa*N3', - NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', self::CHANNEL_SUBSYSTEM, $this->window_size, 0x4000); + $packet = pack( + 'CNa*N3', + NET_SSH2_MSG_CHANNEL_OPEN, + strlen('session'), + 'session', + self::CHANNEL_SUBSYSTEM, + $this->window_size, + 0x4000 + ); if (!$this->_send_binary_packet($packet)) { return false; @@ -2649,8 +2750,16 @@ class SSH2 return false; } - $packet = pack('CNNa*CNa*', - NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL_SUBSYSTEM], strlen('subsystem'), 'subsystem', 1, strlen($subsystem), $subsystem); + $packet = pack( + 'CNNa*CNa*', + NET_SSH2_MSG_CHANNEL_REQUEST, + $this->server_channels[self::CHANNEL_SUBSYSTEM], + strlen('subsystem'), + 'subsystem', + 1, + strlen($subsystem), + $subsystem + ); if (!$this->_send_binary_packet($packet)) { return false; } @@ -2660,7 +2769,7 @@ class SSH2 $response = $this->_get_channel_packet(self::CHANNEL_SUBSYSTEM); if ($response === false) { - return false; + return false; } $this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_DATA; @@ -2899,34 +3008,48 @@ class SSH2 extract(unpack('Nlength', $this->_string_shift($payload, 4))); $data = $this->_string_shift($payload, $length); extract(unpack('Nserver_channel', $this->_string_shift($payload, 4))); - switch($data) { + switch ($data) { case 'auth-agent': case 'auth-agent@openssh.com': if (isset($this->agent)) { - $new_channel = self::CHANNEL_AGENT_FORWARD; + $new_channel = self::CHANNEL_AGENT_FORWARD; - extract(unpack('Nremote_window_size', $this->_string_shift($payload, 4))); - extract(unpack('Nremote_maximum_packet_size', $this->_string_shift($payload, 4))); + extract(unpack('Nremote_window_size', $this->_string_shift($payload, 4))); + extract(unpack('Nremote_maximum_packet_size', $this->_string_shift($payload, 4))); - $this->packet_size_client_to_server[$new_channel] = $remote_window_size; - $this->window_size_server_to_client[$new_channel] = $remote_maximum_packet_size; - $this->window_size_client_to_server[$new_channel] = $this->window_size; + $this->packet_size_client_to_server[$new_channel] = $remote_window_size; + $this->window_size_server_to_client[$new_channel] = $remote_maximum_packet_size; + $this->window_size_client_to_server[$new_channel] = $this->window_size; - $packet_size = 0x4000; + $packet_size = 0x4000; - $packet = pack('CN4', - NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, $server_channel, $new_channel, $packet_size, $packet_size); + $packet = pack( + 'CN4', + NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, + $server_channel, + $new_channel, + $packet_size, + $packet_size + ); - $this->server_channels[$new_channel] = $server_channel; - $this->channel_status[$new_channel] = NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION; - if (!$this->_send_binary_packet($packet)) { - return false; - } + $this->server_channels[$new_channel] = $server_channel; + $this->channel_status[$new_channel] = NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION; + if (!$this->_send_binary_packet($packet)) { + return false; + } } break; default: - $packet = pack('CN3a*Na*', - NET_SSH2_MSG_REQUEST_FAILURE, $server_channel, NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED, 0, '', 0, ''); + $packet = pack( + 'CN3a*Na*', + NET_SSH2_MSG_REQUEST_FAILURE, + $server_channel, + NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED, + 0, + '', + 0, + '' + ); if (!$this->_send_binary_packet($packet)) { return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); @@ -3401,7 +3524,8 @@ class SSH2 ); $temp = $this->_string_shift($data, $max_size); - $packet = pack('CN2a*', + $packet = pack( + 'CN2a*', NET_SSH2_MSG_CHANNEL_DATA, $this->server_channels[$client_channel], strlen($temp), @@ -3442,7 +3566,8 @@ class SSH2 $this->curTimeout = 0; - while (!is_bool($this->_get_channel_packet($client_channel))); + while (!is_bool($this->_get_channel_packet($client_channel))) { + } if ($want_reply) { $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel])); @@ -3502,7 +3627,7 @@ class SSH2 { $args = func_get_args(); foreach ($args as $arg) { - foreach ($arg as $key=>$value) { + foreach ($arg as $key => $value) { if (!defined($value)) { define($value, $key); } else { @@ -3602,6 +3727,25 @@ class SSH2 } } + /** + * Returns the first value of the intersection of two arrays or false if + * the intersection is empty. The order is defined by the first parameter. + * + * @param Array $array1 + * @param Array $array2 + * @return Mixed False if intersection is empty, else intersected value. + * @access private + */ + function _array_intersect_first($array1, $array2) + { + foreach ($array1 as $value) { + if (in_array($value, $array2)) { + return $value; + } + } + return false; + } + /** * Returns all errors * diff --git a/phpseclib/System/SSH/Agent.php b/phpseclib/System/SSH/Agent.php index e53dfd5a..5ec47169 100644 --- a/phpseclib/System/SSH/Agent.php +++ b/phpseclib/System/SSH/Agent.php @@ -226,8 +226,14 @@ class Agent return false; } - $packet = pack('CNNa*C', - NET_SSH2_MSG_CHANNEL_REQUEST, $ssh->server_channels[$request_channel], strlen('auth-agent-req@openssh.com'), 'auth-agent-req@openssh.com', 1); + $packet = pack( + 'CNNa*C', + NET_SSH2_MSG_CHANNEL_REQUEST, + $ssh->server_channels[$request_channel], + strlen('auth-agent-req@openssh.com'), + 'auth-agent-req@openssh.com', + 1 + ); $ssh->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_REQUEST; diff --git a/tests/Functional/Net/SCPSSH2UserStoryTest.php b/tests/Functional/Net/SCPSSH2UserStoryTest.php index 6abd7e5f..41e86e95 100644 --- a/tests/Functional/Net/SCPSSH2UserStoryTest.php +++ b/tests/Functional/Net/SCPSSH2UserStoryTest.php @@ -15,7 +15,7 @@ class Functional_Net_SCPSSH2UserStoryTest extends PhpseclibFunctionalTestCase static protected $exampleData; static protected $exampleDataLength; - static public function setUpBeforeClass() + public static function setUpBeforeClass() { parent::setUpBeforeClass(); self::$remoteFile = uniqid('phpseclib-scp-ssh2-') . '.txt'; diff --git a/tests/Functional/Net/SFTPLargeFileTest.php b/tests/Functional/Net/SFTPLargeFileTest.php index 89d2c95a..cc170e8a 100644 --- a/tests/Functional/Net/SFTPLargeFileTest.php +++ b/tests/Functional/Net/SFTPLargeFileTest.php @@ -11,7 +11,7 @@ use phpseclib\Net\SFTP; class Functional_Net_SFTPLargeFileTest extends Functional_Net_SFTPTestCase { - static public function setUpBeforeClass() + public static function setUpBeforeClass() { if (!extension_loaded('mcrypt') && !extension_loaded('openssl')) { self::markTestSkipped('This test depends on mcrypt or openssl for performance.'); diff --git a/tests/Functional/Net/SFTPStreamTest.php b/tests/Functional/Net/SFTPStreamTest.php index d8c42ca3..b596c4f8 100644 --- a/tests/Functional/Net/SFTPStreamTest.php +++ b/tests/Functional/Net/SFTPStreamTest.php @@ -10,7 +10,7 @@ use phpseclib\Net\SFTP\Stream; class Functional_Net_SFTPStreamTest extends Functional_Net_SFTPTestCase { - static public function setUpBeforeClass() + public static function setUpBeforeClass() { Stream::register(); parent::setUpBeforeClass(); diff --git a/tests/Functional/Net/SFTPUserStoryTest.php b/tests/Functional/Net/SFTPUserStoryTest.php index 3b468426..57102ecb 100644 --- a/tests/Functional/Net/SFTPUserStoryTest.php +++ b/tests/Functional/Net/SFTPUserStoryTest.php @@ -15,7 +15,7 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase static protected $exampleDataLength; static protected $buffer; - static public function setUpBeforeClass() + public static function setUpBeforeClass() { parent::setUpBeforeClass(); @@ -164,7 +164,9 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase { $r = substr(self::$buffer, 0, $length); self::$buffer = substr(self::$buffer, $length); - if (strlen($r)) return $r; + if (strlen($r)) { + return $r; + } return null; } @@ -337,7 +339,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase if ($sftp->is_file($file)) { $cur_size = $sftp->size($file); $this->assertLessThanOrEqual( - $last_size, $cur_size, + $last_size, + $cur_size, 'Failed asserting that nlist() is in descending order' ); $last_size = $cur_size; @@ -388,7 +391,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase $stat = $sftp->stat('symlink'); $lstat = $sftp->lstat('symlink'); $this->assertNotEquals( - $stat, $lstat, + $stat, + $lstat, 'Failed asserting that stat and lstat returned different output for a symlink' ); @@ -421,7 +425,9 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase */ public function testReadlink($sftp) { - $this->assertInternalType('string', $sftp->readlink('symlink'), + $this->assertInternalType( + 'string', + $sftp->readlink('symlink'), 'Failed asserting that a symlink\'s target could be read' ); @@ -436,12 +442,14 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase { $stat = $sftp->stat('.'); $this->assertInternalType( - 'array', $stat, + 'array', + $stat, 'Failed asserting that stat on . returns an array' ); $lstat = $sftp->lstat('.'); $this->assertInternalType( - 'array', $lstat, + 'array', + $lstat, 'Failed asserting that lstat on . returns an array' ); @@ -596,5 +604,52 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase $sftp->stat(self::$scratchDir), 'Failed asserting that stat on a deleted directory returns false' ); + + return $sftp; + } + + /** + * @depends testDeleteEmptyDir + * @group github735 + */ + public function testStatVsLstat($sftp) + { + $this->assertTrue($sftp->mkdir(self::$scratchDir)); + $this->assertTrue($sftp->chdir(self::$scratchDir)); + $this->assertTrue($sftp->put('text.txt', 'zzzzz')); + $this->assertTrue($sftp->symlink('text.txt', 'link.txt')); + $this->assertTrue($sftp->mkdir('subdir')); + $this->assertTrue($sftp->symlink('subdir', 'linkdir')); + + $sftp->clearStatCache(); + + // pre-populate the stat cache + $sftp->nlist(); + + $stat = $sftp->stat('link.txt'); + $this->assertSame($stat['type'], NET_SFTP_TYPE_REGULAR); + $stat = $sftp->lstat('link.txt'); + $this->assertSame($stat['type'], NET_SFTP_TYPE_SYMLINK); + + $stat = $sftp->stat('linkdir'); + $this->assertSame($stat['type'], NET_SFTP_TYPE_DIRECTORY); + $stat = $sftp->lstat('link.txt'); + $this->assertSame($stat['type'], NET_SFTP_TYPE_SYMLINK); + + $sftp->disableStatCache(); + + $sftp->nlist(); + + $stat = $sftp->stat('link.txt'); + $this->assertSame($stat['type'], NET_SFTP_TYPE_REGULAR); + $stat = $sftp->lstat('link.txt'); + $this->assertSame($stat['type'], NET_SFTP_TYPE_SYMLINK); + + $stat = $sftp->stat('linkdir'); + $this->assertSame($stat['type'], NET_SFTP_TYPE_DIRECTORY); + $stat = $sftp->lstat('link.txt'); + $this->assertSame($stat['type'], NET_SFTP_TYPE_SYMLINK); + + $sftp->enableStatCache(); } } diff --git a/tests/Functional/Net/SSH2Test.php b/tests/Functional/Net/SSH2Test.php index 44f18d1e..51373705 100644 --- a/tests/Functional/Net/SSH2Test.php +++ b/tests/Functional/Net/SSH2Test.php @@ -87,4 +87,17 @@ class Functional_Net_SSH2Test extends PhpseclibFunctionalTestCase $this->assertInternalType('string', $ssh->getServerPublicHostKey()); } + + public function testOpenSocketConnect() + { + $fsock = fsockopen($this->getEnv('SSH_HOSTNAME'), 22); + $ssh = new SSH2($fsock); + + $username = $this->getEnv('SSH_USERNAME'); + $password = $this->getEnv('SSH_PASSWORD'); + $this->assertTrue( + $ssh->login($username, $password), + 'SSH2 login using an open socket failed.' + ); + } } diff --git a/tests/PhpseclibFunctionalTestCase.php b/tests/PhpseclibFunctionalTestCase.php index bbde05a3..e0b3a7cf 100644 --- a/tests/PhpseclibFunctionalTestCase.php +++ b/tests/PhpseclibFunctionalTestCase.php @@ -10,7 +10,7 @@ use phpseclib\Math\BigInteger; abstract class PhpseclibFunctionalTestCase extends PhpseclibTestCase { - static public function setUpBeforeClass() + public static function setUpBeforeClass() { if (extension_loaded('runkit')) { if (extension_loaded('gmp')) { diff --git a/tests/PhpseclibTestCase.php b/tests/PhpseclibTestCase.php index f7fce154..8f594e04 100644 --- a/tests/PhpseclibTestCase.php +++ b/tests/PhpseclibTestCase.php @@ -53,7 +53,7 @@ abstract class PhpseclibTestCase extends PHPUnit_Framework_TestCase * * @return null */ - static protected function ensureConstant($constant, $expected) + protected static function ensureConstant($constant, $expected) { if (defined($constant)) { $value = constant($constant); @@ -82,15 +82,15 @@ abstract class PhpseclibTestCase extends PHPUnit_Framework_TestCase } /** - * @param string $filename + * @param string $filename Filename relative to library directory. * * @return null */ - static protected function reRequireFile($filename) + protected static function reRequireFile($filename) { if (function_exists('runkit_import')) { $result = runkit_import( - $filename, + sprintf('%s/../phpseclib/%s', __DIR__, $filename), RUNKIT_IMPORT_FUNCTIONS | RUNKIT_IMPORT_CLASS_METHODS | RUNKIT_IMPORT_OVERRIDE diff --git a/tests/Unit/Crypt/Hash/MD5Test.php b/tests/Unit/Crypt/Hash/MD5Test.php index 2de322da..431184ee 100644 --- a/tests/Unit/Crypt/Hash/MD5Test.php +++ b/tests/Unit/Crypt/Hash/MD5Test.php @@ -22,7 +22,7 @@ class Unit_Crypt_Hash_MD5Test extends Unit_Crypt_Hash_TestCase $this->assertHashesTo($this->getInstance(), $message, $result); } - static public function hashData() + public static function hashData() { return array( array('', 'd41d8cd98f00b204e9800998ecf8427e'), @@ -39,7 +39,7 @@ class Unit_Crypt_Hash_MD5Test extends Unit_Crypt_Hash_TestCase $this->assertHMACsTo($this->getInstance(), $key, $message, $result); } - static public function hmacData() + public static function hmacData() { return array( array('', '', '74e6f7298a9c2d168935f58c001bad88'), diff --git a/tests/Unit/Crypt/Hash/SHA256Test.php b/tests/Unit/Crypt/Hash/SHA256Test.php index 584483b8..bad46b36 100644 --- a/tests/Unit/Crypt/Hash/SHA256Test.php +++ b/tests/Unit/Crypt/Hash/SHA256Test.php @@ -22,7 +22,7 @@ class Unit_Crypt_Hash_SHA256Test extends Unit_Crypt_Hash_TestCase $this->assertHashesTo($this->getInstance(), $message, $result); } - static public function hashData() + public static function hashData() { return array( array( @@ -48,7 +48,7 @@ class Unit_Crypt_Hash_SHA256Test extends Unit_Crypt_Hash_TestCase $this->assertHMACsTo($this->getInstance(), $key, $message, $result); } - static public function hmacData() + public static function hmacData() { return array( // RFC 4231 diff --git a/tests/Unit/Crypt/Hash/SHA512Test.php b/tests/Unit/Crypt/Hash/SHA512Test.php index 78aede77..ad2e63e3 100644 --- a/tests/Unit/Crypt/Hash/SHA512Test.php +++ b/tests/Unit/Crypt/Hash/SHA512Test.php @@ -22,7 +22,7 @@ class Unit_Crypt_Hash_SHA512Test extends Unit_Crypt_Hash_TestCase $this->assertHashesTo($this->getInstance(), $message, $result); } - static public function hashData() + public static function hashData() { return array( array( @@ -48,7 +48,7 @@ class Unit_Crypt_Hash_SHA512Test extends Unit_Crypt_Hash_TestCase $this->assertHMACsTo($this->getInstance(), $key, $message, $result); } - static public function hmacData() + public static function hmacData() { return array( // RFC 4231 diff --git a/tests/Unit/Crypt/Hash/TestCase.php b/tests/Unit/Crypt/Hash/TestCase.php index 967e72e0..2ef63c6b 100644 --- a/tests/Unit/Crypt/Hash/TestCase.php +++ b/tests/Unit/Crypt/Hash/TestCase.php @@ -9,7 +9,7 @@ use phpseclib\Crypt\Hash; abstract class Unit_Crypt_Hash_TestCase extends PhpseclibTestCase { - static public function setUpBeforeClass() + public static function setUpBeforeClass() { if (!defined('CRYPT_HASH_MODE')) { define('CRYPT_HASH_MODE', Hash::MODE_INTERNAL); diff --git a/tests/Unit/Crypt/RSA/ModeTest.php b/tests/Unit/Crypt/RSA/ModeTest.php index 0b90210e..b11ac05b 100644 --- a/tests/Unit/Crypt/RSA/ModeTest.php +++ b/tests/Unit/Crypt/RSA/ModeTest.php @@ -43,4 +43,24 @@ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ $rsa->loadKey($privatekey); $this->assertEquals(trim($rsa->decrypt($result), "\0"), $plaintext); } + + /** + * @group github768 + */ + public function testPSSSigs() + { + $rsa = new RSA(); + $rsa->loadKey('-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqGKukO1De7zhZj6+H0qtjTkVx +wTCpvKe4eCZ0FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFnc +CzWBQ7RKNUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0T +p0GbMJDyR4e9T04ZZwIDAQAB +-----END PUBLIC KEY-----'); + + $sig = pack('H*', '1bd29a1d704a906cd7f726370ce1c63d8fb7b9a620871a05f3141a311c0d6e75fefb5d36dfb50d3ea2d37cd67992471419bfadd35da6e13b494' . + '058ddc9b568d4cfea13ddc3c62b86a6256f5f296980d1131d3eaec6089069a3de79983f73eae20198a18721338b4a66e9cfe80e4f8e4fcef7a5bead5cbb' . + 'b8ac4c76adffbc178c'); + + $this->assertTrue($rsa->verify('zzzz', $sig)); + } } diff --git a/tests/Unit/Crypt/TwofishTest.php b/tests/Unit/Crypt/TwofishTest.php index 7dc166cc..f47443e9 100644 --- a/tests/Unit/Crypt/TwofishTest.php +++ b/tests/Unit/Crypt/TwofishTest.php @@ -18,7 +18,7 @@ class Unit_Crypt_TwofishTest extends PhpseclibTestCase Base::ENGINE_OPENSSL => 'OpenSSL', ); - foreach ($engines as $engine=>$name) { + foreach ($engines as $engine => $name) { $tf = new Twofish(); $tf->disablePadding(); diff --git a/tests/Unit/File/X509/X509Test.php b/tests/Unit/File/X509/X509Test.php index 06c8efb3..045028aa 100644 --- a/tests/Unit/File/X509/X509Test.php +++ b/tests/Unit/File/X509/X509Test.php @@ -12,6 +12,55 @@ use phpseclib\Crypt\RSA; class Unit_File_X509_X509Test extends PhpseclibTestCase { + public function testExtensionMapping() + { + $test = '-----BEGIN CERTIFICATE----- +MIIG1jCCBL6gAwIBAgITUAAAAA0qg8bE6DhrLAAAAAAADTANBgkqhkiG9w0BAQsF +ADAiMSAwHgYDVQQDExcuU2VjdXJlIEVudGVycHJpc2UgQ0EgMTAeFw0xNTAyMjMx +NTE1MDdaFw0xNjAyMjMxNTE1MDdaMD8xFjAUBgoJkiaJk/IsZAEZFgZzZWN1cmUx +DjAMBgNVBAMTBVVzZXJzMRUwEwYDVQQDEwxtZXRhY2xhc3NpbmcwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMdG1CzR/gTalbLN9J+2cvMGeD7wsR7S78 +HU5hdwE+kECROjRAcjFBOR57ezSDrkmhkTzo28tj0oAHjOh8N9vuXtASfZSCXugx +H+ImJ+E7PA4aXBp+0H2hohW9sXNNCFiVNmJLX66O4bxIeKtVRq/+eSNijV4OOEkC +zMyTHAUbOFP0t6KoJtM1syNoQ1+fKdfcjz5XtiEzSVcp2zf0MwNFSeZSgGQ0jh8A +Kd6YVKA8ZnrqOWZxKETT+bBNTjIT0ggjQfzcE4zW2RzrN7zWabUowoU92+DAp4s3 +sAEywX9ISSge62DEzTnZZSf9bpoScAfT8raRFA3BkoJ/s4c4CgfPAgMBAAGjggLm +MIIC4jAdBgNVHQ4EFgQULlIyJL9+ZwAI/SkVdsJMxFOVp+EwHwYDVR0jBBgwFoAU +5nEIMEUT5mMd1WepmviwgK7dIzwwggEKBgNVHR8EggEBMIH+MIH7oIH4oIH1hoG5 +bGRhcDovLy9DTj0uU2VjdXJlJTIwRW50ZXJwcmlzZSUyMENBJTIwMSxDTj1hdXRo +LENOPUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxD +Tj1Db25maWd1cmF0aW9uLERDPXNlY3VyZT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25M +aXN0P2Jhc2U/b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnSGN2h0dHA6 +Ly9jcmwuc2VjdXJlb2JzY3VyZS5jb20vP2FjdGlvbj1jcmwmY2E9ZW50ZXJwcmlz +ZTEwgccGCCsGAQUFBwEBBIG6MIG3MIG0BggrBgEFBQcwAoaBp2xkYXA6Ly8vQ049 +LlNlY3VyZSUyMEVudGVycHJpc2UlMjBDQSUyMDEsQ049QUlBLENOPVB1YmxpYyUy +MEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9 +c2VjdXJlP2NBQ2VydGlmaWNhdGU/YmFzZT9vYmplY3RDbGFzcz1jZXJ0aWZpY2F0 +aW9uQXV0aG9yaXR5MBcGCSsGAQQBgjcUAgQKHggAVQBzAGUAcjAOBgNVHQ8BAf8E +BAMCBaAwKQYDVR0lBCIwIAYKKwYBBAGCNwoDBAYIKwYBBQUHAwQGCCsGAQUFBwMC +MC4GA1UdEQQnMCWgIwYKKwYBBAGCNxQCA6AVDBNtZXRhY2xhc3NpbmdAc2VjdXJl +MEQGCSqGSIb3DQEJDwQ3MDUwDgYIKoZIhvcNAwICAgCAMA4GCCqGSIb3DQMEAgIA +gDAHBgUrDgMCBzAKBggqhkiG9w0DBzANBgkqhkiG9w0BAQsFAAOCAgEAKNmjYh+h +cObJEM0CWgz50jOYKZ4M5iIxoAWgrYY9Pv+0O9aPjvPLzjd5bY322L8lxh5wy5my +DKmip+irzjdVdxzQfoyy+ceODmCbX9L6MfEDn0RBzdwjLe1/eOxE1na0sZztrVCc +yt5nI91NNGZJUcVqVQsIA/25FWlkvo/FTfuqTuXdQiEVM5MCKJI915anmTdugy+G +0CmBJALIxtyz5P7sZhaHZFNdpKnx82QsauErqjP9H0RXc6VXX5qt+tEDvYfSlFcc +0lv3aQnV/eIdfm7APJkQ3lmNWWQwdkVf7adXJ7KAAPHSt1yvSbVxThJR/jmIkyeQ +XW/TOP5m7JI/GrmvdlzI1AgwJ+zO8fOmCDuif99pDb1CvkzQ65RZ8p5J1ZV6hzlb +VvOhn4LDnT1jnTcEqigmx1gxM/5ifvMorXn/ItMjKPlb72vHpeF7OeKE8GHsvZAm +osHcKyJXbTIcXchmpZX1efbmCMJBqHgJ/qBTBMl9BX0+YqbTZyabRJSs9ezbTRn0 +oRYl21Q8EnvS71CemxEUkSsKJmfJKkQNCsOjc8AbX/V/X9R7LJkH3UEx6K2zQQKK +k6m17mi63YW/+iPCGOWZ2qXmY5HPEyyF2L4L4IDryFJ+8xLyw3pH9/yp5aHZDtp6 +833K6qyjgHJT+fUzSEYpiwF5rSBJIGClOCY= +-----END CERTIFICATE-----'; + + $x509 = new X509(); + + $cert = $x509->loadX509($test); + + $this->assertInternalType('array', $cert['tbsCertificate']['extensions'][3]['extnValue']); + } + public function testLoadUnsupportedExtension() { $test = '-----BEGIN CERTIFICATE----- diff --git a/tests/Unit/Math/BigInteger/BCMathTest.php b/tests/Unit/Math/BigInteger/BCMathTest.php index a53fce8c..691d4031 100644 --- a/tests/Unit/Math/BigInteger/BCMathTest.php +++ b/tests/Unit/Math/BigInteger/BCMathTest.php @@ -7,7 +7,7 @@ class Unit_Math_BigInteger_BCMathTest extends Unit_Math_BigInteger_TestCase { - static public function setUpBeforeClass() + public static function setUpBeforeClass() { if (!extension_loaded('bcmath')) { self::markTestSkipped('BCMath extension is not available.'); diff --git a/tests/Unit/Math/BigInteger/GMPTest.php b/tests/Unit/Math/BigInteger/GMPTest.php index 9bcac212..f344a4e8 100644 --- a/tests/Unit/Math/BigInteger/GMPTest.php +++ b/tests/Unit/Math/BigInteger/GMPTest.php @@ -7,7 +7,7 @@ class Unit_Math_BigInteger_GMPTest extends Unit_Math_BigInteger_TestCase { - static public function setUpBeforeClass() + public static function setUpBeforeClass() { if (!extension_loaded('gmp')) { self::markTestSkipped('GNU Multiple Precision (GMP) extension is not available.'); diff --git a/tests/Unit/Math/BigInteger/InternalOpenSSLTest.php b/tests/Unit/Math/BigInteger/InternalOpenSSLTest.php index 83781407..495401fd 100644 --- a/tests/Unit/Math/BigInteger/InternalOpenSSLTest.php +++ b/tests/Unit/Math/BigInteger/InternalOpenSSLTest.php @@ -7,7 +7,7 @@ class Unit_Math_BigInteger_InternalOpenSSLTest extends Unit_Math_BigInteger_TestCase { - static public function setUpBeforeClass() + public static function setUpBeforeClass() { if (!function_exists('openssl_public_encrypt')) { self::markTestSkipped('openssl_public_encrypt() function is not available.'); diff --git a/tests/Unit/Math/BigInteger/InternalTest.php b/tests/Unit/Math/BigInteger/InternalTest.php index 0e4e3dc0..599d94ae 100644 --- a/tests/Unit/Math/BigInteger/InternalTest.php +++ b/tests/Unit/Math/BigInteger/InternalTest.php @@ -7,7 +7,7 @@ class Unit_Math_BigInteger_InternalTest extends Unit_Math_BigInteger_TestCase { - static public function setUpBeforeClass() + public static function setUpBeforeClass() { parent::setUpBeforeClass(); diff --git a/tests/Unit/Math/BigInteger/TestCase.php b/tests/Unit/Math/BigInteger/TestCase.php index 2bcc2fb9..0b236d2e 100644 --- a/tests/Unit/Math/BigInteger/TestCase.php +++ b/tests/Unit/Math/BigInteger/TestCase.php @@ -7,12 +7,9 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase { - static public function setUpBeforeClass() + public static function setUpBeforeClass() { - include_once 'Math/BigInteger.php'; - parent::setUpBeforeClass(); - self::reRequireFile('Math/BigInteger.php'); } @@ -63,7 +60,7 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase public function testAdd() { $x = $this->getInstance('18446744073709551615'); - $y = $this->getInstance( '100000000000'); + $y = $this->getInstance('100000000000'); $a = $x->add($y); $b = $y->add($x); @@ -78,7 +75,7 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase public function testSubtract() { $x = $this->getInstance('18446744073709551618'); - $y = $this->getInstance( '4000000000000'); + $y = $this->getInstance('4000000000000'); $this->assertSame('18446740073709551618', (string) $x->subtract($y)); } diff --git a/tests/Unit/Net/SSH2Test.php b/tests/Unit/Net/SSH2Test.php index b2beed74..df9651af 100644 --- a/tests/Unit/Net/SSH2Test.php +++ b/tests/Unit/Net/SSH2Test.php @@ -39,12 +39,16 @@ class Unit_Net_SSH2Test extends PhpseclibTestCase public function testGenerateIdentifier() { $identifier = $this->createSSHMock()->_generate_identifier(); - $this->assertStringStartsWith('SSH-2.0-phpseclib_0.3', $identifier); + $this->assertStringStartsWith('SSH-2.0-phpseclib_2.0', $identifier); + + if (extension_loaded('libsodium')) { + $this->assertContains('libsodium', $identifier); + } if (extension_loaded('openssl')) { $this->assertContains('openssl', $identifier); $this->assertNotContains('mcrypt', $identifier); - } else if (extension_loaded('mcrypt')) { + } elseif (extension_loaded('mcrypt')) { $this->assertNotContains('openssl', $identifier); $this->assertContains('mcrypt', $identifier); } else { @@ -55,7 +59,7 @@ class Unit_Net_SSH2Test extends PhpseclibTestCase if (extension_loaded('gmp')) { $this->assertContains('gmp', $identifier); $this->assertNotContains('bcmath', $identifier); - } else if (extension_loaded('bcmath')) { + } elseif (extension_loaded('bcmath')) { $this->assertNotContains('gmp', $identifier); $this->assertContains('bcmath', $identifier); } else { diff --git a/travis/run-phpunit.sh b/travis/run-phpunit.sh index 600a1d94..5ee69d66 100755 --- a/travis/run-phpunit.sh +++ b/travis/run-phpunit.sh @@ -20,7 +20,7 @@ then PHPUNIT_ARGS="$PHPUNIT_ARGS -d zend.enable_gc=0" fi -if [ "$TRAVIS_PHP_VERSION" = 'hhvm' ] +if [ "$TRAVIS_PHP_VERSION" = 'hhvm' -o "$TRAVIS_PHP_VERSION" = '7.0' ] then find tests -type f -name "*Test.php" | \ parallel --gnu --keep-order \