Question

Here's what I'm trying to achieve: open a shell (korn or bash, doesn't matter), from that shell, I want to open a ssh connection (ssh user@host). At some point it is likely to happen I will be prompted for either a password or I might be asked whether or not I'm sure I want to connect (offending keys).

Before anyone asks: yes, I am aware there is a plugin for ssh2 exec calls, but the servers I'm working on don't support it, and are unlikely to do so.

Here's what I've tried so far:

$desc = array(array('pipe','r'),array('pipe','w'));//used in all example code
$p = proc_open('ssh user@host',$desc,$pipes);
if(!is_resource($p)){ die('@!#$%');}//will omit this line from now on
sleep(1);//omitting this,too but it's there every time I need it

Then I tried to read console output (stream_get_contents($pipes[1])) to see what I have to pass next (either password, yes or return 'connection failed: '.stream_get_contents($pipes[1]) and proc_close $p.

This gave me the following error:

Pseudo-terminal will not be allocated because stdin is not a terminal.

So, I though ssh was called in the php:// io-stream context, seems a plausible explanation of the above error.

Next: I though about my first SO question and decided it might be a good idea to open a bash/ksh shell first:

$p = proc_open('bash',$desc,$pipes);

And take it from there, but I got the exact same error message, only this time, the script stopped running but ssh did run. So I got hopeful, then felt stupid and, eventually, desperate:

$p=proc_open('bash && ssh user@host',$desc,$pipes);

After a few seconds wait, I got the following error:

PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 133693440 bytes)

The Call Stack keeps bringing up the stream_get_contents line, even in my last desperate attempt:

#!/path/to/bin/php -n
<?php
    $p = proc_open('bash && ssh user@host',array(array('pipe','r'),array('pipe','w')),$ps);
    if (!is_resource($p))
    {
        die('FFS');
    }
    usleep(10);
    fwrite($ps[0],'yes'."\n");
    fflush($ps[0]);
    usleep(20);
    fwrite($ps[0],'password'."\n");
    fflush($ps[0]);
    usleep(20);
    fwrite($ps[0],'whoami'."\n");
    fflush($ps[0]);
    usleep(2);
    $msg = stream_get_contents($ps[1]);
    fwrite($ps[0],'exit'."\n");
    fclose($ps[0]);
    fclose($ps[1]);
    proc_close($p);
?>

I know, its a mess, a lot of fflush and redundancy, but the point is: I know this connection will first prompt me for offending keys, and then ask a password. My guess is the stream in $pipes[1] holds the ssh connection, hence it's content is huge. what I need then, is a pipe inside a pipe... is this even possible? I must be missing something, what good is a pipe if this isn't possible... My guess is the proc_open command is wrong to begin with, (error: Broken pipe). But I really can't see any other way around the first error... any thoughts? Or follow up questions if the above rant isn't at all clear (which it probably isn't).

Was it helpful?

Solution

Before anyone asks: yes, I am aware there is a plugin for ssh2 exec calls, but the servers I'm working on don't support it, and are unlikely to do so.

There are actually two. The PECL module, which is a PITA that most servers don't have installed anyway and phpseclib, a pure PHP SSH2 implementation. An example of its use:

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

$ssh = new Net_SSH2('www.domain.tld');
if (!$ssh->login('username', 'password')) {
    exit('Login Failed');
}

echo $ssh->exec('pwd');
echo $ssh->exec('ls -la');
?>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top