どもです。
こういったPHPによるSSH接続があったとして。
if($connection = ssh2_connect($ip, 22)){
$pass = @ssh2_auth_password($connection, $user, $password);
[中略]
if($pass){
$sftp = ssh2_sftp($connection);
}
}ssh2_sftpのところで以下のエラーが発生してしまいました。
Warning: ssh2_sftp(): Unable to startup SFTP subsystem: session not authenticated yet
接続情報は正しく、ssh2_auth_passwordの戻り値($pass)がtrueなのに、ssh2_sftpでエラーになってしまう。
当然、この後に続くSSHの関数も全てエラーです。
この原因ですが、実は先ほど[中略]とした部分にありまして。
if($connection = ssh2_connect($ip, 22)){
$pass = @ssh2_auth_password($connection, $user, $password);
if(!$pass){
$pass = @ssh2_auth_password($connection, $user2, $password2);
}
if($pass){
$sftp = ssh2_sftp($connection);
}
}本当はこういう構造でした。ログイン情報が2種類あり、1に失敗した場合は2で実行する。
問題が起きたサーバーは、ログイン情報2の方で接続に成功していました。
しかし、どちらにせよ$passはtrueであり、ssh2_sftpには影響がないはずでは…???
と思いきや、OpenSSH8.8以降では「セッション中にユーザー名を変更して認証し直す」が禁止されるようになっていたのでした。
そしてPHPのssh2_系の関数はエラーハンドリングが大雑把で、内部で何が起きて失敗しても「Unable to startup SFTP subsystem: session not authenticated yet」エラーを吐くのですって。
ほげぇ。
つまり、一度ssh2_auth_passwordに失敗したら、そのセッションは一旦捨ててしまわないといけないということです。
if($connection = ssh2_connect($ip, 22)){
$pass = @ssh2_auth_password($connection, $user, $password);
if(!$pass){
@ssh2_exec($connection, "exit");
$connection = ssh2_connect($ip, 22)
$pass = @ssh2_auth_password($connection, $user2, $password2);
}
if($pass){
$sftp = ssh2_sftp($connection);
}
}これで無事に接続成功。
調べるときってこういう「実は…」の部分を省きがちなので、永遠に解が出てこないことがありますね…