phpseclib ssh2 enable tty - php

my ssh script:
include('Net/SSH2.php');
set_include_path(getcwd());
$ssh_host = "myserver.com";
if($ssh_host != null){
$ssh_user = globals::$ssh_logins[$ssh_host];
$ssh = new Net_SSH2($ssh_host);
//$ssh->enablePTY();
if (!$ssh->login($ssh_user['username'], $ssh_user['password'])) {
echo $ssh->isConnected() ? 'bad username or password' : 'unable to establish connection';
}
echo $ssh->exec('sudo bash /myscript.sh');
}else{
echo "no host: " . $ssh_host;
}
when calling:
echo $ssh->exec('sudo bash /myscript.sh');
i get the output:
stdin: is not a tty
sudo: sorry, you must have a tty to run sudo
how do i enable tty on phpseclib?
Sudo is necessary also it is important to retrieve the output. my script returns multiple lines.
Centos 7
PHP 7
interesting link: https://unix.stackexchange.com/questions/136676/sudo-sorry-you-must-have-a-tty-to-run-sudo-when-using-sudo-in-a-remote-scrip?newreg=f31852b195804fd1b988aeb0a9ce59d9

You're on the right track with your $ssh->enablePTY() but once you do that you'll need to do $ssh->read(). Without a PTY $ssh->exec() will return the commands output. If you do $ssh->enablePTY() you'll need to do $ssh->read() to get output.
The reason for this is that with a PTY data can be sent to and from the shell whereas it can't without a PTY. Without a PTY the output you get is the output you get and no input can change that because you can't send input. With a PTY input can change the output.
Also relevant, phpseclib's docs talk about doing sudo with it. From http://phpseclib.sourceforge.net/ssh/examples.html#sudo :
<?php
include('Net/SSH2.php');
$ssh = new Net_SSH2('www.domain.tld');
if (!$ssh->login('username', 'password')) {
exit('Login Failed');
}
echo $ssh->read('username#username:~$');
$ssh->write("sudo ls -la\n");
$output = $ssh->read('#[pP]assword[^:]*:|username#username:~\$#', NET_SSH2_READ_REGEX);
echo $output;
if (preg_match('#[pP]assword[^:]*:#', $output)) {
$ssh->write("password\n");
echo $ssh->read('username#username:~$');
}
If your account doesn't have a password I guess it doesn't matter but if you do have a password then you'll need to do something like the above.

Related

Real-time SSH output in Laravel with phpseclib

