diff options
-rw-r--r-- | auth/authentication.php | 2 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Crypt/AES.php (renamed from libs/phpseclib-1.0.7/Crypt/AES.php) | 0 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Crypt/Base.php (renamed from libs/phpseclib-1.0.7/Crypt/Base.php) | 9 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Crypt/Blowfish.php (renamed from libs/phpseclib-1.0.7/Crypt/Blowfish.php) | 0 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Crypt/DES.php (renamed from libs/phpseclib-1.0.7/Crypt/DES.php) | 0 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Crypt/Hash.php (renamed from libs/phpseclib-1.0.7/Crypt/Hash.php) | 0 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Crypt/RC2.php (renamed from libs/phpseclib-1.0.7/Crypt/RC2.php) | 0 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Crypt/RC4.php (renamed from libs/phpseclib-1.0.7/Crypt/RC4.php) | 2 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Crypt/RSA.php (renamed from libs/phpseclib-1.0.7/Crypt/RSA.php) | 2 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Crypt/Random.php (renamed from libs/phpseclib-1.0.7/Crypt/Random.php) | 0 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Crypt/Rijndael.php (renamed from libs/phpseclib-1.0.7/Crypt/Rijndael.php) | 0 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Crypt/TripleDES.php (renamed from libs/phpseclib-1.0.7/Crypt/TripleDES.php) | 0 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Crypt/Twofish.php (renamed from libs/phpseclib-1.0.7/Crypt/Twofish.php) | 0 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/File/ANSI.php (renamed from libs/phpseclib-1.0.7/File/ANSI.php) | 5 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/File/ASN1.php (renamed from libs/phpseclib-1.0.7/File/ASN1.php) | 80 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/File/X509.php (renamed from libs/phpseclib-1.0.7/File/X509.php) | 68 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Math/BigInteger.php (renamed from libs/phpseclib-1.0.7/Math/BigInteger.php) | 20 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Net/SCP.php (renamed from libs/phpseclib-1.0.7/Net/SCP.php) | 0 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Net/SFTP.php (renamed from libs/phpseclib-1.0.7/Net/SFTP.php) | 53 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Net/SFTP/Stream.php (renamed from libs/phpseclib-1.0.7/Net/SFTP/Stream.php) | 0 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Net/SSH1.php (renamed from libs/phpseclib-1.0.7/Net/SSH1.php) | 0 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/Net/SSH2.php (renamed from libs/phpseclib-1.0.7/Net/SSH2.php) | 369 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/System/SSH/Agent.php (renamed from libs/phpseclib-1.0.7/System/SSH/Agent.php) | 0 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/System/SSH_Agent.php (renamed from libs/phpseclib-1.0.7/System/SSH_Agent.php) | 0 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/bootstrap.php (renamed from libs/phpseclib-1.0.7/bootstrap.php) | 0 | ||||
-rw-r--r-- | libs/phpseclib-1.0.8/openssl.cnf (renamed from libs/phpseclib-1.0.7/openssl.cnf) | 0 |
26 files changed, 498 insertions, 112 deletions
diff --git a/auth/authentication.php b/auth/authentication.php index ed8e8d4..d3bb3cd 100644 --- a/auth/authentication.php +++ b/auth/authentication.php @@ -19,7 +19,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -ini_set('include_path', ini_get('include_path').':./libs/phpseclib-1.0.7'); +ini_set('include_path', ini_get('include_path').':./libs/phpseclib-1.0.8'); require_once('ssh.php'); require_once('telnet.php'); diff --git a/libs/phpseclib-1.0.7/Crypt/AES.php b/libs/phpseclib-1.0.8/Crypt/AES.php index 594011e..594011e 100644 --- a/libs/phpseclib-1.0.7/Crypt/AES.php +++ b/libs/phpseclib-1.0.8/Crypt/AES.php diff --git a/libs/phpseclib-1.0.7/Crypt/Base.php b/libs/phpseclib-1.0.8/Crypt/Base.php index 91ebe59..d3db117 100644 --- a/libs/phpseclib-1.0.7/Crypt/Base.php +++ b/libs/phpseclib-1.0.8/Crypt/Base.php @@ -526,8 +526,8 @@ class Crypt_Base $this->_setEngine(); // Determining whether inline crypting can be used by the cipher - if ($this->use_inline_crypt !== false && function_exists('create_function')) { - $this->use_inline_crypt = true; + if ($this->use_inline_crypt !== false) { + $this->use_inline_crypt = version_compare(PHP_VERSION, '5.3.0') >= 0 || function_exists('create_function'); } } @@ -2550,6 +2550,11 @@ class Crypt_Base } // Create the $inline function and return its name as string. Ready to run! + if (version_compare(PHP_VERSION, '5.3.0') >= 0) { + eval('$func = function ($_action, &$self, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' } };'); + return $func; + } + return create_function('$_action, &$self, $_text', $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }'); } diff --git a/libs/phpseclib-1.0.7/Crypt/Blowfish.php b/libs/phpseclib-1.0.8/Crypt/Blowfish.php index 17c8e7e..17c8e7e 100644 --- a/libs/phpseclib-1.0.7/Crypt/Blowfish.php +++ b/libs/phpseclib-1.0.8/Crypt/Blowfish.php diff --git a/libs/phpseclib-1.0.7/Crypt/DES.php b/libs/phpseclib-1.0.8/Crypt/DES.php index 4c57401..4c57401 100644 --- a/libs/phpseclib-1.0.7/Crypt/DES.php +++ b/libs/phpseclib-1.0.8/Crypt/DES.php diff --git a/libs/phpseclib-1.0.7/Crypt/Hash.php b/libs/phpseclib-1.0.8/Crypt/Hash.php index faa17c5..faa17c5 100644 --- a/libs/phpseclib-1.0.7/Crypt/Hash.php +++ b/libs/phpseclib-1.0.8/Crypt/Hash.php diff --git a/libs/phpseclib-1.0.7/Crypt/RC2.php b/libs/phpseclib-1.0.8/Crypt/RC2.php index 97b4550..97b4550 100644 --- a/libs/phpseclib-1.0.7/Crypt/RC2.php +++ b/libs/phpseclib-1.0.8/Crypt/RC2.php diff --git a/libs/phpseclib-1.0.7/Crypt/RC4.php b/libs/phpseclib-1.0.8/Crypt/RC4.php index 7cec2e7..8a59518 100644 --- a/libs/phpseclib-1.0.7/Crypt/RC4.php +++ b/libs/phpseclib-1.0.8/Crypt/RC4.php @@ -141,7 +141,7 @@ class Crypt_RC4 extends Crypt_Base * @var string * @access private */ - var $key = "\0"; + var $key; /** * The Key Stream for decryption and encryption diff --git a/libs/phpseclib-1.0.7/Crypt/RSA.php b/libs/phpseclib-1.0.8/Crypt/RSA.php index b734c9f..0f7f8aa 100644 --- a/libs/phpseclib-1.0.7/Crypt/RSA.php +++ b/libs/phpseclib-1.0.8/Crypt/RSA.php @@ -2512,7 +2512,7 @@ class Crypt_RSA $db = $maskedDB ^ $dbMask; $lHash2 = substr($db, 0, $this->hLen); $m = substr($db, $this->hLen); - if ($lHash != $lHash2) { + if (!$this->_equals($lHash, $lHash2)) { user_error('Decryption error'); return false; } diff --git a/libs/phpseclib-1.0.7/Crypt/Random.php b/libs/phpseclib-1.0.8/Crypt/Random.php index 1803421..1803421 100644 --- a/libs/phpseclib-1.0.7/Crypt/Random.php +++ b/libs/phpseclib-1.0.8/Crypt/Random.php diff --git a/libs/phpseclib-1.0.7/Crypt/Rijndael.php b/libs/phpseclib-1.0.8/Crypt/Rijndael.php index 56bc4e9..56bc4e9 100644 --- a/libs/phpseclib-1.0.7/Crypt/Rijndael.php +++ b/libs/phpseclib-1.0.8/Crypt/Rijndael.php diff --git a/libs/phpseclib-1.0.7/Crypt/TripleDES.php b/libs/phpseclib-1.0.8/Crypt/TripleDES.php index 4c0b677..4c0b677 100644 --- a/libs/phpseclib-1.0.7/Crypt/TripleDES.php +++ b/libs/phpseclib-1.0.8/Crypt/TripleDES.php diff --git a/libs/phpseclib-1.0.7/Crypt/Twofish.php b/libs/phpseclib-1.0.8/Crypt/Twofish.php index 7125f6a..7125f6a 100644 --- a/libs/phpseclib-1.0.7/Crypt/Twofish.php +++ b/libs/phpseclib-1.0.8/Crypt/Twofish.php diff --git a/libs/phpseclib-1.0.7/File/ANSI.php b/libs/phpseclib-1.0.8/File/ANSI.php index 989537b..0cbed17 100644 --- a/libs/phpseclib-1.0.7/File/ANSI.php +++ b/libs/phpseclib-1.0.8/File/ANSI.php @@ -332,6 +332,9 @@ class File_ANSI case preg_match('#\x1B\[(\d+)D#', $this->ansi, $match): // Move cursor left n lines $this->old_x = $this->x; $this->x-= $match[1]; + if ($this->x < 0) { + $this->x = 0; + } break; case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window break; @@ -443,7 +446,7 @@ class File_ANSI if ($this->x > $this->max_x) { $this->x = 0; - $this->y++; + $this->_newLine(); } else { $this->x++; } diff --git a/libs/phpseclib-1.0.7/File/ASN1.php b/libs/phpseclib-1.0.8/File/ASN1.php index 7ce28bd..732bd9c 100644 --- a/libs/phpseclib-1.0.7/File/ASN1.php +++ b/libs/phpseclib-1.0.8/File/ASN1.php @@ -554,7 +554,9 @@ class File_ASN1 break; case FILE_ASN1_TYPE_UTC_TIME: case FILE_ASN1_TYPE_GENERALIZED_TIME: - $current['content'] = $this->_decodeTime(substr($content, $content_pos), $tag); + $current['content'] = class_exists('DateTime') ? + $this->_decodeDateTime(substr($content, $content_pos), $tag) : + $this->_decodeUnixTime(substr($content, $content_pos), $tag); default: } @@ -788,10 +790,20 @@ class File_ASN1 return isset($this->oids[$decoded['content']]) ? $this->oids[$decoded['content']] : $decoded['content']; case FILE_ASN1_TYPE_UTC_TIME: case FILE_ASN1_TYPE_GENERALIZED_TIME: - if (isset($mapping['implicit'])) { - $decoded['content'] = $this->_decodeTime($decoded['content'], $decoded['type']); + if (class_exists('DateTime')) { + if (isset($mapping['implicit'])) { + $decoded['content'] = $this->_decodeDateTime($decoded['content'], $decoded['type']); + } + if (!$decoded['content']) { + return false; + } + return $decoded['content']->format($this->format); + } else { + if (isset($mapping['implicit'])) { + $decoded['content'] = $this->_decodeUnixTime($decoded['content'], $decoded['type']); + } + return @date($this->format, $decoded['content']); } - return @date($this->format, $decoded['content']); case FILE_ASN1_TYPE_BIT_STRING: if (isset($mapping['mapping'])) { $offset = ord($decoded['content'][0]); @@ -1040,7 +1052,12 @@ class File_ASN1 case FILE_ASN1_TYPE_GENERALIZED_TIME: $format = $mapping['type'] == FILE_ASN1_TYPE_UTC_TIME ? 'y' : 'Y'; $format.= 'mdHis'; - $value = @gmdate($format, strtotime($source)) . 'Z'; + if (!class_exists('DateTime')) { + $value = @gmdate($format, strtotime($source)) . 'Z'; + } else { + $date = new DateTime($source, new DateTimeZone('GMT')); + $value = $date->format($format) . 'Z'; + } break; case FILE_ASN1_TYPE_BIT_STRING: if (isset($mapping['mapping'])) { @@ -1202,7 +1219,7 @@ class File_ASN1 } /** - * BER-decode the time + * BER-decode the time (using UNIX time) * * Called by _decode_ber() and in the case of implicit tags asn1map(). * @@ -1211,7 +1228,7 @@ class File_ASN1 * @param int $tag * @return string */ - function _decodeTime($content, $tag) + function _decodeUnixTime($content, $tag) { /* UTCTime: http://tools.ietf.org/html/rfc5280#section-4.1.2.5.1 @@ -1250,6 +1267,55 @@ class File_ASN1 return @$mktime((int)$hour, (int)$minute, (int)$second, (int)$month, (int)$day, (int)$year) + $timezone; } + + /** + * BER-decode the time (using DateTime) + * + * Called by _decode_ber() and in the case of implicit tags asn1map(). + * + * @access private + * @param string $content + * @param int $tag + * @return string + */ + function _decodeDateTime($content, $tag) + { + /* UTCTime: + http://tools.ietf.org/html/rfc5280#section-4.1.2.5.1 + http://www.obj-sys.com/asn1tutorial/node15.html + + GeneralizedTime: + http://tools.ietf.org/html/rfc5280#section-4.1.2.5.2 + http://www.obj-sys.com/asn1tutorial/node14.html */ + + $format = 'YmdHis'; + + if ($tag == FILE_ASN1_TYPE_UTC_TIME) { + // https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=28 says "the seconds + // element shall always be present" but none-the-less I've seen X509 certs where it isn't and if the + // browsers parse it phpseclib ought to too + if (preg_match('#^(\d{10})(Z|[+-]\d{4})$#', $content, $matches)) { + $content = $matches[1] . '00' . $matches[2]; + } + $prefix = substr($content, 0, 2) >= 50 ? '19' : '20'; + $content = $prefix . $content; + } elseif (strpos($content, '.') !== false) { + $format.= '.u'; + } + + if ($content[strlen($content) - 1] == 'Z') { + $content = substr($content, 0, -1) . '+0000'; + } + + if (strpos($content, '-') !== false || strpos($content, '+') !== false) { + $format.= 'O'; + } + + // error supression isn't necessary as of PHP 7.0: + // http://php.net/manual/en/migration70.other-changes.php + return @DateTime::createFromFormat($format, $content); + } + /** * Set the time format * diff --git a/libs/phpseclib-1.0.7/File/X509.php b/libs/phpseclib-1.0.8/File/X509.php index e6c8443..6f84793 100644 --- a/libs/phpseclib-1.0.7/File/X509.php +++ b/libs/phpseclib-1.0.8/File/X509.php @@ -2114,7 +2114,9 @@ class File_X509 } if (!isset($date)) { - $date = time(); + $date = class_exists('DateTime') ? + new DateTime($date, new DateTimeZone(@date_default_timezone_get())) : + time(); } $notBefore = $this->currentCert['tbsCertificate']['validity']['notBefore']; @@ -2123,9 +2125,17 @@ class File_X509 $notAfter = $this->currentCert['tbsCertificate']['validity']['notAfter']; $notAfter = isset($notAfter['generalTime']) ? $notAfter['generalTime'] : $notAfter['utcTime']; + if (class_exists('DateTime')) { + $notBefore = new DateTime($notBefore, new DateTimeZone(@date_default_timezone_get())); + $notAfter = new DateTime($notAfter, new DateTimeZone(@date_default_timezone_get())); + } else { + $notBefore = @strtotime($notBefore); + $notAfter = @strtotime($notAfter); + } + switch (true) { - case $date < @strtotime($notBefore): - case $date > @strtotime($notAfter): + case $date < $notBefore: + case $date > $notAfter: return false; } @@ -3385,7 +3395,15 @@ class File_X509 */ function _timeField($date) { - $year = @gmdate("Y", @strtotime($date)); // the same way ASN1.php parses this + if (is_object($date) && strtolower(get_class($date)) == 'file_asn1_element') { + return $date; + } + if (!class_exists('DateTime')) { + $year = @gmdate("Y", @strtotime($date)); // the same way ASN1.php parses this + } else { + $dateObj = new DateTime($date, new DateTimeZone('GMT')); + $year = $dateObj->format('Y'); + } if ($year < 2050) { return array('utcTime' => $date); } else { @@ -3450,8 +3468,16 @@ class File_X509 return false; } - $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')); + if (!class_exists('DateTime')) { + $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')); + } else { + $startDate = new DateTime('now', new DateTimeZone(@date_default_timezone_get())); + $startDate = !empty($this->startDate) ? $this->startDate : $startDate->format('D, d M Y H:i:s O'); + + $endDate = new DateTime('+1 year', new DateTimeZone(@date_default_timezone_get())); + $endDate = !empty($this->endDate) ? $this->endDate : $endDate->format('D, d M Y H:i:s O'); + } if (!empty($this->serialNumber)) { $serialNumber = $this->serialNumber; } else { @@ -3724,7 +3750,12 @@ class File_X509 $currentCert = isset($this->currentCert) ? $this->currentCert : null; $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null; - $thisUpdate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O'); + if (!class_exists('DateTime')) { + $thisUpdate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O'); + } else { + $thisUpdate = new DateTime('now', new DateTimeZone(@date_default_timezone_get())); + $thisUpdate = !empty($this->startDate) ? $this->startDate : $thisUpdate->format('D, d M Y H:i:s O'); + } if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) { $this->currentCert = $crl->currentCert; @@ -3876,7 +3907,12 @@ class File_X509 */ function setStartDate($date) { - $this->startDate = @date('D, d M Y H:i:s O', @strtotime($date)); + if (class_exists('DateTime')) { + $date = new DateTime($date, new DateTimeZone(@date_default_timezone_get())); + $this->startDate = $date->format('D, d M Y H:i:s O'); + } else { + $this->startDate = @date('D, d M Y H:i:s O', @strtotime($date)); + } } /** @@ -3900,7 +3936,12 @@ class File_X509 $temp = chr(FILE_ASN1_TYPE_GENERALIZED_TIME) . $asn1->_encodeLength(strlen($temp)) . $temp; $this->endDate = new File_ASN1_Element($temp); } else { - $this->endDate = @date('D, d M Y H:i:s O', @strtotime($date)); + if (class_exists('DateTime')) { + $date = new DateTime($date, new DateTimeZone(@date_default_timezone_get())); + $this->endDate = $date->format('D, d M Y H:i:s O'); + } else { + $this->endDate = @date('D, d M Y H:i:s O', @strtotime($date)); + } } } @@ -4640,9 +4681,16 @@ class File_X509 return false; } + if (!class_exists('DateTime')) { + $revocationDate = @date('D, d M Y H:i:s O'); + } else { + $revocationDate = new DateTime('now', new DateTimeZone(@date_default_timezone_get())); + $revocationDate = $revocationDate->format('D, d M Y H:i:s O'); + } + $i = count($rclist); $rclist[] = array('userCertificate' => $serial, - 'revocationDate' => $this->_timeField(@date('D, d M Y H:i:s O'))); + 'revocationDate' => $this->_timeField($revocationDate)); return $i; } diff --git a/libs/phpseclib-1.0.7/Math/BigInteger.php b/libs/phpseclib-1.0.8/Math/BigInteger.php index 192ce82..6f9d591 100644 --- a/libs/phpseclib-1.0.7/Math/BigInteger.php +++ b/libs/phpseclib-1.0.8/Math/BigInteger.php @@ -360,8 +360,12 @@ class Math_BigInteger case 256: switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: - $sign = $this->is_negative ? '-' : ''; - $this->value = gmp_init($sign . '0x' . bin2hex($x)); + $this->value = function_exists('gmp_import') ? + gmp_import($x) : + gmp_init('0x' . bin2hex($x)); + if ($this->is_negative) { + $this->value = gmp_neg($this->value); + } break; case MATH_BIGINTEGER_MODE_BCMATH: // round $len to the nearest 4 (thanks, DavidMJ!) @@ -563,9 +567,13 @@ class Math_BigInteger return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; } - $temp = gmp_strval(gmp_abs($this->value), 16); - $temp = (strlen($temp) & 1) ? '0' . $temp : $temp; - $temp = pack('H*', $temp); + if (function_exists('gmp_export')) { + $temp = gmp_export($this->value); + } else { + $temp = gmp_strval(gmp_abs($this->value), 16); + $temp = (strlen($temp) & 1) ? '0' . $temp : $temp; + $temp = pack('H*', $temp); + } return $this->precision > 0 ? substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) : @@ -2937,7 +2945,7 @@ class Math_BigInteger // (will always result in a smaller number. ie. ~1 isn't 1111 1110 - it's 0) $temp = $this->toBytes(); if ($temp == '') { - return ''; + return $this->_normalize(new Math_BigInteger()); } $pre_msb = decbin(ord($temp[0])); $temp = ~$temp; diff --git a/libs/phpseclib-1.0.7/Net/SCP.php b/libs/phpseclib-1.0.8/Net/SCP.php index 354acea..354acea 100644 --- a/libs/phpseclib-1.0.7/Net/SCP.php +++ b/libs/phpseclib-1.0.8/Net/SCP.php diff --git a/libs/phpseclib-1.0.7/Net/SFTP.php b/libs/phpseclib-1.0.8/Net/SFTP.php index 40c97da..a0b3632 100644 --- a/libs/phpseclib-1.0.7/Net/SFTP.php +++ b/libs/phpseclib-1.0.8/Net/SFTP.php @@ -199,7 +199,7 @@ class Net_SFTP extends Net_SSH2 * Current working directory * * @var string - * @see self::_realpath() + * @see self::realpath() * @see self::chdir() * @access private */ @@ -228,7 +228,7 @@ class Net_SFTP extends Net_SSH2 * * @see self::getSFTPErrors() * @see self::getLastSFTPError() - * @var string + * @var array * @access private */ var $sftp_errors = array(); @@ -278,6 +278,20 @@ class Net_SFTP extends Net_SSH2 var $sortOptions = array(); /** + * Canonicalization Flag + * + * Determines whether or not paths should be canonicalized before being + * passed on to the remote server. + * + * @see self::enablePathCanonicalization() + * @see self::disablePathCanonicalization() + * @see self::realpath() + * @var bool + * @access private + */ + var $canonicalize_paths = true; + + /** * Default Constructor. * * Connects to an SFTP server @@ -631,6 +645,26 @@ class Net_SFTP extends Net_SSH2 } /** + * Enable path canonicalization + * + * @access public + */ + function enablePathCanonicalization() + { + $this->canonicalize_paths = true; + } + + /** + * Enable path canonicalization + * + * @access public + */ + function disablePathCanonicalization() + { + $this->canonicalize_paths = false; + } + + /** * Returns the current directory name * * @return mixed @@ -688,13 +722,20 @@ class Net_SFTP extends Net_SSH2 * SFTP doesn't provide a mechanism by which the current working directory can be changed, so we'll emulate it. Returns * the absolute (canonicalized) path. * + * If canonicalize_paths has been disabled using disablePathCanonicalization(), $path is returned as-is. + * * @see self::chdir() + * @see self::disablePathCanonicalization() * @param string $path * @return mixed * @access private */ function _realpath($path) { + if (!$this->canonicalize_paths) { + return $path; + } + if ($this->pwd === false) { // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.9 if (!$this->_send_sftp_packet(NET_SFTP_REALPATH, pack('Na*', strlen($path), $path))) { @@ -1349,7 +1390,7 @@ class Net_SFTP extends Net_SSH2 /** * Returns general information about a file or symbolic link * - * Determines information without calling Net_SFTP::_realpath(). + * Determines information without calling Net_SFTP::realpath(). * The second parameter can be either NET_SFTP_STAT or NET_SFTP_LSTAT. * * @param string $filename @@ -1510,7 +1551,7 @@ class Net_SFTP extends Net_SSH2 return true; } - $filename = $this->_realPath($filename); + $filename = $this->realpath($filename); // rather than return what the permissions *should* be, we'll return what they actually are. this will also // tell us if the file actually exists. // incidentally, SFTPv4+ adds an additional 32-bit integer field - flags - to the following: @@ -1995,7 +2036,7 @@ class Net_SFTP extends Net_SSH2 if (isset($fp)) { $stat = fstat($fp); - $size = $stat['size']; + $size = !empty($stat) ? $stat['size'] : 0; if ($local_start >= 0) { fseek($fp, $local_start); @@ -3071,7 +3112,7 @@ class Net_SFTP extends Net_SSH2 /** * Returns all errors * - * @return string + * @return array * @access public */ function getSFTPErrors() diff --git a/libs/phpseclib-1.0.7/Net/SFTP/Stream.php b/libs/phpseclib-1.0.8/Net/SFTP/Stream.php index a944d7f..a944d7f 100644 --- a/libs/phpseclib-1.0.7/Net/SFTP/Stream.php +++ b/libs/phpseclib-1.0.8/Net/SFTP/Stream.php diff --git a/libs/phpseclib-1.0.7/Net/SSH1.php b/libs/phpseclib-1.0.8/Net/SSH1.php index 55473d0..55473d0 100644 --- a/libs/phpseclib-1.0.7/Net/SSH1.php +++ b/libs/phpseclib-1.0.8/Net/SSH1.php diff --git a/libs/phpseclib-1.0.7/Net/SSH2.php b/libs/phpseclib-1.0.8/Net/SSH2.php index d104b81..67f571e 100644 --- a/libs/phpseclib-1.0.7/Net/SSH2.php +++ b/libs/phpseclib-1.0.8/Net/SSH2.php @@ -96,10 +96,10 @@ define('NET_SSH2_MASK_WINDOW_ADJUST', 0x00000020); * @see self::_get_channel_packet() * @access private */ -define('NET_SSH2_CHANNEL_EXEC', 0); // PuTTy uses 0x100 -define('NET_SSH2_CHANNEL_SHELL', 1); -define('NET_SSH2_CHANNEL_SUBSYSTEM', 2); -define('NET_SSH2_CHANNEL_AGENT_FORWARD', 3); +define('NET_SSH2_CHANNEL_EXEC', 1); // PuTTy uses 0x100 +define('NET_SSH2_CHANNEL_SHELL', 2); +define('NET_SSH2_CHANNEL_SUBSYSTEM', 3); +define('NET_SSH2_CHANNEL_AGENT_FORWARD', 4); /**#@-*/ /**#@+ @@ -122,6 +122,10 @@ define('NET_SSH2_LOG_REALTIME', 3); * Dumps the content real-time to a file */ define('NET_SSH2_LOG_REALTIME_FILE', 4); +/** + * Make sure that the log never gets larger than this + */ +define('NET_SSH2_LOG_MAX_SIZE', 1024 * 1024); /**#@-*/ /**#@+ @@ -137,9 +141,9 @@ define('NET_SSH2_READ_SIMPLE', 1); */ define('NET_SSH2_READ_REGEX', 2); /** - * Make sure that the log never gets larger than this + * Returns when a string matching the regular expression $expect is found */ -define('NET_SSH2_LOG_MAX_SIZE', 1024 * 1024); +define('NET_SSH2_READ_NEXT', 3); /**#@-*/ /** @@ -872,6 +876,54 @@ class Net_SSH2 var $agent; /** + * Send the identification string first? + * + * @var bool + * @access private + */ + var $send_id_string_first = true; + + /** + * Send the key exchange initiation packet first? + * + * @var bool + * @access private + */ + var $send_kex_first = true; + + /** + * Some versions of OpenSSH incorrectly calculate the key size + * + * @var bool + * @access private + */ + var $bad_key_size_fix = false; + + /** + * The selected decryption algorithm + * + * @var string + * @access private + */ + var $decrypt_algorithm = ''; + + /** + * Should we try to re-connect to re-establish keys? + * + * @var bool + * @access private + */ + var $retry_connect = false; + + /** + * Binary Packet Buffer + * + * @var string|false + * @access private + */ + var $binary_packet_buffer = false; + + /** * Default Constructor. * * $host can either be a string, representing the host, or a stream resource. @@ -1013,7 +1065,7 @@ class Net_SSH2 * CRYPT_MODE_INTERNAL, CRYPT_MODE_MCRYPT * * @param int $engine - * @access private + * @access public */ function setCryptoEngine($engine) { @@ -1021,6 +1073,62 @@ class Net_SSH2 } /** + * Send Identification String First + * + * https://tools.ietf.org/html/rfc4253#section-4.2 says "when the connection has been established, + * both sides MUST send an identification string". It does not say which side sends it first. In + * theory it shouldn't matter but it is a fact of life that some SSH servers are simply buggy + * + * @access public + */ + function sendIdentificationStringFirst() + { + $this->send_id_string_first = true; + } + + /** + * Send Identification String Last + * + * https://tools.ietf.org/html/rfc4253#section-4.2 says "when the connection has been established, + * both sides MUST send an identification string". It does not say which side sends it first. In + * theory it shouldn't matter but it is a fact of life that some SSH servers are simply buggy + * + * @access public + */ + function sendIdentificationStringLast() + { + $this->send_id_string_first = false; + } + + /** + * Send SSH_MSG_KEXINIT First + * + * https://tools.ietf.org/html/rfc4253#section-7.1 says "key exchange begins by each sending + * sending the [SSH_MSG_KEXINIT] packet". It does not say which side sends it first. In theory + * it shouldn't matter but it is a fact of life that some SSH servers are simply buggy + * + * @access public + */ + function sendKEXINITFirst() + { + $this->send_kex_first = true; + } + + /** + * Send SSH_MSG_KEXINIT Last + * + * https://tools.ietf.org/html/rfc4253#section-7.1 says "key exchange begins by each sending + * sending the [SSH_MSG_KEXINIT] packet". It does not say which side sends it first. In theory + * it shouldn't matter but it is a fact of life that some SSH servers are simply buggy + * + * @access public + */ + function sendKEXINITLast() + { + $this->send_kex_first = false; + } + + /** * Connect to an SSHv2 server * * @return bool @@ -1061,7 +1169,9 @@ class Net_SSH2 $this->identifier = $this->_generate_identifier(); - fputs($this->fsock, $this->identifier . "\r\n"); + if ($this->send_id_string_first) { + fputs($this->fsock, $this->identifier . "\r\n"); + } /* According to the SSH2 specs, @@ -1116,23 +1226,33 @@ class Net_SSH2 $this->errors[] = utf8_decode($extra); } - if ($matches[1] != '1.99' && $matches[1] != '2.0') { + if (version_compare($matches[1], '1.99', '<')) { user_error("Cannot connect to SSH $matches[1] servers"); return false; } - $response = $this->_get_binary_packet(); - if ($response === false) { - user_error('Connection closed by server'); - return false; + if (!$this->send_id_string_first) { + fputs($this->fsock, $this->identifier . "\r\n"); } - if (!strlen($response) || ord($response[0]) != NET_SSH2_MSG_KEXINIT) { - user_error('Expected SSH_MSG_KEXINIT'); - return false; + if (!$this->send_kex_first) { + $response = $this->_get_binary_packet(); + if ($response === false) { + user_error('Connection closed by server'); + return false; + } + + if (!strlen($response) || ord($response[0]) != NET_SSH2_MSG_KEXINIT) { + user_error('Expected SSH_MSG_KEXINIT'); + return false; + } + + if (!$this->_key_exchange($response)) { + return false; + } } - if (!$this->_key_exchange($response)) { + if ($this->send_kex_first && !$this->_key_exchange()) { return false; } @@ -1176,10 +1296,10 @@ class Net_SSH2 /** * Key Exchange * - * @param string $kexinit_payload_server + * @param string $kexinit_payload_server optional * @access private */ - function _key_exchange($kexinit_payload_server) + function _key_exchange($kexinit_payload_server = false) { static $kex_algorithms = array( 'diffie-hellman-group1-sha1', // REQUIRED @@ -1290,8 +1410,9 @@ class Net_SSH2 ); // some SSH servers have buggy implementations of some of the above algorithms - switch ($this->server_identifier) { - case 'SSH-2.0-SSHD': + switch (true) { + case $this->server_identifier == 'SSH-2.0-SSHD': + case substr($this->server_identifier, 0, 13) == 'SSH-2.0-DLINK': $mac_algorithms = array_values(array_diff( $mac_algorithms, array('hmac-sha1-96', 'hmac-md5-96') @@ -1312,6 +1433,51 @@ class Net_SSH2 $client_cookie = crypt_random_string(16); + $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_kex_first) { + if (!$this->_send_binary_packet($kexinit_payload_client)) { + return false; + } + + $kexinit_payload_server = $this->_get_binary_packet(); + if ($kexinit_payload_server === false) { + user_error('Connection closed by server'); + return false; + } + + if (!strlen($kexinit_payload_server) || ord($kexinit_payload_server[0]) != NET_SSH2_MSG_KEXINIT) { + user_error('Expected SSH_MSG_KEXINIT'); + return false; + } + } + $response = $kexinit_payload_server; $this->_string_shift($response, 1); // skip past the message number (it should be SSH_MSG_KEXINIT) $server_cookie = $this->_string_shift($response, 16); @@ -1382,39 +1548,9 @@ class Net_SSH2 extract(unpack('Cfirst_kex_packet_follows', $this->_string_shift($response, 1))); $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 - ); - - if (!$this->_send_binary_packet($kexinit_payload_client)) { + if (!$this->send_kex_first && !$this->_send_binary_packet($kexinit_payload_client)) { return false; } - // here ends the second place. // we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange // we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the @@ -1825,6 +1961,8 @@ class Net_SSH2 //$this->decrypt = new Crypt_Null(); } + $this->decrypt_algorithm = $decrypt; + $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes); if ($this->encrypt) { @@ -1983,6 +2121,10 @@ class Net_SSH2 */ function _encryption_algorithm_to_key_size($algorithm) { + if ($this->bad_key_size_fix && $this->_bad_algorithm_candidate($algorithm)) { + return 16; + } + switch ($algorithm) { case 'none': return 0; @@ -2014,6 +2156,27 @@ class Net_SSH2 } /** + * Tests whether or not proposed algorithm has a potential for issues + * + * @link https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/ssh2-aesctr-openssh.html + * @link https://bugzilla.mindrot.org/show_bug.cgi?id=1291 + * @param string $algorithm Name of the encryption algorithm + * @return bool + * @access private + */ + function _bad_algorithm_candidate($algorithm) + { + switch ($algorithm) { + case 'arcfour256': + case 'aes192-ctr': + case 'aes256-ctr': + return true; + } + + return false; + } + + /** * Login * * The $password parameter can be a plaintext password, a Crypt_RSA object or an array @@ -2092,6 +2255,13 @@ class Net_SSH2 $response = $this->_get_binary_packet(); if ($response === false) { + if ($this->retry_connect) { + $this->retry_connect = false; + if (!$this->_connect()) { + return false; + } + return $this->_login_helper($username, $password); + } user_error('Connection closed by server'); return false; } @@ -2659,7 +2829,7 @@ class Net_SSH2 return false; } - $response = $this->_get_binary_packet(); + $response = $this->_get_binary_packet(true); if ($response === false) { user_error('Connection closed by server'); return false; @@ -2913,6 +3083,10 @@ class Net_SSH2 $channel = $this->_get_interactive_channel(); + if ($mode == NET_SSH2_READ_NEXT) { + return $this->_get_channel_packet($channel); + } + $match = $expect; while (true) { if ($mode == NET_SSH2_READ_REGEX) { @@ -3112,6 +3286,24 @@ class Net_SSH2 } /** + * Resets a connection for re-use + * + * @param int $reason + * @access private + */ + function _reset_connection($reason) + { + $this->_disconnect($reason); + $this->decrypt = $this->encrypt = false; + $this->decrypt_block_size = $this->encrypt_block_size = 8; + $this->hmac_check = $this->hmac_create = false; + $this->hmac_size = false; + $this->session_id = false; + $this->retry_connect = true; + $this->get_seq_no = $this->send_seq_no = 0; + } + + /** * Gets Binary Packets * * See '6. Binary Packet Protocol' of rfc4253 for more info. @@ -3120,7 +3312,7 @@ class Net_SSH2 * @return string * @access private */ - function _get_binary_packet() + function _get_binary_packet($filter_channel_packets = false) { if (!is_resource($this->fsock) || feof($this->fsock)) { user_error('Connection closed prematurely'); @@ -3154,6 +3346,11 @@ class Net_SSH2 // "implementations SHOULD check that the packet length is reasonable" // PuTTY uses 0x9000 as the actual max packet size and so to shall we if ($remaining_length < -$this->decrypt_block_size || $remaining_length > 0x9000 || $remaining_length % $this->decrypt_block_size != 0) { + if (!$this->bad_key_size_fix && $this->_bad_algorithm_candidate($this->decrypt_algorithm) && !($this->bitmap & NET_SSH2_MASK_LOGIN)) { + $this->bad_key_size_fix = true; + $this->_reset_connection(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); + return false; + } user_error('Invalid size'); return false; } @@ -3169,6 +3366,7 @@ class Net_SSH2 $buffer.= $temp; $remaining_length-= strlen($temp); } + $stop = strtok(microtime(), ' ') + strtok(''); if (strlen($buffer)) { $raw.= $this->decrypt !== false ? $this->decrypt->decrypt($buffer) : $buffer; @@ -3204,7 +3402,7 @@ class Net_SSH2 $this->last_packet = $current; } - return $this->_filter($payload); + return $this->_filter($payload, $filter_channel_packets); } /** @@ -3216,7 +3414,7 @@ class Net_SSH2 * @return string * @access private */ - function _filter($payload) + function _filter($payload, $filter_channel_packets) { switch (ord($payload[0])) { case NET_SSH2_MSG_DISCONNECT: @@ -3266,6 +3464,17 @@ class Net_SSH2 // only called when we've already logged in if (($this->bitmap & NET_SSH2_MASK_CONNECTED) && $this->isAuthenticated()) { switch (ord($payload[0])) { + 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 ($filter_channel_packets) { + $this->binary_packet_buffer = $payload; + $this->_get_channel_packet(true); + $payload = $this->_get_binary_packet(true); + } + break; case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4 if (strlen($payload) < 4) { return false; @@ -3450,32 +3659,38 @@ class Net_SSH2 } while (true) { - if ($this->curTimeout) { - if ($this->curTimeout < 0) { - $this->is_timeout = true; - return true; - } + if ($this->binary_packet_buffer !== false) { + $response = $this->binary_packet_buffer; + $this->binary_packet_buffer = false; + } else { + if ($this->curTimeout) { + if ($this->curTimeout < 0) { + $this->is_timeout = true; + return true; + } - $read = array($this->fsock); - $write = $except = null; + $read = array($this->fsock); + $write = $except = null; - $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838 - $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; + $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838 + $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 = strtok(microtime(), ' ') + strtok('') - $start; + $this->curTimeout-= $elapsed; } - $elapsed = strtok(microtime(), ' ') + strtok('') - $start; - $this->curTimeout-= $elapsed; - } - $response = $this->_get_binary_packet(); - if ($response === false) { - user_error('Connection closed by server'); - return false; + $response = $this->_get_binary_packet(); + if ($response === false) { + user_error('Connection closed by server'); + return false; + } } + if ($client_channel == -1 && $response === true) { return true; } diff --git a/libs/phpseclib-1.0.7/System/SSH/Agent.php b/libs/phpseclib-1.0.8/System/SSH/Agent.php index 7388cb4..7388cb4 100644 --- a/libs/phpseclib-1.0.7/System/SSH/Agent.php +++ b/libs/phpseclib-1.0.8/System/SSH/Agent.php diff --git a/libs/phpseclib-1.0.7/System/SSH_Agent.php b/libs/phpseclib-1.0.8/System/SSH_Agent.php index ea434b9..ea434b9 100644 --- a/libs/phpseclib-1.0.7/System/SSH_Agent.php +++ b/libs/phpseclib-1.0.8/System/SSH_Agent.php diff --git a/libs/phpseclib-1.0.7/bootstrap.php b/libs/phpseclib-1.0.8/bootstrap.php index 0da0999..0da0999 100644 --- a/libs/phpseclib-1.0.7/bootstrap.php +++ b/libs/phpseclib-1.0.8/bootstrap.php diff --git a/libs/phpseclib-1.0.7/openssl.cnf b/libs/phpseclib-1.0.8/openssl.cnf index 2b8b52f..2b8b52f 100644 --- a/libs/phpseclib-1.0.7/openssl.cnf +++ b/libs/phpseclib-1.0.8/openssl.cnf |