*/
function _convertPublicKey($n, $e)
{
@@ -1213,6 +1219,7 @@ function. As is, the definitive authority on this encoding scheme isn't the IET
$length = $this->_decodeLength($temp);
switch ($this->_string_shift($temp, $length)) {
case "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01": // rsaEncryption
+ case "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0A": // rsaPSS
break;
case "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03": // pbeWithMD5AndDES-CBC
/*
@@ -1539,6 +1546,8 @@ function. As is, the definitive authority on this encoding scheme isn't the IET
return $components;
}
+
+ return false;
}
/**
@@ -1878,7 +1887,6 @@ function setPrivateKey($key = false, $type = false)
*
* @see self::getPublicKey()
* @access public
- * @param string $key
* @param int $type optional
*/
function getPublicKey($type = self::PUBLIC_FORMAT_PKCS8)
@@ -1936,7 +1944,6 @@ function getPublicKeyFingerprint($algorithm = 'md5')
*
* @see self::getPublicKey()
* @access public
- * @param string $key
* @param int $type optional
* @return mixed
*/
@@ -1961,8 +1968,7 @@ function getPrivateKey($type = self::PUBLIC_FORMAT_PKCS1)
*
* @see self::getPrivateKey()
* @access private
- * @param string $key
- * @param int $type optional
+ * @param int $mode optional
*/
function _getPrivatePublicKey($mode = self::PUBLIC_FORMAT_PKCS8)
{
@@ -2179,7 +2185,7 @@ function setMGFHash($hash)
* of the hash function Hash) and 0.
*
* @access public
- * @param int $format
+ * @param int $sLen
*/
function setSaltLength($sLen)
{
@@ -2212,7 +2218,7 @@ function _i2osp($x, $xLen)
* See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}.
*
* @access private
- * @param string $x
+ * @param int|string|resource $x
* @return \phpseclib\Math\BigInteger
*/
function _os2ip($x)
@@ -2439,7 +2445,7 @@ function _rsavp1($s)
*
* @access private
* @param string $mgfSeed
- * @param int $mgfLen
+ * @param int $maskLen
* @return string
*/
function _mgf1($mgfSeed, $maskLen)
@@ -2911,6 +2917,59 @@ function _emsa_pkcs1_v1_5_encode($m, $emLen)
return $em;
}
+ /**
+ * EMSA-PKCS1-V1_5-ENCODE (without NULL)
+ *
+ * Quoting https://tools.ietf.org/html/rfc8017#page-65,
+ *
+ * "The parameters field associated with id-sha1, id-sha224, id-sha256,
+ * id-sha384, id-sha512, id-sha512/224, and id-sha512/256 should
+ * generally be omitted, but if present, it shall have a value of type
+ * NULL"
+ *
+ * @access private
+ * @param string $m
+ * @param int $emLen
+ * @return string
+ */
+ function _emsa_pkcs1_v1_5_encode_without_null($m, $emLen)
+ {
+ $h = $this->hash->hash($m);
+ if ($h === false) {
+ return false;
+ }
+
+ switch ($this->hashName) {
+ case 'sha1':
+ $t = pack('H*', '301f300706052b0e03021a0414');
+ break;
+ case 'sha256':
+ $t = pack('H*', '302f300b06096086480165030402010420');
+ break;
+ case 'sha384':
+ $t = pack('H*', '303f300b06096086480165030402020430');
+ break;
+ case 'sha512':
+ $t = pack('H*', '304f300b06096086480165030402030440');
+ break;
+ default:
+ return false;
+ }
+ $t.= $h;
+ $tLen = strlen($t);
+
+ if ($emLen < $tLen + 11) {
+ user_error('Intended encoded message length too short');
+ return false;
+ }
+
+ $ps = str_repeat(chr(0xFF), $emLen - $tLen - 3);
+
+ $em = "\0\1$ps\0$t";
+
+ return $em;
+ }
+
/**
* RSASSA-PKCS1-V1_5-SIGN
*
@@ -2948,6 +3007,7 @@ function _rsassa_pkcs1_v1_5_sign($m)
*
* @access private
* @param string $m
+ * @param string $s
* @return string
*/
function _rsassa_pkcs1_v1_5_verify($m, $s)
@@ -2976,13 +3036,17 @@ function _rsassa_pkcs1_v1_5_verify($m, $s)
// EMSA-PKCS1-v1_5 encoding
$em2 = $this->_emsa_pkcs1_v1_5_encode($m, $this->k);
- if ($em2 === false) {
+ $em3 = $this->_emsa_pkcs1_v1_5_encode_without_null($m, $this->k);
+
+ if ($em2 === false && $em3 === false) {
user_error('RSA modulus too short');
return false;
}
// Compare
- return $this->_equals($em, $em2);
+
+ return ($em2 !== false && $this->_equals($em, $em2)) ||
+ ($em3 !== false && $this->_equals($em, $em3));
}
/**
@@ -3088,7 +3152,7 @@ function encrypt($plaintext)
*
* @see self::encrypt()
* @access public
- * @param string $plaintext
+ * @param string $ciphertext
* @return string
*/
function decrypt($ciphertext)
diff --git a/phpseclib/File/ANSI.php b/phpseclib/File/ANSI.php
index 334d10faf..b6874d357 100644
--- a/phpseclib/File/ANSI.php
+++ b/phpseclib/File/ANSI.php
@@ -203,8 +203,7 @@ function setDimensions($x, $y)
/**
* Set the number of lines that should be logged past the terminal height
*
- * @param int $x
- * @param int $y
+ * @param int $history
* @access public
*/
function setHistory($history)
@@ -316,19 +315,20 @@ function appendString($source)
$mods = explode(';', $match[1]);
foreach ($mods as $mod) {
switch ($mod) {
- case 0: // Turn off character attributes
+ case '':
+ case '0': // Turn off character attributes
$attr_cell = clone $this->base_attr_cell;
break;
- case 1: // Turn bold mode on
+ case '1': // Turn bold mode on
$attr_cell->bold = true;
break;
- case 4: // Turn underline mode on
+ case '4': // Turn underline mode on
$attr_cell->underline = true;
break;
- case 5: // Turn blinking mode on
+ case '5': // Turn blinking mode on
$attr_cell->blink = true;
break;
- case 7: // Turn reverse video on
+ case '7': // Turn reverse video on
$attr_cell->reverse = !$attr_cell->reverse;
$temp = $attr_cell->background;
$attr_cell->background = $attr_cell->foreground;
@@ -341,23 +341,23 @@ function appendString($source)
$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;
- case 33: $front = 'yellow'; break;
- case 34: $front = 'blue'; break;
- case 35: $front = 'magenta'; break;
- case 36: $front = 'cyan'; break;
- case 37: $front = 'white'; break;
-
- case 40: $back = 'black'; break;
- case 41: $back = 'red'; break;
- case 42: $back = 'green'; break;
- case 43: $back = 'yellow'; break;
- case 44: $back = 'blue'; break;
- case 45: $back = 'magenta'; break;
- case 46: $back = 'cyan'; break;
- case 47: $back = 'white'; break;
+ case '30': $front = 'black'; break;
+ case '31': $front = 'red'; break;
+ case '32': $front = 'green'; break;
+ case '33': $front = 'yellow'; break;
+ case '34': $front = 'blue'; break;
+ case '35': $front = 'magenta'; break;
+ case '36': $front = 'cyan'; break;
+ case '37': $front = 'white'; break;
+
+ case '40': $back = 'black'; break;
+ case '41': $back = 'red'; break;
+ case '42': $back = 'green'; break;
+ case '43': $back = 'yellow'; break;
+ case '44': $back = 'blue'; break;
+ case '45': $back = 'magenta'; break;
+ case '46': $back = 'cyan'; break;
+ case '47': $back = 'white'; break;
// @codingStandardsIgnoreEnd
default:
diff --git a/phpseclib/File/ASN1.php b/phpseclib/File/ASN1.php
index a304a000a..dc5b78f64 100644
--- a/phpseclib/File/ASN1.php
+++ b/phpseclib/File/ASN1.php
@@ -235,7 +235,7 @@ function _decode_ber($encoded, $start = 0, $encoded_pos = 0)
$current = array('start' => $start);
$type = ord($encoded[$encoded_pos++]);
- $start++;
+ $startOffset = 1;
$constructed = ($type >> 5) & 1;
@@ -245,13 +245,20 @@ function _decode_ber($encoded, $start = 0, $encoded_pos = 0)
// process septets (since the eighth bit is ignored, it's not an octet)
do {
$temp = ord($encoded[$encoded_pos++]);
+ $startOffset++;
$loop = $temp >> 7;
$tag <<= 7;
- $tag |= $temp & 0x7F;
- $start++;
+ $temp &= 0x7F;
+ // "bits 7 to 1 of the first subsequent octet shall not all be zero"
+ if ($startOffset == 2 && $temp == 0) {
+ return false;
+ }
+ $tag |= $temp;
} while ($loop);
}
+ $start+= $startOffset;
+
// Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13
$length = ord($encoded[$encoded_pos++]);
$start++;
@@ -344,13 +351,16 @@ function _decode_ber($encoded, $start = 0, $encoded_pos = 0)
switch ($tag) {
case self::TYPE_BOOLEAN:
// "The contents octets shall consist of a single octet." -- paragraph 8.2.1
- //if (strlen($content) != 1) {
- // return false;
- //}
+ if ($constructed || strlen($content) != 1) {
+ return false;
+ }
$current['content'] = (bool) ord($content[$content_pos]);
break;
case self::TYPE_INTEGER:
case self::TYPE_ENUMERATED:
+ if ($constructed) {
+ return false;
+ }
$current['content'] = new BigInteger(substr($content, $content_pos), -256);
break;
case self::TYPE_REAL: // not currently supported
@@ -370,15 +380,15 @@ function _decode_ber($encoded, $start = 0, $encoded_pos = 0)
$last = count($temp) - 1;
for ($i = 0; $i < $last; $i++) {
// all subtags should be bit strings
- //if ($temp[$i]['type'] != self::TYPE_BIT_STRING) {
- // return false;
- //}
+ if ($temp[$i]['type'] != self::TYPE_BIT_STRING) {
+ return false;
+ }
$current['content'].= substr($temp[$i]['content'], 1);
}
// all subtags should be bit strings
- //if ($temp[$last]['type'] != self::TYPE_BIT_STRING) {
- // return false;
- //}
+ if ($temp[$last]['type'] != self::TYPE_BIT_STRING) {
+ return false;
+ }
$current['content'] = $temp[$last]['content'][0] . $current['content'] . substr($temp[$i]['content'], 1);
}
break;
@@ -395,9 +405,9 @@ function _decode_ber($encoded, $start = 0, $encoded_pos = 0)
}
$content_pos += $temp['length'];
// all subtags should be octet strings
- //if ($temp['type'] != self::TYPE_OCTET_STRING) {
- // return false;
- //}
+ if ($temp['type'] != self::TYPE_OCTET_STRING) {
+ return false;
+ }
$current['content'].= $temp['content'];
$length+= $temp['length'];
}
@@ -408,12 +418,15 @@ function _decode_ber($encoded, $start = 0, $encoded_pos = 0)
break;
case self::TYPE_NULL:
// "The contents octets shall not contain any octets." -- paragraph 8.8.2
- //if (strlen($content)) {
- // return false;
- //}
+ if ($constructed || strlen($content)) {
+ return false;
+ }
break;
case self::TYPE_SEQUENCE:
case self::TYPE_SET:
+ if (!$constructed) {
+ return false;
+ }
$offset = 0;
$current['content'] = array();
$content_len = strlen($content);
@@ -434,7 +447,13 @@ function _decode_ber($encoded, $start = 0, $encoded_pos = 0)
}
break;
case self::TYPE_OBJECT_IDENTIFIER:
+ if ($constructed) {
+ return false;
+ }
$current['content'] = $this->_decodeOID(substr($content, $content_pos));
+ if ($current['content'] === false) {
+ return false;
+ }
break;
/* Each character string type shall be encoded as if it had been declared:
[UNIVERSAL x] IMPLICIT OCTET STRING
@@ -464,12 +483,20 @@ function _decode_ber($encoded, $start = 0, $encoded_pos = 0)
case self::TYPE_UTF8_STRING:
// ????
case self::TYPE_BMP_STRING:
+ if ($constructed) {
+ return false;
+ }
$current['content'] = substr($content, $content_pos);
break;
case self::TYPE_UTC_TIME:
case self::TYPE_GENERALIZED_TIME:
+ if ($constructed) {
+ return false;
+ }
$current['content'] = $this->_decodeTime(substr($content, $content_pos), $tag);
+ break;
default:
+ return false;
}
$start+= $length;
@@ -790,7 +817,7 @@ function asn1map($decoded, $mapping, $special = array())
*
* @param string $source
* @param string $mapping
- * @param int $idx
+ * @param array $special
* @return string
* @access public
*/
@@ -806,6 +833,7 @@ function encodeDER($source, $mapping, $special = array())
* @param string $source
* @param string $mapping
* @param int $idx
+ * @param array $special
* @return string
* @access private
*/
@@ -1126,6 +1154,11 @@ function _decodeOID($content)
$oid = array();
$pos = 0;
$len = strlen($content);
+
+ if (ord($content[$len - 1]) & 0x80) {
+ return false;
+ }
+
$n = new BigInteger();
while ($pos < $len) {
$temp = ord($content[$pos++]);
@@ -1161,7 +1194,7 @@ function _decodeOID($content)
* Called by _encode_der()
*
* @access private
- * @param string $content
+ * @param string $source
* @return string
*/
function _encodeOID($source)
diff --git a/phpseclib/File/X509.php b/phpseclib/File/X509.php
index ddbc61595..7b1b1cfad 100644
--- a/phpseclib/File/X509.php
+++ b/phpseclib/File/X509.php
@@ -1608,7 +1608,7 @@ function saveX509($cert, $format = self::FORMAT_PEM)
* Map extension values from octet string to extension-specific internal
* format.
*
- * @param array ref $root
+ * @param array $root (by reference)
* @param string $path
* @param object $asn1
* @access private
@@ -1661,7 +1661,7 @@ function _mapInExtensions(&$root, $path, $asn1)
* Map extension values from extension-specific internal format to
* octet string.
*
- * @param array ref $root
+ * @param array $root (by reference)
* @param string $path
* @param object $asn1
* @access private
@@ -1727,7 +1727,7 @@ function _mapOutExtensions(&$root, $path, $asn1)
* Map attribute values from ANY type to attribute-specific internal
* format.
*
- * @param array ref $root
+ * @param array $root (by reference)
* @param string $path
* @param object $asn1
* @access private
@@ -1768,7 +1768,7 @@ function _mapInAttributes(&$root, $path, $asn1)
* Map attribute values from attribute-specific internal format to
* ANY type.
*
- * @param array ref $root
+ * @param array $root (by reference)
* @param string $path
* @param object $asn1
* @access private
@@ -1811,7 +1811,7 @@ function _mapOutAttributes(&$root, $path, $asn1)
* Map DN values from ANY type to DN-specific internal
* format.
*
- * @param array ref $root
+ * @param array $root (by reference)
* @param string $path
* @param object $asn1
* @access private
@@ -1841,7 +1841,7 @@ function _mapInDNs(&$root, $path, $asn1)
* Map DN values from DN-specific internal format to
* ANY type.
*
- * @param array ref $root
+ * @param array $root (by reference)
* @param string $path
* @param object $asn1
* @access private
@@ -3195,7 +3195,8 @@ function getPublicKey()
/**
* Load a Certificate Signing Request
*
- * @param string $csr
+ * @param string|array $csr
+ * @param int $mode
* @access public
* @return mixed
*/
@@ -3332,7 +3333,7 @@ function saveCSR($csr, $format = self::FORMAT_PEM)
*
* https://developer.mozilla.org/en-US/docs/HTML/Element/keygen
*
- * @param string $csr
+ * @param string|array $spkac
* @access public
* @return mixed
*/
@@ -3403,7 +3404,7 @@ function loadSPKAC($spkac)
/**
* Save a SPKAC CSR request
*
- * @param array $csr
+ * @param string|array $spkac
* @param int $format optional
* @access public
* @return string
@@ -3447,6 +3448,7 @@ function saveSPKAC($spkac, $format = self::FORMAT_PEM)
* Load a Certificate Revocation List
*
* @param string $crl
+ * @param int $mode
* @access public
* @return mixed
*/
@@ -4043,8 +4045,7 @@ function signCRL($issuer, $crl, $signatureAlgorithm = 'sha1WithRSAEncryption')
/**
* X.509 certificate signing helper function.
*
- * @param object $key
- * @param \phpseclib\File\X509 $subject
+ * @param \phpseclib\File\X509 $key
* @param string $signatureAlgorithm
* @access public
* @return mixed
@@ -4119,7 +4120,7 @@ function setEndDate($date)
* Set Serial Number
*
* @param string $serial
- * @param $base optional
+ * @param int $base optional
* @access public
*/
function setSerialNumber($serial, $base = -256)
@@ -4782,7 +4783,6 @@ function setDomain()
* Set the IP Addresses's which the cert is to be valid for
*
* @access public
- * @param string $ipAddress optional
*/
function setIPAddress()
{
@@ -5054,11 +5054,16 @@ function _extractBER($str)
* subject=/O=organization/OU=org unit/CN=common name
* issuer=/O=organization/CN=common name
*/
- $temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1);
- // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff
- $temp = preg_replace('#-+[^-]+-+#', '', $temp);
+ if (strlen($str) > ini_get('pcre.backtrack_limit')) {
+ $temp = $str;
+ } else {
+ $temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1);
+ $temp = preg_replace('#-+END.*[\r\n ]*.*#ms', '', $str, 1);
+ }
// remove new lines
$temp = str_replace(array("\r", "\n", ' '), '', $temp);
+ // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff
+ $temp = preg_replace('#^-+[^-]+-+|-+[^-]+-+$#', '', $temp);
$temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
return $temp != false ? $temp : $str;
}
diff --git a/phpseclib/Math/BigInteger.php b/phpseclib/Math/BigInteger.php
index e7f664670..fc24b9145 100644
--- a/phpseclib/Math/BigInteger.php
+++ b/phpseclib/Math/BigInteger.php
@@ -243,7 +243,7 @@ class BigInteger
* ?>
*
*
- * @param $x base-10 number or base-$base number if $base set.
+ * @param int|string|resource $x base-10 number or base-$base number if $base set.
* @param int $base
* @return \phpseclib\Math\BigInteger
* @access public
@@ -658,11 +658,11 @@ function toBits($twos_compliment = false)
{
$hex = $this->toHex($twos_compliment);
$bits = '';
- for ($i = strlen($hex) - 8, $start = strlen($hex) & 7; $i >= $start; $i-=8) {
- $bits = str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT) . $bits;
+ for ($i = strlen($hex) - 6, $start = strlen($hex) % 6; $i >= $start; $i-=6) {
+ $bits = str_pad(decbin(hexdec(substr($hex, $i, 6))), 24, '0', STR_PAD_LEFT) . $bits;
}
if ($start) { // hexdec('') == 0
- $bits = str_pad(decbin(hexdec(substr($hex, 0, $start))), 8, '0', STR_PAD_LEFT) . $bits;
+ $bits = str_pad(decbin(hexdec(substr($hex, 0, $start))), 8 * $start, '0', STR_PAD_LEFT) . $bits;
}
$result = $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0');
@@ -1994,7 +1994,7 @@ function _squareReduce($x, $n, $mode)
*
* @see self::_slidingWindow()
* @access private
- * @param \phpseclib\Math\BigInteger
+ * @param \phpseclib\Math\BigInteger $n
* @return \phpseclib\Math\BigInteger
*/
function _mod2($n)
@@ -2688,7 +2688,7 @@ function abs()
* Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y).
*
* @param \phpseclib\Math\BigInteger $y
- * @return int < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
+ * @return int that is < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
* @access public
* @see self::equals()
* @internal Could return $this->subtract($x), but that's not as fast as what we do do.
@@ -3090,7 +3090,7 @@ function bitwise_rightRotate($shift)
*
* Byte length is equal to $length. Uses \phpseclib\Crypt\Random if it's loaded and mt_rand if it's not.
*
- * @param int $length
+ * @param int $size
* @return \phpseclib\Math\BigInteger
* @access private
*/
@@ -3557,7 +3557,7 @@ function _rshift($shift)
*
* Removes leading zeros and truncates (if necessary) to maintain the appropriate precision
*
- * @param \phpseclib\Math\BigInteger
+ * @param \phpseclib\Math\BigInteger $result
* @return \phpseclib\Math\BigInteger
* @see self::_trim()
* @access private
@@ -3634,8 +3634,8 @@ function _trim($value)
/**
* Array Repeat
*
- * @param $input Array
- * @param $multiplier mixed
+ * @param array $input
+ * @param mixed $multiplier
* @return array
* @access private
*/
@@ -3649,8 +3649,8 @@ function _array_repeat($input, $multiplier)
*
* Shifts binary strings $shift bits, essentially multiplying by 2**$shift.
*
- * @param $x String
- * @param $shift Integer
+ * @param string $x (by reference)
+ * @param int $shift
* @return string
* @access private
*/
@@ -3678,8 +3678,8 @@ function _base256_lshift(&$x, $shift)
*
* Shifts binary strings $shift bits, essentially dividing by 2**$shift and returning the remainder.
*
- * @param $x String
- * @param $shift Integer
+ * @param string $x (by referenc)
+ * @param int $shift
* @return string
* @access private
*/
diff --git a/phpseclib/Net/SFTP.php b/phpseclib/Net/SFTP.php
index 7c821377b..34741831b 100644
--- a/phpseclib/Net/SFTP.php
+++ b/phpseclib/Net/SFTP.php
@@ -259,6 +259,16 @@ class SFTP extends SSH2
*/
var $requestBuffer = array();
+ /**
+ * Preserve timestamps on file downloads / uploads
+ *
+ * @see self::get()
+ * @see self::put()
+ * @var bool
+ * @access private
+ */
+ var $preserveTime = false;
+
/**
* Default Constructor.
*
@@ -406,7 +416,6 @@ function __construct($host, $port = 22, $timeout = 10)
* Login
*
* @param string $username
- * @param string $password
* @return bool
* @access public
*/
@@ -1015,7 +1024,7 @@ function _list($dir, $raw = true)
uasort($contents, array(&$this, '_comparator'));
}
- return $raw ? $contents : array_keys($contents);
+ return $raw ? $contents : array_map('strval', array_keys($contents));
}
/**
@@ -1217,7 +1226,7 @@ function _remove_from_stat_cache($path)
*
* Mainly used by file_exists
*
- * @param string $dir
+ * @param string $path
* @return mixed
* @access private
*/
@@ -1772,6 +1781,8 @@ function symlink($target, $link)
* Creates a directory.
*
* @param string $dir
+ * @param int $mode
+ * @param bool $recursive
* @return bool
* @access public
*/
@@ -1804,6 +1815,7 @@ function mkdir($dir, $mode = -1, $recursive = false)
* Helper function for directory creation
*
* @param string $dir
+ * @param int $mode
* @return bool
* @access private
*/
@@ -2075,7 +2087,14 @@ function put($remote_file, $data, $mode = self::SOURCE_STRING, $start = -1, $loc
}
if ($mode & self::SOURCE_LOCAL_FILE) {
- fclose($fp);
+ if ($this->preserveTime) {
+ $stat = fstat($fp);
+ $this->touch($remote_file, $stat['mtime'], $stat['atime']);
+ }
+
+ if (isset($fp) && is_resource($fp)) {
+ fclose($fp);
+ }
}
return $this->_close_handle($handle);
@@ -2198,7 +2217,7 @@ function get($remote_file, $local_file = false, $offset = 0, $length = -1, $prog
$res_offset = $stat['size'];
} else {
$res_offset = 0;
- if ($local_file !== false) {
+ if ($local_file !== false && !is_callable($local_file)) {
$fp = fopen($local_file, 'wb');
if (!$fp) {
return false;
@@ -2208,7 +2227,7 @@ function get($remote_file, $local_file = false, $offset = 0, $length = -1, $prog
}
}
- $fclose_check = $local_file !== false && !is_resource($local_file);
+ $fclose_check = $local_file !== false && !is_callable($local_file) && !is_resource($local_file);
$start = $offset;
$read = 0;
@@ -2229,9 +2248,6 @@ function get($remote_file, $local_file = false, $offset = 0, $length = -1, $prog
}
$packet = null;
$read+= $packet_size;
- if (is_callable($progressCallback)) {
- call_user_func($progressCallback, $read);
- }
$i++;
}
@@ -2258,9 +2274,14 @@ function get($remote_file, $local_file = false, $offset = 0, $length = -1, $prog
$offset+= strlen($temp);
if ($local_file === false) {
$content.= $temp;
+ } elseif (is_callable($local_file)) {
+ $local_file($temp);
} else {
fputs($fp, $temp);
}
+ if (is_callable($progressCallback)) {
+ call_user_func($progressCallback, $offset);
+ }
$temp = null;
break;
case NET_SFTP_STATUS:
@@ -2292,6 +2313,11 @@ function get($remote_file, $local_file = false, $offset = 0, $length = -1, $prog
if ($fclose_check) {
fclose($fp);
+
+ if ($this->preserveTime) {
+ $stat = $this->stat($remote_file);
+ touch($local_file, $stat['mtime'], $stat['atime']);
+ }
}
if (!$this->_close_handle($handle)) {
@@ -2713,6 +2739,7 @@ function _get_lstat_cache_prop($path, $prop)
*
* @param string $path
* @param string $prop
+ * @param mixed $type
* @return mixed
* @access private
*/
@@ -2953,6 +2980,7 @@ function _parseLongname($longname)
*
* @param int $type
* @param string $data
+ * @param int $request_id
* @see self::_get_sftp_packet()
* @see self::_send_channel_packet()
* @return bool
@@ -2960,6 +2988,10 @@ function _parseLongname($longname)
*/
function _send_sftp_packet($type, $data, $request_id = 1)
{
+ // in SSH2.php the timeout is cumulative per function call. eg. exec() will
+ // timeout after 10s. but for SFTP.php it's cumulative per packet
+ $this->curTimeout = $this->timeout;
+
$packet = $this->use_request_id ?
pack('NCNa*', strlen($data) + 5, $type, $request_id, $data) :
pack('NCa*', strlen($data) + 1, $type, $data);
@@ -2972,9 +3004,17 @@ function _send_sftp_packet($type, $data, $request_id = 1)
$packet_type = '-> ' . $this->packet_types[$type] .
' (' . round($stop - $start, 4) . 's)';
if (NET_SFTP_LOGGING == self::LOG_REALTIME) {
- echo "\r\n" . $this->_format_log(array($data), array($packet_type)) . "\r\n
\r\n";
- flush();
- ob_flush();
+ switch (PHP_SAPI) {
+ case 'cli':
+ $start = $stop = "\r\n";
+ break;
+ default:
+ $start = '';
+ $stop = '
';
+ }
+ echo $start . $this->_format_log(array($data), array($packet_type)) . $stop;
+ @flush();
+ @ob_flush();
} else {
$this->packet_type_log[] = $packet_type;
if (NET_SFTP_LOGGING == self::LOG_COMPLEX) {
@@ -3081,9 +3121,17 @@ function _get_sftp_packet($request_id = null)
$packet_type = '<- ' . $this->packet_types[$this->packet_type] .
' (' . round($stop - $start, 4) . 's)';
if (NET_SFTP_LOGGING == self::LOG_REALTIME) {
- echo "\r\n" . $this->_format_log(array($packet), array($packet_type)) . "\r\n
\r\n";
- flush();
- ob_flush();
+ switch (PHP_SAPI) {
+ case 'cli':
+ $start = $stop = "\r\n";
+ break;
+ default:
+ $start = '';
+ $stop = '
';
+ }
+ echo $start . $this->_format_log(array($packet), array($packet_type)) . $stop;
+ @flush();
+ @ob_flush();
} else {
$this->packet_type_log[] = $packet_type;
if (NET_SFTP_LOGGING == self::LOG_COMPLEX) {
@@ -3176,4 +3224,24 @@ function _disconnect($reason)
$this->pwd = false;
parent::_disconnect($reason);
}
+
+ /**
+ * Enable Date Preservation
+ *
+ * @access public
+ */
+ function enableDatePreservation()
+ {
+ $this->preserveTime = true;
+ }
+
+ /**
+ * Disable Date Preservation
+ *
+ * @access public
+ */
+ function disableDatePreservation()
+ {
+ $this->preserveTime = false;
+ }
}
diff --git a/phpseclib/Net/SFTP/Stream.php b/phpseclib/Net/SFTP/Stream.php
index d2c4425de..ec9e5841a 100644
--- a/phpseclib/Net/SFTP/Stream.php
+++ b/phpseclib/Net/SFTP/Stream.php
@@ -410,7 +410,7 @@ function _stream_seek($offset, $whence)
{
switch ($whence) {
case SEEK_SET:
- if ($offset >= $this->size || $offset < 0) {
+ if ($offset < 0) {
return false;
}
break;
@@ -447,7 +447,9 @@ function _stream_metadata($path, $option, $var)
// and https://github.com/php/php-src/blob/master/main/php_streams.h#L592
switch ($option) {
case 1: // PHP_STREAM_META_TOUCH
- return $this->sftp->touch($path, $var[0], $var[1]);
+ $time = isset($var[0]) ? $var[0] : null;
+ $atime = isset($var[1]) ? $var[1] : null;
+ return $this->sftp->touch($path, $time, $atime);
case 2: // PHP_STREAM_OWNER_NAME
case 3: // PHP_STREAM_GROUP_NAME
return false;
@@ -626,7 +628,6 @@ function _mkdir($path, $mode, $options)
* $options. What does 8 correspond to?
*
* @param string $path
- * @param int $mode
* @param int $options
* @return bool
* @access public
@@ -768,8 +769,8 @@ function _stream_close()
* If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not
* NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method.
*
- * @param string
- * @param array
+ * @param string $name
+ * @param array $arguments
* @return mixed
* @access public
*/
diff --git a/phpseclib/Net/SSH1.php b/phpseclib/Net/SSH1.php
index ff48d5436..e372b8b92 100644
--- a/phpseclib/Net/SSH1.php
+++ b/phpseclib/Net/SSH1.php
@@ -812,6 +812,7 @@ function setTimeout($timeout)
* @see self::interactiveRead()
* @see self::interactiveWrite()
* @param string $cmd
+ * @param bool $block
* @return mixed
* @access public
*/
@@ -1385,7 +1386,6 @@ function _rsa_crypt($m, $key)
* named constants from it, using the value as the name of the constant and the index as the value of the constant.
* If any of the constants that would be defined already exists, none of the constants will be defined.
*
- * @param array $array
* @access private
*/
function _define_array()
@@ -1584,7 +1584,8 @@ function getServerIdentification()
*
* Makes sure that only the last 1MB worth of packets will be logged
*
- * @param string $data
+ * @param int $protocol_flags
+ * @param string $message
* @access private
*/
function _append_log($protocol_flags, $message)
diff --git a/phpseclib/Net/SSH2.php b/phpseclib/Net/SSH2.php
index ba83c9d0e..f8f8dcfde 100644
--- a/phpseclib/Net/SSH2.php
+++ b/phpseclib/Net/SSH2.php
@@ -687,6 +687,14 @@ class SSH2
*/
var $curTimeout;
+ /**
+ * Keep Alive Interval
+ *
+ * @see self::setKeepAlive()
+ * @access private
+ */
+ var $keepAlive;
+
/**
* Real-time log file pointer
*
@@ -1538,6 +1546,32 @@ function _key_exchange($kexinit_payload_server = false)
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
+ $server_host_key_algorithm = $this->_array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms);
+ if ($server_host_key_algorithm === false) {
+ user_error('No compatible server host key algorithms found');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
+ }
+
+ $mac_algorithm_in = $this->_array_intersect_first($s2c_mac_algorithms, $this->mac_algorithms_server_to_client);
+ if ($mac_algorithm_in === false) {
+ user_error('No compatible server to client message authentication algorithms found');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
+ }
+
+ $compression_algorithm_out = $this->_array_intersect_first($c2s_compression_algorithms, $this->compression_algorithms_client_to_server);
+ if ($compression_algorithm_out === false) {
+ user_error('No compatible client to server compression algorithms found');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
+ }
+ //$this->decompress = $compression_algorithm_out == 'zlib';
+
+ $compression_algorithm_in = $this->_array_intersect_first($s2c_compression_algorithms, $this->compression_algorithms_client_to_server);
+ if ($compression_algorithm_in === false) {
+ user_error('No compatible server to client compression algorithms found');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
+ }
+ //$this->compress = $compression_algorithm_in == 'zlib';
+
// Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty.
$exchange_hash_rfc4419 = '';
@@ -1773,12 +1807,6 @@ function _key_exchange($kexinit_payload_server = false)
$this->session_id = $this->exchange_hash;
}
- $server_host_key_algorithm = $this->_array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms);
- if ($server_host_key_algorithm === false) {
- user_error('No compatible server host key algorithms found');
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
switch ($server_host_key_algorithm) {
case 'ssh-dss':
$expected_key_format = 'ssh-dss';
@@ -1903,14 +1931,14 @@ function _key_exchange($kexinit_payload_server = false)
$this->decrypt->decrypt(str_repeat("\0", 1536));
}
- $mac_algorithm = $this->_array_intersect_first($c2s_mac_algorithms, $this->mac_algorithms_client_to_server);
- if ($mac_algorithm === false) {
+ $mac_algorithm_out = $this->_array_intersect_first($c2s_mac_algorithms, $this->mac_algorithms_client_to_server);
+ if ($mac_algorithm_out === false) {
user_error('No compatible client to server message authentication algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
$createKeyLength = 0; // ie. $mac_algorithm == 'none'
- switch ($mac_algorithm) {
+ switch ($mac_algorithm_out) {
case 'hmac-sha2-256':
$this->hmac_create = new Hash('sha256');
$createKeyLength = 32;
@@ -1931,17 +1959,11 @@ function _key_exchange($kexinit_payload_server = false)
$this->hmac_create = new Hash('md5-96');
$createKeyLength = 16;
}
- $this->hmac_create->name = $mac_algorithm;
-
- $mac_algorithm = $this->_array_intersect_first($s2c_mac_algorithms, $this->mac_algorithms_server_to_client);
- if ($mac_algorithm === false) {
- user_error('No compatible server to client message authentication algorithms found');
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
+ $this->hmac_create->name = $mac_algorithm_out;
$checkKeyLength = 0;
$this->hmac_size = 0;
- switch ($mac_algorithm) {
+ switch ($mac_algorithm_in) {
case 'hmac-sha2-256':
$this->hmac_check = new Hash('sha256');
$checkKeyLength = 32;
@@ -1967,7 +1989,7 @@ function _key_exchange($kexinit_payload_server = false)
$checkKeyLength = 16;
$this->hmac_size = 12;
}
- $this->hmac_check->name = $mac_algorithm;
+ $this->hmac_check->name = $mac_algorithm_in;
$key = $kexHash->hash($keyBytes . $this->exchange_hash . 'E' . $this->session_id);
while ($createKeyLength > strlen($key)) {
@@ -1981,20 +2003,6 @@ function _key_exchange($kexinit_payload_server = false)
}
$this->hmac_check->setKey(substr($key, 0, $checkKeyLength));
- $compression_algorithm = $this->_array_intersect_first($c2s_compression_algorithms, $this->compression_algorithms_client_to_server);
- if ($compression_algorithm === false) {
- user_error('No compatible client to server compression algorithms found');
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
- //$this->decompress = $compression_algorithm == 'zlib';
-
- $compression_algorithm = $this->_array_intersect_first($s2c_compression_algorithms, $this->compression_algorithms_client_to_server);
- if ($compression_algorithm === false) {
- user_error('No compatible server to client compression algorithms found');
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
- //$this->compress = $compression_algorithm == 'zlib';
-
return true;
}
@@ -2112,8 +2120,6 @@ function _bad_algorithm_candidate($algorithm)
* The $password parameter can be a plaintext password, a \phpseclib\Crypt\RSA object or an array
*
* @param string $username
- * @param mixed $password
- * @param mixed $...
* @return bool
* @see self::_login()
* @access public
@@ -2125,11 +2131,13 @@ function login($username)
// try logging with 'none' as an authentication method first since that's what
// PuTTY does
- if ($this->_login($username)) {
- return true;
- }
- if (count($args) == 1) {
- return false;
+ if (substr($this->server_identifier, 0, 13) != 'SSH-2.0-CoreFTP') {
+ if ($this->_login($username)) {
+ return true;
+ }
+ if (count($args) == 1) {
+ return false;
+ }
}
return call_user_func_array(array(&$this, '_login'), $args);
}
@@ -2138,8 +2146,6 @@ function login($username)
* Login Helper
*
* @param string $username
- * @param mixed $password
- * @param mixed $...
* @return bool
* @see self::_login_helper()
* @access private
@@ -2400,7 +2406,6 @@ function _keyboard_interactive_login($username, $password)
/**
* Handle the keyboard-interactive requests / responses.
*
- * @param string $responses...
* @return bool
* @access private
*/
@@ -2545,7 +2550,7 @@ function _ssh_agent_login($username, $agent)
* Login with an RSA private key
*
* @param string $username
- * @param \phpseclib\Crypt\RSA $password
+ * @param \phpseclib\Crypt\RSA $privatekey
* @return bool
* @access private
* @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
@@ -2629,6 +2634,13 @@ function _privatekey_login($username, $privatekey)
// we'll just take it on faith that the public key blob and the public key algorithm name are as
// they should be
$this->_updateLogHistory('UNKNOWN (60)', 'NET_SSH2_MSG_USERAUTH_PK_OK');
+ break;
+ case NET_SSH2_MSG_USERAUTH_SUCCESS:
+ $this->bitmap |= self::MASK_LOGIN;
+ return true;
+ default:
+ user_error('Unexpected response to publickey authentication pt 1');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
}
$packet = $part1 . chr(1) . $part2;
@@ -2663,7 +2675,8 @@ function _privatekey_login($username, $privatekey)
return true;
}
- return false;
+ user_error('Unexpected response to publickey authentication pt 2');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
}
/**
@@ -2680,6 +2693,19 @@ function setTimeout($timeout)
$this->timeout = $this->curTimeout = $timeout;
}
+ /**
+ * Set Keep Alive
+ *
+ * Sends an SSH2_MSG_IGNORE message every x seconds, if x is a positive non-zero number.
+ *
+ * @param int $interval
+ * @access public
+ */
+ function setKeepAlive($interval)
+ {
+ $this->keepAlive = $interval;
+ }
+
/**
* Get the output from stdError
*
@@ -2909,28 +2935,6 @@ function _initShell()
return false;
}
- $response = $this->_get_binary_packet();
- if ($response === false) {
- $this->bitmap = 0;
- user_error('Connection closed by server');
- return false;
- }
-
- if (!strlen($response)) {
- return false;
- }
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- switch ($type) {
- case NET_SSH2_MSG_CHANNEL_SUCCESS:
- // if a pty can't be opened maybe commands can still be executed
- case NET_SSH2_MSG_CHANNEL_FAILURE:
- break;
- default:
- user_error('Unable to request pseudo-terminal');
- return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
-
$packet = pack(
'CNNa*C',
NET_SSH2_MSG_CHANNEL_REQUEST,
@@ -2943,14 +2947,7 @@ function _initShell()
return false;
}
- $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_REQUEST;
-
- $response = $this->_get_channel_packet(self::CHANNEL_SHELL);
- if ($response === false) {
- return false;
- }
-
- $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_DATA;
+ $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_IGNORE;
$this->bitmap |= self::MASK_SHELL;
@@ -3318,6 +3315,54 @@ function _reset_connection($reason)
*/
function _get_binary_packet($skip_channel_filter = false)
{
+ if ($skip_channel_filter) {
+ $read = array($this->fsock);
+ $write = $except = null;
+
+ if ($this->curTimeout <= 0) {
+ if ($this->keepAlive <= 0) {
+ @stream_select($read, $write, $except, null);
+ } else {
+ if (!@stream_select($read, $write, $except, $this->keepAlive) && !count($read)) {
+ $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0));
+ return $this->_get_binary_packet(true);
+ }
+ }
+ } else {
+ if ($this->curTimeout < 0) {
+ $this->is_timeout = true;
+ return true;
+ }
+
+ $read = array($this->fsock);
+ $write = $except = null;
+
+ $start = microtime(true);
+
+ if ($this->keepAlive > 0 && $this->keepAlive < $this->curTimeout) {
+ if (!@stream_select($read, $write, $except, $this->keepAlive) && !count($read)) {
+ $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0));
+ $elapsed = microtime(true) - $start;
+ $this->curTimeout-= $elapsed;
+ return $this->_get_binary_packet(true);
+ }
+ $elapsed = microtime(true) - $start;
+ $this->curTimeout-= $elapsed;
+ }
+
+ $sec = floor($this->curTimeout);
+ $usec = 1000000 * ($this->curTimeout - $sec);
+
+ // on windows this returns a "Warning: Invalid CRT parameters detected" error
+ if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
+ $this->is_timeout = true;
+ return true;
+ }
+ $elapsed = microtime(true) - $start;
+ $this->curTimeout-= $elapsed;
+ }
+ }
+
if (!is_resource($this->fsock) || feof($this->fsock)) {
$this->bitmap = 0;
user_error('Connection closed prematurely');
@@ -3469,9 +3514,19 @@ function _filter($payload, $skip_channel_filter)
// only called when we've already logged in
if (($this->bitmap & self::MASK_CONNECTED) && $this->isAuthenticated()) {
switch (ord($payload[0])) {
+ case NET_SSH2_MSG_CHANNEL_REQUEST:
+ if (strlen($payload) == 31) {
+ extract(unpack('cpacket_type/Nchannel/Nlength', $payload));
+ if (substr($payload, 9, $length) == 'keepalive@openssh.com' && isset($this->server_channels[$channel])) {
+ if (ord(substr($payload, 9 + $length))) { // want reply
+ $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_SUCCESS, $this->server_channels[$channel]));
+ }
+ $payload = $this->_get_binary_packet($skip_channel_filter);
+ }
+ }
+ break;
case NET_SSH2_MSG_CHANNEL_DATA:
case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
- case NET_SSH2_MSG_CHANNEL_REQUEST:
case NET_SSH2_MSG_CHANNEL_CLOSE:
case NET_SSH2_MSG_CHANNEL_EOF:
if (!$skip_channel_filter && !empty($this->server_channels)) {
@@ -3651,8 +3706,9 @@ function isPTYEnabled()
*
* Returns the data as a string if it's available and false if not.
*
- * @param $client_channel
- * @return mixed
+ * @param int $client_channel
+ * @param bool $skip_extended
+ * @return mixed|bool
* @access private
*/
function _get_channel_packet($client_channel, $skip_extended = false)
@@ -3666,36 +3722,13 @@ function _get_channel_packet($client_channel, $skip_extended = false)
$response = $this->binary_packet_buffer;
$this->binary_packet_buffer = false;
} else {
- $read = array($this->fsock);
- $write = $except = null;
-
- if (!$this->curTimeout) {
- @stream_select($read, $write, $except, null);
- } else {
- if ($this->curTimeout < 0) {
- $this->is_timeout = true;
- return true;
- }
-
- $read = array($this->fsock);
- $write = $except = null;
-
- $start = microtime(true);
- $sec = floor($this->curTimeout);
- $usec = 1000000 * ($this->curTimeout - $sec);
- // on windows this returns a "Warning: Invalid CRT parameters detected" error
- if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
- $this->is_timeout = true;
- if ($client_channel == self::CHANNEL_EXEC && !$this->request_pty) {
- $this->_close_channel($client_channel);
- }
- return true;
+ $response = $this->_get_binary_packet(true);
+ if ($response === true && $this->is_timeout) {
+ if ($client_channel == self::CHANNEL_EXEC && !$this->request_pty) {
+ $this->_close_channel($client_channel);
}
- $elapsed = microtime(true) - $start;
- $this->curTimeout-= $elapsed;
+ return true;
}
-
- $response = $this->_get_binary_packet(true);
if ($response === false) {
$this->bitmap = 0;
user_error('Connection closed by server');
@@ -3843,6 +3876,16 @@ function _get_channel_packet($client_channel, $skip_extended = false)
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
}
break;
+ case NET_SSH2_MSG_IGNORE:
+ switch ($type) {
+ case NET_SSH2_MSG_CHANNEL_SUCCESS:
+ //$this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_DATA;
+ continue 3;
+ case NET_SSH2_MSG_CHANNEL_FAILURE:
+ user_error('Error opening channel');
+ return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
+ }
+ break;
case NET_SSH2_MSG_CHANNEL_REQUEST:
switch ($type) {
case NET_SSH2_MSG_CHANNEL_SUCCESS:
@@ -3862,6 +3905,10 @@ function _get_channel_packet($client_channel, $skip_extended = false)
switch ($type) {
case NET_SSH2_MSG_CHANNEL_DATA:
+ //if ($this->channel_status[$channel] == NET_SSH2_MSG_IGNORE) {
+ // $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_DATA;
+ //}
+
/*
if ($channel == self::CHANNEL_EXEC) {
// SCP requires null packets, such as this, be sent. further, in the case of the ssh.com SSH server
@@ -3962,7 +4009,7 @@ function _send_binary_packet($data, $logged = null)
$packet.= $hmac;
$start = microtime(true);
- $result = strlen($packet) == fputs($this->fsock, $packet);
+ $result = strlen($packet) == @fputs($this->fsock, $packet);
$stop = microtime(true);
if (defined('NET_SSH2_LOGGING')) {
@@ -3982,7 +4029,8 @@ function _send_binary_packet($data, $logged = null)
*
* Makes sure that only the last 1MB worth of packets will be logged
*
- * @param string $data
+ * @param string $message_number
+ * @param string $message
* @access private
*/
function _append_log($message_number, $message)
@@ -4187,7 +4235,6 @@ function _string_shift(&$string, $index = 1)
* named constants from it, using the value as the name of the constant and the index as the value of the constant.
* If any of the constants that would be defined already exists, none of the constants will be defined.
*
- * @param array $array
* @access private
*/
function _define_array()
@@ -4603,11 +4650,15 @@ function getSupportedEncryptionAlgorithms()
//'none' // OPTIONAL no encryption; NOT RECOMMENDED
);
- $engines = array(
- Base::ENGINE_OPENSSL,
- Base::ENGINE_MCRYPT,
- Base::ENGINE_INTERNAL
- );
+ if ($this->crypto_engine) {
+ $engines = array($this->crypto_engine);
+ } else {
+ $engines = array(
+ Base::ENGINE_OPENSSL,
+ Base::ENGINE_MCRYPT,
+ Base::ENGINE_INTERNAL
+ );
+ }
$ciphers = array();
foreach ($engines as $engine) {
diff --git a/tests/Functional/Net/SFTPLargeFileTest.php b/tests/Functional/Net/SFTPLargeFileTest.php
index cc170e8a1..69baa8ea7 100644
--- a/tests/Functional/Net/SFTPLargeFileTest.php
+++ b/tests/Functional/Net/SFTPLargeFileTest.php
@@ -16,6 +16,7 @@ public static function setUpBeforeClass()
if (!extension_loaded('mcrypt') && !extension_loaded('openssl')) {
self::markTestSkipped('This test depends on mcrypt or openssl for performance.');
}
+ self::ensureConstant('CRYPT_HASH_MODE', 3);
parent::setUpBeforeClass();
}
diff --git a/tests/Functional/Net/SFTPUserStoryTest.php b/tests/Functional/Net/SFTPUserStoryTest.php
index 5767eb9fc..ceffca1f3 100644
--- a/tests/Functional/Net/SFTPUserStoryTest.php
+++ b/tests/Functional/Net/SFTPUserStoryTest.php
@@ -135,6 +135,16 @@ public function testStatOnDir($sftp)
return $sftp;
}
+ static function demoCallback($length)
+ {
+ $r = substr(self::$buffer, 0, $length);
+ self::$buffer = substr(self::$buffer, $length);
+ if (strlen($r)) {
+ return $r;
+ }
+ return null;
+ }
+
/**
* @depends testStatOnDir
*/
@@ -160,16 +170,6 @@ public function testPutSizeGetFile($sftp)
return $sftp;
}
- static function callback($length)
- {
- $r = substr(self::$buffer, 0, $length);
- self::$buffer = substr(self::$buffer, $length);
- if (strlen($r)) {
- return $r;
- }
- return null;
- }
-
/**
* @depends testStatOnDir
*/
@@ -177,7 +177,7 @@ public function testPutSizeGetFileCallback($sftp)
{
self::$buffer = self::$exampleData;
$this->assertTrue(
- $sftp->put('file1.txt', array(__CLASS__, 'callback'), $sftp::SOURCE_CALLBACK),
+ $sftp->put('file1.txt', array(__CLASS__, 'demoCallback'), $sftp::SOURCE_CALLBACK),
'Failed asserting that example data could be successfully put().'
);
@@ -439,8 +439,7 @@ public function testLinkFile($sftp)
*/
public function testReadlink($sftp)
{
- $this->assertInternalType(
- 'string',
+ $this->assertIsString(
$sftp->readlink('symlink'),
'Failed asserting that a symlink\'s target could be read'
);
@@ -455,14 +454,12 @@ public function testReadlink($sftp)
public function testStatOnCWD($sftp)
{
$stat = $sftp->stat('.');
- $this->assertInternalType(
- 'array',
+ $this->assertIsArray(
$stat,
'Failed asserting that stat on . returns an array'
);
$lstat = $sftp->lstat('.');
- $this->assertInternalType(
- 'array',
+ $this->assertIsArray(
$lstat,
'Failed asserting that lstat on . returns an array'
);
@@ -604,8 +601,7 @@ public function testDeleteEmptyDir($sftp)
'Failed asserting that scratch directory could ' .
'be created.'
);
- $this->assertInternalType(
- 'array',
+ $this->assertIsArray(
$sftp->stat(self::$scratchDir),
'Failed asserting that stat on an existant empty directory returns an array'
);
diff --git a/tests/Functional/Net/SSH2Test.php b/tests/Functional/Net/SSH2Test.php
index 1a9217429..5356580ae 100644
--- a/tests/Functional/Net/SSH2Test.php
+++ b/tests/Functional/Net/SSH2Test.php
@@ -124,7 +124,7 @@ public function testGetServerPublicHostKey()
{
$ssh = new SSH2($this->getEnv('SSH_HOSTNAME'));
- $this->assertInternalType('string', $ssh->getServerPublicHostKey());
+ $this->assertIsString($ssh->getServerPublicHostKey());
}
public function testOpenSocketConnect()
diff --git a/tests/PhpseclibTestCase.php b/tests/PhpseclibTestCase.php
index 9da0d42ec..e07533a1b 100644
--- a/tests/PhpseclibTestCase.php
+++ b/tests/PhpseclibTestCase.php
@@ -101,4 +101,48 @@ protected static function reRequireFile($filename)
}
}
}
+
+ // assertIsArray was not introduced until PHPUnit 8
+ public static function assertIsArray($actual, $message = '')
+ {
+ if (method_exists('\PHPUnit\Framework\TestCase', 'assertIsArray')) {
+ parent::assertIsArray($actual, $message);
+ return;
+ }
+
+ parent::assertInternalType('array', $actual, $message);
+ }
+
+ // assertIsString was not introduced until PHPUnit 8
+ public static function assertIsString($actual, $message = '')
+ {
+ if (method_exists('\PHPUnit\Framework\TestCase', 'assertIsString')) {
+ parent::assertIsString($actual, $message);
+ return;
+ }
+
+ parent::assertInternalType('string', $actual, $message);
+ }
+
+ // assertContains is deprecated for strings in PHPUnit 8
+ public static function assertStringContainsString($needle, $haystack, $message = '')
+ {
+ if (method_exists('\PHPUnit\Framework\TestCase', 'assertStringContainsString')) {
+ parent::assertStringContainsString($needle, $haystack, $message);
+ return;
+ }
+
+ parent::assertContains($needle, $haystack, $message);
+ }
+
+ // assertNotContains is deprecated for strings in PHPUnit 8
+ public static function assertStringNotContainsString($needle, $haystack, $message = '')
+ {
+ if (method_exists('\PHPUnit\Framework\TestCase', 'assertStringContainsString')) {
+ parent::assertStringNotContainsString($needle, $haystack, $message);
+ return;
+ }
+
+ parent::assertNotContains($needle, $haystack, $message);
+ }
}
diff --git a/tests/Unit/Crypt/AES/InternalTest.php b/tests/Unit/Crypt/AES/PurePHPTest.php
similarity index 81%
rename from tests/Unit/Crypt/AES/InternalTest.php
rename to tests/Unit/Crypt/AES/PurePHPTest.php
index b0433e844..8692ec623 100644
--- a/tests/Unit/Crypt/AES/InternalTest.php
+++ b/tests/Unit/Crypt/AES/PurePHPTest.php
@@ -7,7 +7,7 @@
use phpseclib\Crypt\Base;
-class Unit_Crypt_AES_InternalTest extends Unit_Crypt_AES_TestCase
+class Unit_Crypt_AES_PurePHPTest extends Unit_Crypt_AES_TestCase
{
protected function setUp()
{
diff --git a/tests/Unit/Crypt/Hash/SHA256_96Test.php b/tests/Unit/Crypt/Hash/SHA256_96Test.php
index 85aaf295e..24a09be48 100644
--- a/tests/Unit/Crypt/Hash/SHA256_96Test.php
+++ b/tests/Unit/Crypt/Hash/SHA256_96Test.php
@@ -7,6 +7,10 @@
use phpseclib\Crypt\Hash;
+if (version_compare(PHP_VERSION, '7.0', '>=')) {
+ require 'SHA256Test.php';
+}
+
class Unit_Crypt_Hash_SHA256_96Test extends Unit_Crypt_Hash_SHA256Test
{
public function getInstance()
diff --git a/tests/Unit/Crypt/Hash/SHA512_96Test.php b/tests/Unit/Crypt/Hash/SHA512_96Test.php
index 760fa243a..0d48a7fb4 100644
--- a/tests/Unit/Crypt/Hash/SHA512_96Test.php
+++ b/tests/Unit/Crypt/Hash/SHA512_96Test.php
@@ -7,6 +7,10 @@
use phpseclib\Crypt\Hash;
+if (version_compare(PHP_VERSION, '7.0', '>=')) {
+ require 'SHA512Test.php';
+}
+
class Unit_Crypt_Hash_SHA512_96Test extends Unit_Crypt_Hash_SHA512Test
{
public function getInstance()
diff --git a/tests/Unit/Crypt/RSA/LoadKeyTest.php b/tests/Unit/Crypt/RSA/LoadKeyTest.php
index 09db5f538..ee3bcc59f 100644
--- a/tests/Unit/Crypt/RSA/LoadKeyTest.php
+++ b/tests/Unit/Crypt/RSA/LoadKeyTest.php
@@ -6,6 +6,7 @@
*/
use phpseclib\Crypt\RSA;
+use phpseclib\Math\BigInteger;
class Unit_Crypt_RSA_LoadKeyTest extends PhpseclibTestCase
{
@@ -37,7 +38,7 @@ public function testPKCS1Key()
-----END RSA PRIVATE KEY-----';
$this->assertTrue($rsa->loadKey($key));
- $this->assertInternalType('string', $rsa->getPrivateKey());
+ $this->assertIsString($rsa->getPrivateKey());
}
public function testPKCS1SpacesKey()
@@ -60,7 +61,7 @@ public function testPKCS1SpacesKey()
$key = str_replace(array("\r", "\n", "\r\n"), ' ', $key);
$this->assertTrue($rsa->loadKey($key));
- $this->assertInternalType('string', $rsa->getPrivateKey());
+ $this->assertIsString($rsa->getPrivateKey());
}
public function testPKCS1NoHeaderKey()
@@ -80,7 +81,7 @@ public function testPKCS1NoHeaderKey()
37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=';
$this->assertTrue($rsa->loadKey($key));
- $this->assertInternalType('string', $rsa->getPrivateKey());
+ $this->assertIsString($rsa->getPrivateKey());
}
public function testPKCS1NoWhitespaceNoHeaderKey()
@@ -100,7 +101,7 @@ public function testPKCS1NoWhitespaceNoHeaderKey()
'37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=';
$this->assertTrue($rsa->loadKey($key));
- $this->assertInternalType('string', $rsa->getPrivateKey());
+ $this->assertIsString($rsa->getPrivateKey());
}
public function testRawPKCS1Key()
@@ -121,7 +122,7 @@ public function testRawPKCS1Key()
$key = base64_decode($key);
$this->assertTrue($rsa->loadKey($key));
- $this->assertInternalType('string', $rsa->getPrivateKey());
+ $this->assertIsString($rsa->getPrivateKey());
}
public function testLoadPKCS8PrivateKey()
@@ -160,7 +161,7 @@ public function testLoadPKCS8PrivateKey()
-----END ENCRYPTED PRIVATE KEY-----';
$this->assertTrue($rsa->loadKey($key));
- $this->assertInternalType('string', $rsa->getPrivateKey());
+ $this->assertIsString($rsa->getPrivateKey());
}
public function testSavePKCS8PrivateKey()
@@ -185,7 +186,7 @@ public function testSavePKCS8PrivateKey()
$this->assertTrue($rsa->loadKey($key));
$key = $rsa->getPrivateKey(RSA::PRIVATE_FORMAT_PKCS8);
- $this->assertInternalType('string', $key);
+ $this->assertIsString($key);
$this->assertTrue($rsa->loadKey($key));
}
@@ -204,7 +205,7 @@ public function testPubKey1()
-----END RSA PUBLIC KEY-----';
$this->assertTrue($rsa->loadKey($key));
- $this->assertInternalType('string', $rsa->getPublicKey());
+ $this->assertIsString($rsa->getPublicKey());
$this->assertFalse($rsa->getPrivateKey());
}
@@ -223,10 +224,68 @@ public function testPubKey2()
-----END PUBLIC KEY-----';
$this->assertTrue($rsa->loadKey($key));
- $this->assertInternalType('string', $rsa->getPublicKey());
+ $this->assertIsString($rsa->getPublicKey());
$this->assertFalse($rsa->getPrivateKey());
}
+ public function testPubKeyPssWithoutParams()
+ {
+ $rsa = new RSA();
+
+ // extracted from a SubjectPublicKeyInfo of a CSR created by OpenSSL
+ $key = '-----BEGIN PUBLIC KEY-----
+MIIBIDALBgkqhkiG9w0BAQoDggEPADCCAQoCggEBANHPPf5tjTmEHtQvzi6+rItj
+G3OUvh6Nihc9bXSu0xNFjl/9TdyIXstRUG/Lh07isHgZFEfXn4pmm/iZIQh09ACg
+TjEau8rpcLB0BS9dDgTh8hvgkbdxWR2UPxk34bFcdgIplckslAfB4+/ebL+ObvUa
+W3sZosTq3D6/qh0fujGZg/EKLJcNCHI27XMiAT5yWztSjHWwQm7LBwJ5uKlFLEDC
+Z/+LIV/vPEIMfE6lA/+OnLKwVFB540eXQPuWar1ARHXN8PpiCqJHanddYMA5l/Cw
+5R7kJ+CBoHzaPePXjB9V1bfzEBzBHb2ddiSjum+qtLWuH0Q7B8gPX9EjxIwuCzMC
+AwEAAQ==
+-----END PUBLIC KEY-----';
+
+ $this->assertTrue($rsa->loadKey($key));
+ $this->assertIsString($rsa->getPublicKey());
+ $this->assertFalse($rsa->getPrivateKey());
+ }
+
+ public function testPrivateKeyPssWithoutParams()
+ {
+ $rsa = new RSA();
+
+ $key = '-----BEGIN PRIVATE KEY-----
+MIIEugIBADALBgkqhkiG9w0BAQoEggSmMIIEogIBAAKCAQEA0c89/m2NOYQe1C/O
+Lr6si2Mbc5S+Ho2KFz1tdK7TE0WOX/1N3Ihey1FQb8uHTuKweBkUR9efimab+Jkh
+CHT0AKBOMRq7yulwsHQFL10OBOHyG+CRt3FZHZQ/GTfhsVx2AimVySyUB8Hj795s
+v45u9RpbexmixOrcPr+qHR+6MZmD8Qoslw0IcjbtcyIBPnJbO1KMdbBCbssHAnm4
+qUUsQMJn/4shX+88Qgx8TqUD/46csrBUUHnjR5dA+5ZqvUBEdc3w+mIKokdqd11g
+wDmX8LDlHuQn4IGgfNo949eMH1XVt/MQHMEdvZ12JKO6b6q0ta4fRDsHyA9f0SPE
+jC4LMwIDAQABAoIBAFPuTMWAO7Obh92oNhn7CvlDr1KgWSHNy0UavLOl0ChwddEu
+erxTDWDWaZAfYkSLaL7SgYtv1ZG/FHvxfgZtCsNJXZ5FLISyt/LOpthYqGgJnxnJ
+z2EMBfNQP6Gt+ipCa67XxeTRYXJs/OsTFnvW1cpVPe1TxwpxTaQIdlvqOkjmgCci
+TRzH+Acj8unWDHAJpQkCOvmi+25sE0BMQYWnsfMSzm63Yk3SeZLIJKqoUdZhYMZU
+6FK2DMDNR4TZps7s50MFlZfUUJfzgb4Hb4miiKzLPhf4q7rxS4VzrvUQ/81ySCwi
+1LaSw5HoH1YMDT6rwcHMwHhzhu8X2CKlNIrri8ECgYEA7aiZAxmlY28LWcXHqqhZ
+Yky76vLy/mbs0TfAVK2pSqyFhaGZe5daAJSIrVcZEEgAwR6/ZLITTWBuGdsHw6vF
+GtSvkElLhopmQEs73kKqeBFLhpTqYXYVW0txi3jdWElie8fZa/Oa/sFLEeNsibQu
+fbVWWGakf9458FDuR0i2k+ECgYEA4gBu2u6xkJzqOzOjBg5tNhxmzcPyt4Ds3ryA
+e+C5hVCotd1EX6HZRPYjLEys0yUhiXDAn7ViEdtiXt9RYfpK+OKLGeTZ7pMCyZW+
+Yhc0i2XYqWSKUH3iNonp8B0JSkfEQBY2KlA7b5YZQZkr/Ml/WtoKeicHLBcdVxqa
+t7krQZMCgYBMU7GQxVPQs4E5u8N8k8ThRTO1KYHRIs08BGPIzl1oli/r0xKwFtPZ
+C9s5kJeEGxvi6jUd6fM5DpdNxoKf3TLYgyY/eMrA0wIz8/WuVErbdPKErp733izN
+vVUiLhcom6j9iBnUCdDlsL6jaB8burqTtQGeMpjyWDTTcaqVSk0ZAQKBgCqc1EoZ
+eYd/3rZc7R8mNzddsZCYorow5/izaDJzU+esJrNrzgmOFc5n7ofayTdip+knRlqW
+s7AUQn8K8mhb7ijxZjLysJjIRV1HC8epAnJKOMjvuRimM7H+3Qo2H1tPHtTKm1nt
+GNfYYFi7Dc0zHP0/YXxYwYRxs0mKLaP4mQxbAoGARHngPhGC0yM5KqxNrkHPVjLq
+CHQy+e9GTPXtDLC3D7HAYyyzKqy4mdBDzMeLqA3a+iT2PXjn4w5zOEW8GAcRYRtG
+3EyvclPmWtmCpU5xqD8ieFtQhMeW/XzJHjTXlcncz0PCkGVoQiuRvXWNAukNPg0D
+BocC2CO6SNi4Qjr3NlM=
+-----END PRIVATE KEY-----';
+
+ $this->assertTrue($rsa->loadKey($key));
+ $this->assertIsString($rsa->getPublicKey());
+ $this->assertIsString($rsa->getPrivateKey());
+ }
+
public function testSSHPubKey()
{
$rsa = new RSA();
@@ -237,7 +296,7 @@ public function testSSHPubKey()
'phpseclib-generated-key';
$this->assertTrue($rsa->loadKey($key));
- $this->assertInternalType('string', $rsa->getPublicKey());
+ $this->assertIsString($rsa->getPublicKey());
$this->assertFalse($rsa->getPrivateKey());
}
@@ -381,6 +440,18 @@ public function testSetLoad()
$rsa->loadKey($rsa);
}
+ public function testRaw()
+ {
+ $key = array(
+ 'e' => new BigInteger('010001', 16),
+ 'n' => new BigInteger('00d0991cd1dc9519de1a5a935742cb3a0f998b0c7995eab3f204f2663b81229474105bd38e2e657e1acd095d8178a1bdcb0a7631e491771ff99d8e705017cff26d6632665f9171734aa5f5d80cc0ea10ef5e8dfa2199af3b7bf69703104b8bdab5db0510b6a7cf61ec9799f25000a0994ec287b711075cfdad79b90da273172dc0fd2127181b45564c602c102d8e63929d53597f8be7ee5709885d42a5ddf8e3142432e35a61e8baeeb1a6dd23a6a74672c2a95ad974ace161813df32daaca8ce008e67d3a48c1e3ce8aa4ddfd2df644783f582c669892b91a8613f2a5c67f520845c53f09f6faa760ae0d1b0fd64953cb26f22317494d2fd5d9bc72b5f56f3ea1', 16)
+ );
+
+ $rsa = new RSA;
+ $this->assertTrue($rsa->loadKey($key));
+ $this->assertIsString("$rsa");
+ }
+
/**
* @group github980
*/
@@ -416,7 +487,7 @@ public function testGoodBad()
-----END RSA PUBLIC KEY-----';
$this->assertTrue($rsa->loadKey($key));
- $this->assertInternalType('string', $rsa->getPublicKey());
+ $this->assertIsString($rsa->getPublicKey());
$this->assertFalse($rsa->loadKey('zzz'));
$this->assertFalse($rsa->getPublicKey());
}
diff --git a/tests/Unit/Crypt/RSA/ModeTest.php b/tests/Unit/Crypt/RSA/ModeTest.php
index 788878b2b..854f90829 100644
--- a/tests/Unit/Crypt/RSA/ModeTest.php
+++ b/tests/Unit/Crypt/RSA/ModeTest.php
@@ -6,6 +6,7 @@
*/
use phpseclib\Crypt\RSA;
+use phpseclib\Math\BigInteger;
class Unit_Crypt_RSA_ModeTest extends PhpseclibTestCase
{
@@ -115,4 +116,26 @@ public function testPSSSigsWithNonPowerOf2Key()
$payload = 'eyJraWQiOiJ0RkMyVUloRnBUTV9FYTNxY09kX01xUVQxY0JCbTlrRkxTRGZlSmhzUkc4IiwiYWxnIjoiUFMyNTYifQ.eyJhcHAiOiJhY2NvdW50cG9ydGFsIiwic3ViIjoiNTliOGM4YzA5NTVhNDA5MDg2MGRmYmM3ZGQwMjVjZWEiLCJjbGlkIjoiZTQ5ZTA2N2JiMTFjNDcyMmEzNGIyYjNiOGE2YTYzNTUiLCJhbSI6InBhc3N3b3JkIiwicCI6ImVOcDFrRUZQd3pBTWhmXC9QdEVOYU5kQkc2bUZDNHNpbENNNXU0aTNXMHFSS0hFVDU5V1JzcXpZRUp4XC84M3ZQbkIxcUg3Rm5CZVNabEtNME9saGVZVUVWTXlHOEVUOEZnWDI4dkdqWG4wWkcrV2hSK01rWVBicGZacHI2U3E0N0RFYjBLYkRFT21CSUZuOTZKN1ZDaWg1Q2p4dWNRZDJmdHJlMCt2cSthZFFObUluK0poWEl0UlBvQ0xya1wvZ05VV3N3T09vSVwva0Q5ZVk4c05jRHFPUzNkanFWb3RPU21oRUo5b0hZZmFqZmpSRzFGSWpGRFwvOExtT2pKbVF3d0tBMnQ0aXJBQ2NncHo0dzBuN3BtXC84YXV2T0dFM2twVFZ2d0IzdzlQZk1YZnJJUTBhejRsaEtIdVBUMU42XC9sb1FJPSIsImlhaSI6IjU5YjhjOGMwOTU1YTQwOTA4NjBkZmJjN2RkMDI1Y2VhIiwiY2xzdmMiOiJhY2NvdW50cG9ydGFsIiwibHB2IjoxNTQ3Njc1NDM4LCJ0IjoicyIsImljIjp0cnVlLCJleHAiOjE1NDc3MDQyMzgsImlhdCI6MTU0NzY3NTQzOCwianRpIjoiZTE0N2UzM2UzNzVhNDkyNWJjMzdjZTRjMDIwMmJjNDYifQ';
$this->assertTrue($rsa->verify($payload, $sig));
}
+
+ public function testPKCS1SigWithoutNull()
+ {
+ $rsa = new RSA();
+ $rsa->loadKey(array(
+ 'n' => new BigInteger('0xE932AC92252F585B3A80A4DD76A897C8B7652952FE788F6EC8DD640587A1EE5647670A8AD
+4C2BE0F9FA6E49C605ADF77B5174230AF7BD50E5D6D6D6D28CCF0A886A514CC72E51D209CC7
+72A52EF419F6A953F3135929588EBE9B351FCA61CED78F346FE00DBB6306E5C2A4C6DFC3779
+AF85AB417371CF34D8387B9B30AE46D7A5FF5A655B8D8455F1B94AE736989D60A6F2FD5CADB
+FFBD504C5A756A2E6BB5CECC13BCA7503F6DF8B52ACE5C410997E98809DB4DC30D943DE4E81
+2A47553DCE54844A78E36401D13F77DC650619FED88D8B3926E3D8E319C80C744779AC5D6AB
+E252896950917476ECE5E8FC27D5F053D6018D91B502C4787558A002B9283DA7', 16),
+ 'e' => new BigInteger('3')
+ ));
+
+ $message = 'hello world!';
+ $signature = pack('H*', 'a0073057133ff3758e7e111b4d7441f1d8cbe4b2dd5ee4316a14264290dee5ed7f175716639bd9bb43a14e4f9fcb9e84dedd35e2205caac04828b2c053f68176d971ea88534dd2eeec903043c3469fc69c206b2a8694fd262488441ed8852280c3d4994e9d42bd1d575c7024095f1a20665925c2175e089c0d731471f6cc145404edf5559fd2276e45e448086f71c78d0cc6628fad394a34e51e8c10bc39bfe09ed2f5f742cc68bee899d0a41e4c75b7b80afd1c321d89ccd9fe8197c44624d91cc935dfa48de3c201099b5b417be748aef29248527e8bbb173cab76b48478d4177b338fe1f1244e64d7d23f07add560d5ad50b68d6649a49d7bc3db686daaa7');
+
+ $rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
+ $rsa->setHash('sha256');
+ $this->assertTrue($rsa->verify($message, $signature));
+ }
}
diff --git a/tests/Unit/File/ASN1Test.php b/tests/Unit/File/ASN1Test.php
index 3a44bdc48..d371154ed 100644
--- a/tests/Unit/File/ASN1Test.php
+++ b/tests/Unit/File/ASN1Test.php
@@ -79,7 +79,7 @@ public function testAnyString()
$decoded = $asn1->decodeBER(base64_decode($str));
$result = $asn1->asn1map($decoded[0], $AS_REP);
- $this->assertInternalType('array', $result);
+ $this->assertIsArray($result);
}
/**
@@ -231,7 +231,7 @@ public function testIncorrectString()
$decoded = $asn1->decodeBER(base64_decode($str));
$result = $asn1->asn1map($decoded[0], $AS_REP);
- $this->assertInternalType('array', $result);
+ $this->assertIsArray($result);
}
/**
@@ -276,7 +276,7 @@ public function testContextSpecificNonConstructed()
{
$asn1 = new ASN1();
$decoded = $asn1->decodeBER(base64_decode('MBaAFJtUo7c00HsI5EPZ4bkICfkOY2Pv'));
- $this->assertInternalType('string', $decoded[0]['content'][0]['content']);
+ $this->assertIsString($decoded[0]['content'][0]['content']);
}
/**
@@ -286,7 +286,7 @@ public function testEmptyContextTag()
{
$asn1 = new ASN1();
$decoded = $asn1->decodeBER("\xa0\x00");
- $this->assertInternalType('array', $decoded);
+ $this->assertIsArray($decoded);
$this->assertCount(0, $decoded[0]['content']);
}
@@ -390,6 +390,62 @@ public function testExplicitImplicitDate()
$a = $asn1->decodeBER($a);
$a = $asn1->asn1map($a[0], $map);
- $this->assertInternalType('array', $a);
+ $this->assertIsArray($a);
+ }
+
+ public function testNullGarbage()
+ {
+ $asn1 = new ASN1();
+
+ $em = pack('H*', '3080305c0609608648016503040201054f8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888804207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9');
+ $decoded = $asn1->decodeBER($em);
+ $this->assertFalse($decoded[0]);
+
+ $em = pack('H*', '3080307f0609608648016503040201057288888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888804207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca90000');
+ $decoded = $asn1->decodeBER($em);
+ $this->assertFalse($decoded[0]);
+ }
+
+ public function testOIDGarbage()
+ {
+ $asn1 = new ASN1();
+
+ $em = pack('H*', '3080305c065860864801650304020188888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888050004207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9');
+ $decoded = $asn1->decodeBER($em);
+ $this->assertFalse($decoded[0]);
+
+ $em = pack('H*', '3080307f067d608648016503040201888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888804207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9');
+ $decoded = $asn1->decodeBER($em);
+ $this->assertFalse($decoded[0]);
+ }
+
+ public function testConstructedMismatch()
+ {
+ $asn1 = new ASN1();
+
+ $em = pack('H*', '1031300d0609608648016503040201050004207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9');
+ $decoded = $asn1->decodeBER($em);
+ $this->assertFalse($decoded[0]);
+
+ $em = pack('H*', '3031100d0609608648016503040201050004207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9');
+ $decoded = $asn1->decodeBER($em);
+ $this->assertFalse($decoded[0]);
+
+ $em = pack('H*', '3031300d2609608648016503040201050004207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9');
+ $decoded = $asn1->decodeBER($em);
+ $this->assertFalse($decoded[0]);
+
+ $em = pack('H*', '3031300d06096086480165030402012d0004207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9');
+ $decoded = $asn1->decodeBER($em);
+ $this->assertFalse($decoded[0]);
+ }
+
+ public function testBadTagSecondOctet()
+ {
+ $asn1 = new ASN1();
+
+ $em = pack('H*', '3033300f1f808080060960864801650304020104207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9');
+ $decoded = $asn1->decodeBER($em);
+ $this->assertFalse($decoded[0]);
}
}
diff --git a/tests/Unit/File/X509/CSRTest.php b/tests/Unit/File/X509/CSRTest.php
index f0313a5b7..93bf273ea 100644
--- a/tests/Unit/File/X509/CSRTest.php
+++ b/tests/Unit/File/X509/CSRTest.php
@@ -27,7 +27,7 @@ public function testLoadCSR()
$spkac = $x509->loadCSR($test);
- $this->assertInternalType('array', $spkac);
+ $this->assertIsArray($spkac);
}
public function testCSRWithAttributes()
@@ -67,7 +67,7 @@ public function testCSRWithAttributes()
$csr = $x509->loadCSR($test);
- $this->assertInternalType('array', $csr);
+ $this->assertIsArray($csr);
}
public function testCSRDER()
@@ -92,7 +92,7 @@ public function testCSRDER()
$csr = $x509->loadCSR($csr);
- $this->assertInternalType('array', $csr);
+ $this->assertIsArray($csr);
}
// on PHP 7.1, with older versions of phpseclib, this would produce a "A non-numeric value encountered" warning
diff --git a/tests/Unit/File/X509/SPKACTest.php b/tests/Unit/File/X509/SPKACTest.php
index d31a34404..2c5792d07 100644
--- a/tests/Unit/File/X509/SPKACTest.php
+++ b/tests/Unit/File/X509/SPKACTest.php
@@ -28,11 +28,11 @@ public function testLoadSPKAC()
$spkac = $x509->loadSPKAC($test);
- $this->assertInternalType('array', $spkac);
+ $this->assertIsArray($spkac);
$spkac = $x509->loadSPKAC('SPKAC=' . $test);
- $this->assertInternalType('array', $spkac);
+ $this->assertIsArray($spkac);
$this->assertTrue(
$x509->validateSignature(),
@@ -41,7 +41,7 @@ public function testLoadSPKAC()
$pubKey = $x509->getPublicKey();
- $this->assertInternalType('string', "$pubKey");
+ $this->assertIsString("$pubKey");
}
public function testSaveSPKAC()
@@ -55,17 +55,17 @@ public function testSaveSPKAC()
$x509->setChallenge('...');
$spkac = $x509->signSPKAC();
- $this->assertInternalType('array', $spkac);
+ $this->assertIsArray($spkac);
- $this->assertInternalType('string', $x509->saveSPKAC($spkac));
+ $this->assertIsString($x509->saveSPKAC($spkac));
$x509 = new X509();
$x509->setPrivateKey($privKey);
$spkac = $x509->signSPKAC();
- $this->assertInternalType('array', $spkac);
+ $this->assertIsArray($spkac);
- $this->assertInternalType('string', $x509->saveSPKAC($spkac));
+ $this->assertIsString($x509->saveSPKAC($spkac));
}
public function testBadSignatureSPKAC()
diff --git a/tests/Unit/File/X509/X509Test.php b/tests/Unit/File/X509/X509Test.php
index 0d019ede2..d40ad311f 100644
--- a/tests/Unit/File/X509/X509Test.php
+++ b/tests/Unit/File/X509/X509Test.php
@@ -58,7 +58,7 @@ public function testExtensionMapping()
$cert = $x509->loadX509($test);
- $this->assertInternalType('array', $cert['tbsCertificate']['extensions'][3]['extnValue']);
+ $this->assertIsArray($cert['tbsCertificate']['extensions'][3]['extnValue']);
}
public function testLoadUnsupportedExtension()
@@ -811,4 +811,119 @@ public function testRandomString()
$this->assertFalse($r);
}
+
+ /**
+ * @group github1542
+ */
+ public function testMultiCertPEM()
+ {
+ $a = '-----BEGIN CERTIFICATE-----
+MIILODCCCSCgAwIBAgIQDh0LGipJ++wxFLj8X5MXKDANBgkqhkiG9w0BAQsFADCB
+kDELMAkGA1UEBhMCVVMxDTALBgNVBAgTBFV0YWgxDTALBgNVBAcTBExlaGkxFzAV
+BgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29t
+MS8wLQYDVQQDEyZEaWdpQ2VydCBWZXJpZmllZCBNYXJrIEludGVybWVkaWF0ZSBD
+QTAeFw0yMDA3MzAwMDAwMDBaFw0yMTAxMjUxMjAwMDBaMIIBDjEdMBsGA1UEDxMU
+UHJpdmF0ZSBPcmdhbml6YXRpb24xEzARBgsrBgEEAYI3PAIBAxMCVVMxGTAXBgsr
+BgEEAYI3PAIBAhMIRGVsYXdhcmUxEDAOBgNVBAUTBzM2MzMwMTkxGTAXBgNVBAkT
+EDEwMDAgVyBNYXVkZSBBdmUxDjAMBgNVBBETBTk0MDg1MQswCQYDVQQGEwJVUzET
+MBEGA1UECBMKQ2FsaWZvcm5pYTESMBAGA1UEBxMJU3Vubnl2YWxlMR0wGwYDVQQK
+ExRMaW5rZWRJbiBDb3Jwb3JhdGlvbjESMBAGCisGAQQBg55fAQMTAlVTMRcwFQYK
+KwYBBAGDnl8BBBMHNTY3NTczOTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAOCl7WccAcvSaf5+pNsV82VjFuwdzEwjDYESZmIuurz95e+JtJZst/M3Hw90
+YxKSDV4LdaVFAogXy2F+Npit1KhbBEb8vbBkm4LJ3iM8teE/10JugLyxrcVi3LSj
+iKHs+rqxcTJsVYoR+CuPLuAbu4xKi+xQ4tVafrFd0Y21n6OL8nB2SRISHF58kRXq
+UDW/NippF1AhcdCc5L5EmXFPCpyWfv+UXgTj9i+/I9AWUC3diHckb5NXd/wS7Jmq
+5FE0uixRGTixI5a9uZr0jasTtfhlVtvqFyDmzARB/q9IU0eXm3dtcCJISIXGum6o
+yCFUk8pyYsGd/M5Fyw7zbmEqsucCAwEAAaOCBgswggYHMB8GA1UdIwQYMBaAFOsN
+zmX0UnV7TbPUsz0w41AYq+NuMB0GA1UdDgQWBBSkuL0+t0wu/+y2xkUY/FOSsiuV
+ODAXBgNVHREEEDAOggxsaW5rZWRpbi5jb20wEwYDVR0lBAwwCgYIKwYBBQUHAx8w
+gZkGA1UdHwSBkTCBjjBFoEOgQYY/aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0Rp
+Z2lDZXJ0VmVyaWZpZWRNYXJrSW50ZXJtZWRpYXRlQ0EuY3JsMEWgQ6BBhj9odHRw
+Oi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRWZXJpZmllZE1hcmtJbnRlcm1l
+ZGlhdGVDQS5jcmwwUAYDVR0gBEkwRzA3BglghkgBhv1sCgEwKjAoBggrBgEFBQcC
+ARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAMBgorBgEEAYOeXwEBMF4G
+CCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL2NhY2VydHMuZGlnaWNl
+cnQuY29tL0RpZ2lDZXJ0VmVyaWZpZWRNYXJrSW50ZXJtZWRpYXRlQ0EuY3J0MAwG
+A1UdEwEB/wQCMAAwggOsBggrBgEFBQcBDASCA54wggOaooIDlqCCA5IwggOOMIID
+ijCCA4YWDWltYWdlL3N2Zyt4bWwwIzAhMAkGBSsOAwIaBQAEFGckN8uhuoNkcXXh
+wRAm7wkz4JRLMIIDThaCA0pkYXRhOmltYWdlL3N2Zyt4bWw7YmFzZTY0LEg0c0lB
+QUFBQUFBQUNsMVR5MjdiTUJDODl5c0k5VXlhKytLanNITElJVWlCRnVqSjkxUlJR
+cUdLSGNTQ25PYnJ1NVRVQkMwTVNKN2w3SEozZHJRL3o0OW03bC9PdytuWU51Q3dN
+YTlQNC9IY05tV2Fuci9zZHBmTHhWM0luVjRlZCtpOTN5bS9NWmZoZmlwdEUySm9U
+T21IeHpKdFlCNzZ5L1hwdFcyODhVWWpab24rdkR2M1AxNU9EOFBZdDgwMEhIL2I1
+M056dForR2FleXZ2ZzNIWC8zOTErTit0K0w5ODkxVWpITEh0dm5zWTB6WFd1Ryti
+YjVMQkJkek5vR2NSTHdGenk1NzdpeWk4eHlzUXdETDNnR2dnZWlZWTBYczJWQjJu
+T0ZRODFQb0hBcVltaFBGUUhLRXVSTDBIdk5CbHhBTGgrQlNsazZwb0R3VXJnUU1i
+R3QxcVVBazJwVjlBRS9PQitxc0k1S2xwUlN0cG5GSWxSSlo3RWVDZHZQVzdQNmQ5
+T2JtWmgwVFdGd01ZakJrNXlHVnBFc0pNbU1BUjVHS1hmRmhPMzU3cWwwbnNFRGVl
+Y29kQmcyVFZVblFjSFJBYkJBMHRDTGRpTDQ4OHRrdVVkZzRkbzF1SExzRlY0cjlD
+Q3BsMXRJeDZKemVnMFZ4T2RGeUFTODhMMm03WU1sNnl1QkN5bVpycnNUb2N1YVpS
+S094YUZhUXV5UTZGNXJ0cGI3UnUxd1N0SXdPcVV2NkZORjRWdFVqR1dGdEp2NUZn
+S3p5d3d4TWprUnVXZFFBZEdEZEJqSjIzdXJGVEdvT0liU3FHRUZhNjc0RGJUQkg0
+eTBuOVFBWjBqWHE2WVpDckhZNmlGYlI3cXYwa04rVi8zK0RIdXB2WFdLQXJNcWdF
+YThWTXBXbytXRkdVcURPVWkxVXh3M3BJR20yUzZ4VXgyU0FlVUc2V2xGVDUvVnN0
+S3FkVitlcWtwNHFTTHFnQlJTcmpnRzFTTlRCb0pETE10ZWpHTWEwT0hyNVg3Q3VZ
+cXlPaC9WMFhwNjNJWUxTMTl4YUtlZGx0UHFsWDMzNkEwYlJhNW9nQkFBQTCBigYK
+KwYBBAHWeQIEAgR8BHoAeAB2AFVZU64wlgCAbNLrUgimyZ6TGCisEFa0QhxVNhVM
+X3WsAAABc6DTF3wAAAQDAEcwRQIgRsnN1miYsyCMT234C14MaMgSAgKHXmc7RrBM
+a/1ovTMCIQCOc/THDvltzhZrtnoRSbjc2EYp57A0VVHvduQPa7FKBDANBgkqhkiG
+9w0BAQsFAAOCAgEA8UQt5jcUeOaDkhvbLq380Oq1Jy8Vr1BO1GPisn20KRCz/NvE
+56f8hhmZlZ1xXfOM+JCaGQnwVwcRBQtLQ/+6bmeT8/WM3hf9A5rP0g0ZxvaAlQtu
+e6UjvgnNx02QOKNPrmxN0rW8s24kUi0OAf1ump3SY5Ab+S+ywRG7Ah+3qch+FwA8
+CYau9TgV5kvfYDRULBM84EeFhsPcwT+YJ5u7RvkGQobqNao21Ti5tupiks/9NzI8
+splBS77Z6bPdFGvZ7pJdXiiDB2+SZdyv8iqDFM6mKRbOcuwAHcTY2zVhcS46H7SO
+8OU7L/2y0XQB1rMtQDarCKwdAcsAb2e+N8mYQ0glQX4k41Sf4saMXsU1EjnOCUas
+YxvVgJRD+fe4JWf8EO59fElzkrQsT3guBIzV5Kg1dYaCHngCYQIakjKQM0eKxZ3d
+vn4648A0vXynhJUThOSxN4jbvVA5uYYHqHDMjJtkBPDA7HtLSIxRNattshOAoeC5
+LMszAsL9th/WoXkAa2lTs2kashOHEpx+ncGactrL8tu7dvU01Yk6yP1QAjFEo1Nt
+8umUG7jQQIuquB2ry4qzFuQvKpbNQZ//9RsSmq1nni+DEKd/S63N7T8M0FpioLVm
+Z2OXFTCG5ORjPUOyMGjxzjEPZWmTOG+gqNOc0HKXbuBAsGZbK4dind+YdZE=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIHLzCCBRegAwIBAgIQDZXVhKBTvJ0ZjW6meNxHhTANBgkqhkiG9w0BAQsFADCB
+iDELMAkGA1UEBhMCVVMxDTALBgNVBAgTBFV0YWgxDTALBgNVBAcTBExlaGkxFzAV
+BgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29t
+MScwJQYDVQQDEx5EaWdpQ2VydCBWZXJpZmllZCBNYXJrIFJvb3QgQ0EwHhcNMTkw
+OTIzMTIyNTQyWhcNMzQwOTIzMTIyNTQyWjCBkDELMAkGA1UEBhMCVVMxDTALBgNV
+BAgTBFV0YWgxDTALBgNVBAcTBExlaGkxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMu
+MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBW
+ZXJpZmllZCBNYXJrIEludGVybWVkaWF0ZSBDQTCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAPfhMd+2RBjNZpqq0GVUF0kKK72fQxhJbnxgYv7GFpmi69sX
+dgeqH9RE07ShTDtkLks9G/GuiXsLEmjSCBDDTwfB3hpbdrZsNQFWOIRHXmU8ykuP
+bCd/HVRZGULeWvbt93deEB1el5MpxP9Fs3LKjw7xytbuM/nkGJ4D2R1IHC953FoU
+4BYsp+8VB1+7Gh8eKVh+HpmBeEfIB+cuq4FpZKxi+F5J7UjW5yO4SuDcTF4AMY0J
+DPuKIy+Og6laNOtDS30P1CUu1N6BwLMYTbeqyYHJ7B3kLWsDceGMqIcxo8zrk1rT
+sJctcXHXhB4k2PnVxt8qkQjg2Lo++kU0dFSUyrzvg3WrGypv9vphWMI+vmCjmu2K
+0BZLZ4nKshoTX495R6pGbsecGaaGgACB/1NcGI7PVp7spY2ytLvHHZ+Hh446BGFy
+AdM8lZCMXEhNftP8RRRVr8mwHHzyIa86r4yk0SkOlXUkNrGdTqqyMSDJ3W7DWGO/
+vCObzXiM0aq77ebD/0fE5LsZhEJYx7txF9NA1DoICgHp8zqF35i3UOp4+5IyJ8A9
+MjqYcX+LayH06B45bMgTHLmJKcsRYvXAtu+nIvIL0fk4+Ea7kJ7MNx5/udS89b2f
+vSFC4hmA3OBDiJqGmldwqJL/HP7RI8O54yj10vpiH4obDo8QgfhKSVoX5HwDAgMB
+AAGjggGJMIIBhTAdBgNVHQ4EFgQU6w3OZfRSdXtNs9SzPTDjUBir424wHwYDVR0j
+BBgwFoAU7G8ipLME4sFjh+Z3Y+pGaU7u/OswDgYDVR0PAQH/BAQDAgGGMBMGA1Ud
+JQQMMAoGCCsGAQUFBwMfMBIGA1UdEwEB/wQIMAYBAf8CAQAwfAYIKwYBBQUHAQEE
+cDBuMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRgYIKwYB
+BQUHMAKGOmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFZlcmlm
+aWVkTWFya1Jvb3RDQS5jcnQwSAYDVR0fBEEwPzA9oDugOYY3aHR0cDovL2NybDMu
+ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VmVyaWZpZWRNYXJrUm9vdENBLmNybDBCBgNV
+HSAEOzA5MDcGCWCGSAGG/WwKATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5k
+aWdpY2VydC5jb20vQ1BTMA0GCSqGSIb3DQEBCwUAA4ICAQA6v371ixHAA9WyGlFr
++RvmmqkZZg9pf6+j5sKImeTFAHfYz3TJa2wmDRpZxSRYy9VUFOMPVDEavsJ2i5Ua
+jEpkJ/7VHbX60joKBxQHKCbMpbwGen6pTXRaeE6CET2zCMbyiIqT2E6OiBZL8cWT
+sgLbdhVKspoOi+c3JwTR4khR24J9IQVxK90Nq3zeciYgBvM3G+ZJtZgkA58CRdex
+xVO6O57bwe4ti4rlRgWOGgAFpFrJSD1jqhhHD3MWg17NI4k0ciBPoDHHBAI8hiqg
+jPM+y6aEGww7BFSfkp5tl/Aq9uGXCwxNLOc3UlUd8Cc0qH1KfkvjrumVMmJhsk9I
+88YefbCuGPZ5Q8V2LIz7LrNDh0VRq/HSENXn1sBGlAFahgUTk/cWJ8nKA+8mHMlE
+NGmx205Rtbf9lVL1CbH3QFwlvGEfqoMXw6G9JW2hFQVTKpBKuzjQw43CEw12lstP
+oa96ixNAXXVGJsdKpYCqTIWJ0x1DssvG2shvzdHxawvYQ3C+/jaEoQ6bxSIdanI2
+NMtBdy9Q0TjDc7uf/eaUYKkP4wskNc1Os23oHllFHVm++8wdDltNulc7B1TXIQ+2
+oD5EoULMFSVUHX8gtyd463GgOQtBDwf3aZ4Xe6eDrhdfI/4IW098kVcg+qFO841L
+qzFkAKWjJj4KjfrbZX4C0Spfxw==
+-----END CERTIFICATE-----';
+
+ $x509 = new X509();
+ $r = $x509->loadX509($a);
+
+ $this->assertIsArray($r);
+ }
}
diff --git a/tests/Unit/Math/BigInteger/TestCase.php b/tests/Unit/Math/BigInteger/TestCase.php
index efef0a7d6..5c17c15ee 100644
--- a/tests/Unit/Math/BigInteger/TestCase.php
+++ b/tests/Unit/Math/BigInteger/TestCase.php
@@ -399,7 +399,7 @@ public function testDebugInfo()
{
$num = $this->getInstance(50);
$str = print_r($num, true);
- $this->assertContains('[value] => 0x32', $str);
+ $this->assertStringContainsString('[value] => 0x32', $str);
return $str;
}
diff --git a/tests/Unit/Net/SFTPStreamTest.php b/tests/Unit/Net/SFTPStreamUnitTest.php
similarity index 92%
rename from tests/Unit/Net/SFTPStreamTest.php
rename to tests/Unit/Net/SFTPStreamUnitTest.php
index 6f98bb0cb..80c3f63c8 100644
--- a/tests/Unit/Net/SFTPStreamTest.php
+++ b/tests/Unit/Net/SFTPStreamUnitTest.php
@@ -7,7 +7,7 @@
use phpseclib\Net\SFTP\Stream;
-class Unit_Net_SFTPStreamTest extends PhpseclibTestCase
+class Unit_Net_SFTPStreamUnitTest extends PhpseclibTestCase
{
public function testRegisterWithoutArgument()
{
diff --git a/tests/Unit/Net/SSH2Test.php b/tests/Unit/Net/SSH2UnitTest.php
similarity index 76%
rename from tests/Unit/Net/SSH2Test.php
rename to tests/Unit/Net/SSH2UnitTest.php
index 54695d5b2..aefcc5443 100644
--- a/tests/Unit/Net/SSH2Test.php
+++ b/tests/Unit/Net/SSH2UnitTest.php
@@ -6,7 +6,7 @@
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*/
-class Unit_Net_SSH2Test extends PhpseclibTestCase
+class Unit_Net_SSH2UnitTest extends PhpseclibTestCase
{
public function formatLogDataProvider()
{
@@ -46,25 +46,25 @@ public function testGenerateIdentifier()
}
if (extension_loaded('openssl')) {
- $this->assertContains('openssl', $identifier);
- $this->assertNotContains('mcrypt', $identifier);
+ $this->assertStringContainsString('openssl', $identifier);
+ $this->assertStringNotContainsString('mcrypt', $identifier);
} elseif (extension_loaded('mcrypt')) {
- $this->assertNotContains('openssl', $identifier);
- $this->assertContains('mcrypt', $identifier);
+ $this->assertStringNotContainsString('openssl', $identifier);
+ $this->assertStringContainsString('mcrypt', $identifier);
} else {
- $this->assertNotContains('openssl', $identifier);
- $this->assertNotContains('mcrypt', $identifier);
+ $this->assertStringNotContainsString('openssl', $identifier);
+ $this->assertStringNotContainsString('mcrypt', $identifier);
}
if (extension_loaded('gmp')) {
- $this->assertContains('gmp', $identifier);
- $this->assertNotContains('bcmath', $identifier);
+ $this->assertStringContainsString('gmp', $identifier);
+ $this->assertStringNotContainsString('bcmath', $identifier);
} elseif (extension_loaded('bcmath')) {
- $this->assertNotContains('gmp', $identifier);
- $this->assertContains('bcmath', $identifier);
+ $this->assertStringNotContainsString('gmp', $identifier);
+ $this->assertStringContainsString('bcmath', $identifier);
} else {
- $this->assertNotContains('gmp', $identifier);
- $this->assertNotContains('bcmath', $identifier);
+ $this->assertStringNotContainsString('gmp', $identifier);
+ $this->assertStringNotContainsString('bcmath', $identifier);
}
}
diff --git a/travis/run-phpunit.sh b/travis/run-phpunit.sh
index ce393a772..31b98afcf 100755
--- a/travis/run-phpunit.sh
+++ b/travis/run-phpunit.sh
@@ -20,6 +20,23 @@ then
PHPUNIT_ARGS="$PHPUNIT_ARGS -d zend.enable_gc=0"
fi
+if $PHPUNIT --atleast-version 9
+then
+ find tests -type f -name "*.php" -print0 | xargs -0 sed -i 's/n setUpBeforeClass()/n setUpBeforeClass(): void/g'
+ find tests -type f -name "*.php" -print0 | xargs -0 sed -i 's/n setUp()/n setUp(): void/g'
+ find tests -type f -name "*.php" -print0 | xargs -0 sed -i 's/n tearDown()/n tearDown(): void/g'
+ find tests -type f -name "*.php" -print0 | xargs -0 sed -i 's/\(n assertIsArray([^)]*)\)/\1: void/g'
+ find tests -type f -name "*.php" -print0 | xargs -0 sed -i 's/\(n assertIsString([^)]*)\)/\1: void/g'
+ find tests -type f -name "*.php" -print0 | xargs -0 sed -i 's/\(n assertStringContainsString([^)]*)\)/\1: void/g'
+ find tests -type f -name "*.php" -print0 | xargs -0 sed -i 's/\(n assertStringNotContainsString([^)]*)\)/\1: void/g'
+ find tests -type f -name "*.php" -print0 | xargs -0 sed -i 's/^class Unit_Crypt_\(AES\|Hash\|RSA\)_/class /g'
+ find tests -type f -name "*.php" -print0 | xargs -0 sed -i 's/^class Unit_File_\(X509\)_/class /g'
+ find tests -type f -name "*.php" -print0 | xargs -0 sed -i 's/^class Unit_Math_\(BigInteger\)_/class /g'
+ find tests -type f -name "*.php" -print0 | xargs -0 sed -i 's/^class Unit_\(Crypt\|File\|Math\|Net\)_/class /g'
+ find tests -type f -name "*.php" -print0 | xargs -0 sed -i 's/^class Functional_Net_/class /g'
+ find tests -type f -name "*.php" -print0 | xargs -0 sed -i 's/extends Unit_Crypt_Hash_\(SHA512Test\|SHA256Test\)/extends \1/g'
+fi
+
if [ "$TRAVIS_PHP_VERSION" = 'hhvm' -o `php -r "echo (int) version_compare(PHP_VERSION, '7.0', '>=');"` = "1" ]
then
find tests -type f -name "*Test.php" | \