I've tried different SSH libraries but they don't seem to work too well in Laravel. Since I got phpseclib to work well, I'm trying to stick with it. But, I'm not seeing a way to have a live output from the SSH connection.
Some things that I plan on running can take up to a few hours to finish but the software being accessed always prints out a percentage of completion that I'd like to utilize to display in the browser.
Currently, I have this:
<?php
use phpseclib\Net\SSH2;
use phpseclib\Crypt\RSA;
$key = new RSA();
$key->loadKey(file_get_contents('key.pem'));
$command = 'ping google.com';
$ssh = new SSH2('awesomeserver.com');
if (!$ssh->login('username', $key))
{
echo 'Login Failed';
}
else
{
echo $ssh->exec($command);
}
?>
This just waits until the command is complete and then just barfs it all onto the screen.
Previously, in the else bracket, I had
while(# ob_end_flush());
$proc = $ssh->exec($command);
while(!feof($proc))
{
echo fread($proc, 4096);
# flush();
}
But, $proc was only recognized as a string instead of a resource, so it didn't work.
Do you all have any other suggestions, other than using a different library?
Thanks!
EDIT (Partial solution):
I eventually got this script to work by utilizing the read() function with this:
while(# ob_end_flush());
$ssh->write($command.'\n');
while($read = $ssh->read())
{
echo $read;
# flush();
}
You could employee a callback. eg.
$ssh->exec('ping 127.0.0.1', function($output) {
echo $output;
});

PHP shell_exec does not work for some commands?

If I do the following command, I get an 'hey' output:
echo shell_exec("echo 'hey'");
But If I do the following command, it will not kill any screen:
echo shell_exec("killall screen");
Or if I do
echo shell_exec("sh /var/www/html/run.sh");
It will not run that file at all (that file does the screen killing aswell)
And If I even get that file with get contents, it successfully reads the content in it.
If it can execute echo so whats wrong?
To run such powerful commands, I had to use this library as stated in this question. This allows me to login into the SSH with root access and execute any command!
function ssh_script($script, $ip, $user, $pass) {
$ssh = new Net_SSH2($ip);
if (!$ssh->login($user, $pass)) {
exit('Login Failed');
}
if ($ssh !== false) {
echo $ssh->exec("sh " . $script);
}
else {
echo "fail";
}
}

SSH2 and PHP not working 'Terminal'

Whenever I try and execute
if (!($stream = ssh2_exec($con, "cd $dir; screen -S creative java -Xmx500M -Xms500M -jar spigot.jar" ))) {
it keeps returning with 'Must be connected to a terminal.' which I can't seem to get around.
How do I get around/fix this?
You could try to use phpseclib's read() / write() functions. eg.
<?php
include('Net/SSH2.php');
$ssh = new Net_SSH2('www.domain.tld');
if (!$ssh->login('username', 'password')) {
exit('Login Failed');
}
echo $ssh->read('username#username:~$');
$ssh->write("ls -la\n"); // note the "\n"
echo $ssh->read('username#username:~$');
Test this :
You should pass a pty emulation name ("vt102", "ansi", etc...) if you want to emulate a pty, or NULL if you don't.
Passing false will convert false to a string, and will allocate a "" terminal.
cf. http://php.net/manual/fr/function.ssh2-exec.php
Starting screen like you did requires a valid TTY because of it get's attached to your session. The ssh implementation of PHP just doesn't create a session like that.
Starting screen detached should do the trick:
screen -d -m [<command>]
So your code would look like:
if (!($stream = ssh2_exec($con, "cd $dir; screen -d -m -S creative java -Xmx500M -Xms500M -jar spigot.jar" ))) {

PHP Connect over ssh with public key and switch user to execute commands

Good evening,
currently I'm developing on a script that uses PHP. PHP uses "ssh2_connect" with Public Key as command for the connection to a remote host. Furthermore i use ssh2_exec to execute some commands with user_a. I would like to switch to user_b to execute antoher command and
optional to return to user_a.
$connection = ssh2_connect('192.168.2.100', 22, array('hostkey'=>'ssh-rsa'));
if (ssh2_auth_pubkey_file($connection, 'user_a', './ssh/id_rsa.pub', './ssh/id_rsa'))
{
echo "Public Key Authentication Successful\n<br />";
}
else
{
die('Public Key Authentication Failed');
}
if(!($stream = ssh2_exec($connection, "sudo su user_b ; cd ~ ; ls -la" )) )
{
echo "fail: unable to execute command\n";
}
else
{
stream_set_blocking( $stream, true );
echo stream_get_contents($stream);
}
ssh2_exec($connection, 'exit');
unset($connection);
The problem is a normal command works well but switching a user returns in a timeout (sudo File was edited)... I've already tried it with fwrite to send commands.
;
Is there any solution to fix this with a few commands (own php code) or is it better to use http://phpseclib.sourceforge.net/ ?
So you could probably do this:
echo password | sudo su user_b ; cd ~ ; ls -la
The downside of this would be that it'd show up in your bash history.
Here's a way to do it with phpseclib without having it show up in your bash history without having it show up in your bash history:
Here's a way to get the password to sudo with phpseclib / interactive mode:
<?php
include('Net/SSH2.php');
include('Crypt/RSA.php');
$rsa = new Crypt_RSA();
$rsa->loadKey('./ssh/id_rsa');
$ssh = new Net_SSH2('192.168.2.100');
if ($ssh->login('user_r', $rsa)) {
echo "Public Key Authentication Successful\n<br />";
} else {
die('Public Key Authentication Failed');
}
echo $ssh->read('username#username:~$');
$ssh->write("sudo su user_b\n");
$output = $ssh->read('#[pP]assword[^:]*:|username#username:~\$#', NET_SSH2_READ_REGEX);
echo $output;
if (preg_match('#[pP]assword[^:]*:#', $output)) {
$ssh->write("password\n");
echo $ssh->read('username#username:~$');
}
$ssh->write("cd ~\n");
echo $ssh->read('username#username:~$');
$ssh->write("ls -la\n");
echo $ssh->read('username#username:~$');
?>
Here's how to do it with phpseclib if you don't care about bash history:
<?php
include('Net/SSH2.php');
include('Crypt/RSA.php');
$rsa = new Crypt_RSA();
$rsa->loadKey('./ssh/id_rsa');
$ssh = new Net_SSH2('192.168.2.100');
if ($ssh->login('user_r', $rsa)) {
echo "Public Key Authentication Successful\n<br />";
} else {
die('Public Key Authentication Failed');
}
echo $ssh->exec("sudo su user_b ; cd ~ ; ls -la");

Waiting for command to finish using SSH2_Shell in PHP

I have an SSH2_Shell session working in PHP. my issue is that i need a command to completely finish before moving onto the next command. Here is my code so far:
$command_capture = "cd /mnt/NADS/scripts/";
$command_capture2 = "./tcpdump.sh $capture_name $sleep";
if (!($connection = ssh2_connect("172.20.1.18", 22))) {
echo "fail: unable to establish connection";
}
if (!ssh2_auth_password($connection, "root", "Hideandseek")) {
echo "fail: unable to authenticate";
}
$stream = ssh2_shell($connection);
fwrite($stream, $command_capture. PHP_EOL);
sleep(1);
fwrite($stream, $command_capture2 . PHP_EOL);
sleep(5);
$data="";
while($buf = stream_get_contents($stream)){
$data.=$buf;
}
echo $data;
fclose($stream);
the tcpdump.sh script is running a lftp command but is not being given anough time to complete. I cant use sleep as it may take longer then the specified time and i dont want to make the user wait if it only needs a few seconds. I have not had luck implementing stream_set_blocking as when i do, it seems to freeze up my browser.
overall, I need a way to detect when a command has finished and move into the next command.
Thanks in advance!
Thanks for the ideas but I think I got it solved. I did an echo of a few special characters when the command finished and then I would search for the characters using strpos(). Another thing I think may have helped was adjusting the max_execution_time setting in the php.ini file. I found that answer here:
http://verysimple.com/2006/03/30/fatal-error-maximum-execution-time-of-30-seconds-exceeded/
And here is my new code
$data="";
while (true){
$data .= stream_get_contents($stream);
if (strpos($data,"XOXO") !== false) {
echo "okay: command finished\n";
break;
}
}
echo $data;
fclose($stream);
I have an SSH2 class that implements the Secure Shell2 over on github .. check out https://github.com/bubba-h57/PHP-SSH2 and see if that helps.
I continue to search for a better way to handle finding the prompts though, so any advice or contribution to that would be welcomed. Hopefully it will help, if nothing more than giving you some ideas.
You could use phpseclib, a pure PHP SSH implementation. eg.
<?php
include('Net/SSH2.php');
$ssh = new Net_SSH2();
$ssh->login('username', 'password');
echo $ssh->exec('command');
echo $ssh->exec('command2');
?>
If you really need shell support you could do the following (with the latest SVN):
<?php
include('Net/SSH2.php');
$ssh = new Net_SSH2();
$ssh->login('username', 'password');
$ssh->read('[prompt]');
$ssh->write("command\n");
echo $ssh->read('[prompt]');
$ssh->write("command\n");
echo $ssh->read('[prompt]');
?>

Categories