3

I'm using phpseclib and need to make a couple of php functions that enable someone to programmatically ssh into their server and change the root password and also change the password of a user that may have forgotten their password (so have to be logged in as root).

I tried using libssh2, but found it a bit nasty to use. I'm now looking at phpseclib which seems more robust. But when I tried to use the 'su' command like so:

echo $ssh->exec('su');

I get the reply:

su: must be run from a terminal

and when I try to use sudo:

echo $ssh->exec('sudo passwd root');

I get the error:

sudo: no tty present and no askpass program specified

Anyway, it turns out that su is disabled for direct ssh access, but after having a look at this article, it turns out you can do it with the following command:

ssh -t -t -l 'username' 'host' 'su -'

That's what finally worked for me anyway when entering into a terminal from my laptop (running ubuntu), and then I entered my password and then the root password to finish off.

Quoting from the site linked to above:

Ssh commands (using -t) the remote sshd to establish a 'pseudo-terminal' pipe to the worker process when -t is given.

. ssh does this as long as its stdin is a terminal.

. But if ssh's stdin is a non-terminal, ssh won't direct sshd to establish a
pseudo-terminal unless TWO -t's are given:

echo password | ssh -t -t -l username remote_host

. So with -t -t (from ssh) sshd sets up a pseudo-terminal to the client process.

. The client, whether it be 'tty' or 'su' cannot tell it is connected to a ficticious >terminal:

echo dummystr | ssh -t -t -l username host.com -c ''tty'

echo password | ssh -t -t -l username host.com -c 'su -'

So there is the answer. Use double -t if you are 'su root'ing' on a linux box through an >interactive client ssh like the one from OpenBSD.

So, it actually worked from the terminal as I said above using:

ssh -t -t -l 'username' 'host' 'su -'

but I really want to be able to execute this command using phpseclib. Only thing is I don't know how to put in any flags into the exec() function. Specifically, I need to put in the -t flags (twice).

I've looked for ages and can't find anything. Be really grateful for some help on this. Sorry about the length of this post as well. :)

Cheers

Joe

neubert
  • 14,208
  • 21
  • 90
  • 172
Joe
  • 4,562
  • 9
  • 55
  • 79
  • You could share which library you're using already. I had to google phpseclib and then discovered there are two ssh implementations. – Till Apr 23 '11 at 01:21
  • Ah, sorry. I am using what I believe to be the latest phpseclib version: v 1.53 – Joe Apr 23 '11 at 10:15
  • No, what I mean is, phpseclib mentions `Net_SSH` and `Net_SSH2`. Which are you using? :) – Till Apr 23 '11 at 17:03

3 Answers3

2

You can enable the pseudoterminal by calling

$ssh->enablePTY();

after you login, but before the exec. This will prevent it from complaining about the missing tty.

Benubird
  • 15,843
  • 24
  • 83
  • 128
2

If sudo passwd root requires a tty try read() / write() in phpseclib. eg.

<?php
include('Net/SSH2.php');

$ssh = new Net_SSH2('localhost', 22);
$ssh->login('username', 'password');

$ssh->read('[prompt]');
$ssh->write("sudo passwd root\n");
$ssh->read('Password:');
$ssh->write("Password\n");
echo $ssh->read('[prompt]');
?>

Actually, I'm just copy / pasting from your other post: php ssh2_exec not executing 'su' command

Looks like you were getting some help there and then stopped following up? Someone suggested you need to add new lines to your commands. Did you try that? They also suggested posting on the phpseclib support forums. Seems like a good bit of advice to me...

Community
  • 1
  • 1
rhinestone
  • 54
  • 1
  • 1
    I don't see how till's example would work anyway. su - prompts for a password doesn't it? Where, in till's example, is a password provided to su? There's the password to SSH into the server but not the password to do the su... Also, when I do a Google search for it I see Net_SSH1 and Net_SSH2 for phpseclib. Not Net_SSH and Net_SSH2. That's important, I think, because there are two different SSH protocols - SSH1 and SSH2. Seems like one class would correspond to one and the other class would correspond to the other... – rhinestone Apr 24 '11 at 00:22
  • Depends - I guess you could use `sudo` instead. That might be the better option. – Till Apr 25 '11 at 21:25
1

I looked into phpseclib's Net_SSH2 for the time being. It looks like it uses sockets to connect to the server. So there's no way to pass in -t twice. It's not an ssh call.

Since you mentioned libssh2 in your question, there's a PEAR wrapper which supports it, might make things easier, the code is only in SVN currently. The PEAR wrapper is called Net_SSH2 as well, but is different from phpseclib's Net_SSH2 (confusing).

Check out the code here:

To download it, do an svn checkout out with:

svn co http://svn.php.net/repository/pear/packages/Net_SSH2/trunk/ ./Net_SSH2

Small example:

<?php
require_once './Net_SSH2/Net/SSH.php';
$ssh = new Net_SSH2::factory('LibSSH2', array(
    'login_name' => 'user',
    'password'   => 'pass',
    'hostname'   => 'example.org',
    'command'    => 'su -',
));
$ssh->sshExec($std_output, $std_error);
var_dump($std_output, $std_error);

Would that help?

Till
  • 21,590
  • 4
  • 55
  • 86
  • Thanks Till. Haven't has time to check this out yet, but I will. Will post back once I have done. – Joe Apr 25 '11 at 09:56