Created
November 1, 2016 20:58
-
-
Save cbj4074/7b8b3509150d35a786a51dce395bf9c6 to your computer and use it in GitHub Desktop.
Demonstrates segfault that occurs with PHP 7.0.12 and PECL ssh2 extension, version 1.0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class ssh2 | |
{ | |
private $host = 'host'; | |
private $user = 'user'; | |
private $port = '22'; | |
private $password = 'password'; | |
private $con = null; | |
private $pubKeyFile = null; | |
private $privKeyFile = null; | |
private $shell_type = 'xterm'; | |
private $shell = null; | |
private $log = array(); | |
private $sftp = null; | |
private $knownHost = null; | |
function __construct($host = '', $port = '', $knownHost = NULL) | |
{ | |
if ($host != '') { | |
$this->host = $host; | |
} | |
if ($port != '') { | |
$this->port = $port; | |
} | |
if (!is_null($knownHost)) { | |
$this->knownHost = $knownHost; | |
} | |
$this->con = ssh2_connect($this->host, $this->port, array('hostkey'=>'ssh-rsa,ssh-dss')); | |
if (!$this->con) { | |
$this->log[] = 'Connection failed!'; | |
$this->con = NULL; | |
} | |
else { | |
//If a host fingerprint has been required, check it. | |
if (!is_null($this->knownHost)) { | |
$fingerprint = ssh2_fingerprint($this->con, SSH2_FINGERPRINT_MD5 | SSH2_FINGERPRINT_HEX); | |
if (is_string($fingerprint)) { | |
if (strcasecmp($fingerprint, $this->knownHost) != 0) { | |
$this->log[] = 'HOSTKEY MISMATCH! (Expected "' . $this->knownHost . '" and received "' . $fingerprint . '" [comparison is case-insensitive]; possible Man-In-The-Middle Attack?'; | |
$this->con = NULL; | |
} | |
} | |
else { | |
$this->log[] = 'Could not determine remote host fingerprint (returned value was "' . $fingerprint . '"); aborting connection'; | |
$this->con = NULL; | |
} | |
} | |
} | |
} | |
function __destruct() | |
{ | |
$this->disconnect(); | |
} | |
function getCon() | |
{ | |
return $this->con; | |
} | |
function getSftp() | |
{ | |
return $this->sftp; | |
} | |
function authKeyFile($user, $pubKeyFile, $privKeyFile) | |
{ | |
if ($user != '') { | |
$this->user = $user; | |
} | |
if ($pubKeyFile != '') { | |
$this->pubKeyFile = $pubKeyFile; | |
} | |
if ($privKeyFile != '') { | |
$this->privKeyFile = $privKeyFile; | |
} | |
if (!ssh2_auth_pubkey_file($this->con, $this->user, $this->pubKeyFile, $this->privKeyFile)) { | |
$this->log[] = 'Public key authorization failed (public key "' . $this->pubKeyFile . '" and private key "' . $this->privKeyFile . '")!'; | |
return FALSE; | |
} | |
else { | |
return TRUE; | |
} | |
} | |
function sftpCon() | |
{ | |
global $startTime; | |
echo 'Calling ssh2_sftp(); time elapsed: ' . (microtime(true) - $startTime) . PHP_EOL; | |
$sftp = ssh2_sftp($this->con); | |
$this->sftp = $sftp; | |
} | |
function getLog() | |
{ | |
return $this->log; | |
} | |
function disconnect() | |
{ | |
ssh2_disconnect($this->con); | |
} | |
} | |
class SshTest | |
{ | |
public static function connectToSshServer($server) | |
{ | |
global $startTime; | |
//Establish an SSH session, so we can use file_exists() | |
//on the remote server (requires sftp wrapper). | |
echo 'Calling "new ssh2()"; time elapsed: ' . ((microtime(true) - $startTime)) . PHP_EOL; | |
$ssh = new ssh2($server['hostname'], '22', $server['fingerprint']); | |
echo 'Calling "$ssh->getCon()"; time elapsed: ' . (microtime(true) - $startTime) . PHP_EOL; | |
if ($ssh->getCon() !== NULL) { | |
//We were able to open an SSH session and the remote | |
//server has the fingerprint that we expect. It's safe | |
//to supply authentication credentials (as safe as possible, anyway). | |
echo 'Calling "$ssh->authKeyFile()"; time elapsed: ' . (microtime(true) - $startTime) . PHP_EOL; | |
if ($ssh->authKeyFile($server['sshUser'], $server['publicKey'], $server['privateKey'])) { | |
//If authenticaton was successful, establish | |
//an SFTP session so that sftp wrappers are available. | |
echo 'Calling "$ssh->sftpCon()"; time elapsed: ' . (microtime(true) - $startTime) . PHP_EOL; | |
$ssh->sftpCon(); | |
} | |
} | |
echo 'Returning from SshTest::connectToSshServer(); time elapsed: ' . (microtime(true) - $startTime) . PHP_EOL; | |
return $ssh; | |
} | |
} | |
################################################################################ | |
$testSshServers = array( | |
1 => array( | |
'hostname' => 'localhost', | |
'fingerprint' => 'DF551756B1D7AE3592AD574AD4D9F462', | |
'sshUser' => 'user', | |
'publicKey' => '/var/www/example.com/.ssh/user.pub', | |
'privateKey' => '/var/www/example.com/.ssh/user', | |
), | |
); | |
global $startTime; | |
$startTime = microtime(true); | |
$ssh = SshTest::connectToSshServer($testSshServers[1]); | |
var_dump($ssh); | |
echo 'Attempting ssh2_disconnect(); time elapsed: ' . (microtime(true) - $startTime) . PHP_EOL; | |
$ssh->disconnect(); | |
echo 'Exiting; time elapsed: ' . (microtime(true) - $startTime) . PHP_EOL; | |
exit; | |
/* | |
Typical output: | |
php -f /var/www/example.com/web/php7-ssh2-segfault-test.php | |
Calling "new ssh2()"; time elapsed: 6.9141387939453E-6 | |
Calling "$ssh->getCon()"; time elapsed: 0.054915904998779 | |
Calling "$ssh->authKeyFile()"; time elapsed: 0.055253982543945 | |
Calling "$ssh->sftpCon()"; time elapsed: 0.066303968429565 | |
Calling ssh2_sftp(); time elapsed: 0.066792964935303 | |
Returning from SshTest::connectToSshServer(); time elapsed: 0.25690102577209 | |
object(ssh2)#1 (12) { | |
["host":"ssh2":private]=> | |
string(9) "localhost" | |
["user":"ssh2":private]=> | |
string(3) "user" | |
["port":"ssh2":private]=> | |
string(2) "22" | |
["password":"ssh2":private]=> | |
string(8) "password" | |
["con":"ssh2":private]=> | |
resource(4) of type (SSH2 Session) | |
["pubKeyFile":"ssh2":private]=> | |
string(29) "/var/www/example.com/.ssh/user.pub" | |
["privKeyFile":"ssh2":private]=> | |
string(25) "/var/www/example.com/.ssh/user" | |
["shell_type":"ssh2":private]=> | |
string(5) "xterm" | |
["shell":"ssh2":private]=> | |
NULL | |
["log":"ssh2":private]=> | |
array(0) { | |
} | |
["sftp":"ssh2":private]=> | |
resource(5) of type (SSH2 SFTP) | |
["knownHost":"ssh2":private]=> | |
string(32) "DF551756B1D7AE3592AD574AD4D9F462" | |
} | |
Attempting ssh2_disconnect(); time elapsed: 0.26224684715271 | |
Exiting; time elapsed: 0.26915097236633 | |
Segmentation fault (core dumped) | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment