Exemplo n.º 1
0
function ssh_open($remote, $password)
{
    global $php_version;
    global $debug;
    // Open a child process with the 'proc_open' function.
    //
    // Some tricks: we must open the connection using '-x' to disable
    // X11 forwarding, and use '-t -t' to avoid SSH generating an error
    // because we are not connected to any terminal.
    // NOTE:
    //   We require users to have an account and password on
    //   the UI and provide their user/password through the web or
    //   otherwise (e.g. using myproxy)
    //
    // NOTE: if the web server is trusted remotely (i.e. it's SSH public
    // key is accepted in ~user@host:.ssh/authorized_keys) then any
    // password will do.
    if ($php_version < 5) {
        // Prepare I/O
        $descriptorspec = array(0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w"));
        // prepare password
        putenv("DISPLAY=none:0.");
        putenv("SSH_ASKPASS={$tmpfname}");
        umask(077);
        $tmpfname = tempnam("/tmp", "egTinker");
        chmod($tmpfname, 0700);
        $fp = fopen($tmpfname, "w");
        fputs($fp, "#!/bin/sh\necho {$password}\n");
        fputs($fp, "rm {$tmpfname}\n");
        fclose($fp);
        $process = proc_open("ssh -x -t -t {$remote}", $descriptorspec, $pipes);
        if ($debug) {
            echo "ssh -x -t -t {$remote}<br />\n";
        }
        // check status
        if (!is_resource($process)) {
            letal("SSH::connect", "cannot connect to the remote host");
            return;
        }
        if ($debug) {
            echo "proc_open<br />\n";
        }
    } else {
        /* php5 -- we can use PTYs */
        /* XXX -- untested -- probably unneeded */
        $descriptorspec = array(0 => array("pty"), 1 => array("pty"), 2 => array("pty"));
        // prepare password
        putenv("DISPLAY=none:0.");
        putenv("SSH_ASKPASS={$tmpfname}");
        umask(077);
        $tmpfname = tempnam("/tmp", "egTinker");
        chmod($tmpfname, 0700);
        $fp = fopen($tmpfname, "w");
        fputs($fp, "#!/bin/sh\necho {$password}\n");
        fputs($fp, "rm {$tmpfname}\n");
        fclose($fp);
        $process = proc_open("ssh -x -t -t {$remote}", $descriptorspec, $pipes);
        // check status
        if (!is_resource($process)) {
            letal("SSH::connect", "cannot connect to the remote host");
            return;
        }
        $status = proc_get_status($process);
        if ($status->running == FALSE) {
            fclose($pipes[0]);
            fclose($pipes[1]);
            fclose($pipes[2]);
            proc_close($process);
            letal("SSH::connect", "connection exited " . $status->exitcode);
            return;
        }
        if ($status->signaled) {
            fclose($pipes[0]);
            fclose($pipes[1]);
            fclose($pipes[2]);
            proc_close($process);
            letal("SSH::connect", "connection terminated by " . $status->termsig);
            return;
        }
        if ($status->stopped) {
            // Tell the user and hope for the best
            warning("SSH::connect stopped by " . $status->stopsig . " it may still have a chance though");
        }
    }
    // $pipes now looks like this:
    //   0 => writeable handle connected to child stdin
    //   1 => readable handle connected to child stdout
    // We now have a connection to the remote Grid User Interface
    // Server which we may use to send commands/receive output
    return array('stdin' => $pipes[0], 'stdout' => $pipes[1], 'stderr' => $pipes[2]);
}
Exemplo n.º 2
0
 /**
  *	Open an SSH connection to run an interactive command on a remote
  * site
  *
  *	Connects to a remote host and runs an interactive command
  * with NO controlling terminal.
  *
  *	This routine creates communication streams with the remote shell,
  * and stores all output (standard and error) of the connection into
  * two separate local log files (one for stdout and one for stderr).
  *
  *	Returns a process_control array which contains the process resource
  * ID and an the standard file descriptors which the caller may use to
  * interact with the remote shell.
  *
  * The process control array contains:
  *
  *	'process' -- the process resource for the newly created connection
  *
  *	'std_in' -- handle to the standard input of the new connection
  *
  *	'std_out' -- handle to standard output of the new connection
  *
  *	'std_err' -- handle to standard error of the new connection
  *
  *	'stdout_file' -- actual filename of the local log file for the
  *		new connection standard output
  *
  *	'stderr_file' -- actual filename of the local log file for the
  *		new connection standard error
  *
  *	@param	string command to be executed interactively on the remote end
  *
  *	@return mixed|false a process control associative array or FALSE
  *	    	on failure.
  *
  *	@access public
  *  @since Method available since Release 1.0
  */
 function ssh_open_command($command)
 {
     global $debug_sexec;
     // Open a child process with the 'proc_open' function.
     //
     // Some tricks: we must open the connection using '-x' to disable
     // X11 forwarding, and use '-t -t' to avoid SSH generating an error
     // because we are not connected to any terminal.
     //
     // NOTE: if the web server is trusted remotely (i.e. it's SSH public
     // key is accepted in ~user@host:.ssh/authorized_keys) then any
     // password will do.
     // Prepare I/O
     umask(077);
     if ($debug_sexec) {
         $child_stdout = tempnam($this->workdir, "open_cmd-" . getmypid() . "-1-");
         $child_stderr = tempnam($this->workdir, "open_cmd-" . getmypid() . "-2-");
     } else {
         $child_stdout = tempnam($this->workdir, "open_cmd-");
         $child_stderr = tempnam($this->workdir, "open_cmd-");
     }
     $descriptorspec = array(0 => array("pipe", "r"), 1 => array("file", $child_stdout, "a"), 2 => array("file", $child_stderr, "a"));
     if ($debug_sexec) {
         echo "{$this->ssh} -x -t -t -S {$this->mplex_socket} {$this->remote} {$command}<br />\n";
     }
     $process = proc_open("{$this->ssh} -x -t -t -S {$this->mplex_socket} {$this->remote} \"{$command}\"", $descriptorspec, $pipes);
     // check status
     if (!is_resource($process) || $process == FALSE) {
         letal("SSH::connect", "cannot connect to the remote host");
         return FALSE;
     }
     if ($debug_sexec) {
         echo "proc_open done<br />\n";
     }
     // $pipes now looks like this:
     //   0 => writeable handle connected to child stdin
     // Open child's stdin and stdout
     $pipes[1] = fopen($child_stdout, "r");
     $pipes[2] = fopen($child_stderr, "r");
     // Should we leave this to the user?
     // set to non-blocking and avoid having to call fflush
     #stream_set_blocking($pipes[0], FALSE);
     #stream_set_blocking($pipes[1], FALSE);
     #stream_set_blocking($pipes[2], FALSE);
     stream_set_write_buffer($pipes[0], 0);
     stream_set_write_buffer($pipes[1], 0);
     stream_set_write_buffer($pipes[2], 0);
     // We now have a connection to the remote SSH
     // Server which we may use to send commands/receive output
     $p = array('process' => $process, 'std_in' => $pipes[0], 'std_out' => $pipes[1], 'std_err' => $pipes[2], 'stdout_file' => $child_stdout, 'stderr_file' => $child_stderr);
     if ($debug_sexec) {
         echo "process descriptor array is \n";
         print_r($p);
     }
     return $p;
 }