Updated a CentOS server, from pecl ssh2 version 1.4.1 to 1.5.0, and completely changed/broke the existing ssh/sftp connectivity we had built.
Below is a short example showing the issue at hand.
<?php
/**
* Minimal reproduction: ssh2.sftp:// stream wrapper opendir() failure
*
* Tests whether opendir() works via the ssh2.sftp:// stream wrapper.
* Known behavior:
* php-pecl-ssh2 1.4.1 -- opendir() returns a valid handle
* php-pecl-ssh2 1.5.0 -- opendir() returns false (regression)
*
* Usage:
* php ssh2_stream_wrapper_repro.php <host> <port> <user> <password> [<dir>]
*
* Example:
* php ssh2_stream_wrapper_repro.php sftp.example.com 22 myuser mypassword /
*/
if ($argc < 5) {
fprintf(STDERR, "Usage: %s <host> <port> <user> <password> [<dir>]\n", $argv[0]);
exit(1);
}
$host = $argv[1];
$port = (int)$argv[2];
$user = $argv[3];
$pwd = $argv[4];
$dir = isset($argv[5]) ? $argv[5] : "/";
echo "ssh2 extension version : " . phpversion("ssh2") . "\n";
echo "PHP version : " . PHP_VERSION . "\n";
echo "Host : {$host}:{$port}\n";
echo "User : {$user}\n";
echo "Directory : {$dir}\n";
echo str_repeat("-", 50) . "\n";
// Step 1: connect
echo "ssh2_connect() : ";
$conn = ssh2_connect($host, $port);
var_dump($conn);
if (!$conn) { echo "FAIL: could not connect\n"; exit(1); }
// Step 2: authenticate
echo "ssh2_auth_password() : ";
$auth = ssh2_auth_password($conn, $user, $pwd);
var_dump($auth);
if (!$auth) { echo "FAIL: authentication failed\n"; exit(1); }
// Step 3: open SFTP subsystem
echo "ssh2_sftp() : ";
$sftp = ssh2_sftp($conn);
var_dump($sftp);
if (!$sftp) { echo "FAIL: could not open SFTP subsystem\n"; exit(1); }
// Step 4: show how the resource looks and what intval() gives
echo "intval(\$sftp) : ";
var_dump(intval($sftp));
// Step 5: build the stream wrapper URL
$url = "ssh2.sftp://" . intval($sftp) . $dir;
echo "Stream wrapper URL : {$url}\n";
// Step 6: the actual test — opendir via stream wrapper
echo "opendir() : ";
$handle = opendir($url);
var_dump($handle);
if ($handle === false) {
echo "FAIL: opendir() returned false — stream wrapper is broken\n";
exit(1);
}
// Step 7: list a few entries to confirm it actually works
echo "Directory listing :\n";
$count = 0;
while (false !== ($entry = readdir($handle))) {
if ($entry === "." || $entry === "..") continue;
echo " {$entry}\n";
if (++$count >= 10) { echo " (truncated after 10 entries)\n"; break; }
}
closedir($handle);
echo str_repeat("-", 50) . "\n";
echo "PASS: stream wrapper opendir() works correctly\n";
Examples of each:
v1.4.1:
php tmp.php host.com 22 user REDACTED /
ssh2 extension version : 1.4.1
PHP version : 8.4.20
Host : host.com:22
User : user
Directory : /
--------------------------------------------------
ssh2_connect() : resource(4) of type (SSH2 Session)
ssh2_auth_password() : bool(true)
ssh2_sftp() : resource(5) of type (SSH2 SFTP)
intval($sftp) : int(5)
Stream wrapper URL : ssh2.sftp://5/
opendir() : resource(7) of type (stream)
Directory listing :
boot
dev
home
proc
run
sys
tmp
etc
root
var
(truncated after 10 entries)
v1.5.0
php tmp.php host.com 22 user REDACTED /
ssh2 extension version : 1.5.0
PHP version : 8.4.20
Host : host.com:22
User : user
Directory : /
--------------------------------------------------
ssh2_connect() : resource(4) of type (SSH2 Session)
ssh2_auth_password() : bool(true)
ssh2_sftp() : resource(5) of type (SSH2 SFTP)
intval($sftp) : int(5)
Stream wrapper URL : ssh2.sftp://5/
opendir() : bool(false)
FAIL: opendir() returned false — stream wrapper is broken
Updated a CentOS server, from pecl ssh2 version 1.4.1 to 1.5.0, and completely changed/broke the existing ssh/sftp connectivity we had built.
Below is a short example showing the issue at hand.
Examples of each:
v1.4.1:
v1.5.0