diff --git a/phpseclib/Net/SSH2.php b/phpseclib/Net/SSH2.php index 2d88e4b2..c400e543 100644 --- a/phpseclib/Net/SSH2.php +++ b/phpseclib/Net/SSH2.php @@ -73,10 +73,11 @@ * @access private */ define('NET_SSH2_MASK_CONSTRUCTOR', 0x00000001); -define('NET_SSH2_MASK_LOGIN_REQ', 0x00000002); -define('NET_SSH2_MASK_LOGIN', 0x00000004); -define('NET_SSH2_MASK_SHELL', 0x00000008); -define('NET_SSH2_MASK_WINDOW_ADJUST', 0X00000010); +define('NET_SSH2_MASK_CONNECTED', 0x00000002); +define('NET_SSH2_MASK_LOGIN_REQ', 0x00000004); +define('NET_SSH2_MASK_LOGIN', 0x00000008); +define('NET_SSH2_MASK_SHELL', 0x00000010); +define('NET_SSH2_MASK_WINDOW_ADJUST', 0X00000020); /**#@-*/ /**#@+ @@ -669,6 +670,7 @@ class Net_SSH2 /** * Time of first network activity * + * @var Integer * @access private */ var $last_packet; @@ -684,6 +686,7 @@ class Net_SSH2 /** * Flag to request a PTY when using exec() * + * @var Boolean * @see Net_SSH2::enablePTY() * @access private */ @@ -692,6 +695,7 @@ class Net_SSH2 /** * Flag set while exec() is running when using enablePTY() * + * @var Boolean * @access private */ var $in_request_pty_exec = false; @@ -699,6 +703,7 @@ class Net_SSH2 /** * Flag set after startSubsystem() is called * + * @var Boolean * @access private */ var $in_subsystem; @@ -706,6 +711,7 @@ class Net_SSH2 /** * Contents of stdError * + * @var String * @access private */ var $stdErrorLog; @@ -714,6 +720,7 @@ class Net_SSH2 * The Last Interactive Response * * @see Net_SSH2::_keyboard_interactive_process() + * @var String * @access private */ var $last_interactive_response = ''; @@ -722,6 +729,7 @@ class Net_SSH2 * Keyboard Interactive Request / Responses * * @see Net_SSH2::_keyboard_interactive_process() + * @var Array * @access private */ var $keyboard_requests_responses = array(); @@ -734,6 +742,7 @@ class Net_SSH2 * * @see Net_SSH2::_filter() * @see Net_SSH2::getBannerMessage() + * @var String * @access private */ var $banner_message = ''; @@ -741,7 +750,8 @@ class Net_SSH2 /** * Did read() timeout or return normally? * - * @see Net_SSH2::isTimeout + * @see Net_SSH2::isTimeout() + * @var Boolean * @access private */ var $is_timeout = false; @@ -750,6 +760,7 @@ class Net_SSH2 * Log Boundary * * @see Net_SSH2::_format_log + * @var String * @access private */ var $log_boundary = ':'; @@ -758,6 +769,7 @@ class Net_SSH2 * Log Long Width * * @see Net_SSH2::_format_log + * @var Integer * @access private */ var $log_long_width = 65; @@ -766,10 +778,29 @@ class Net_SSH2 * Log Short Width * * @see Net_SSH2::_format_log + * @var Integer * @access private */ var $log_short_width = 16; + /** + * Hostname + * + * @see Net_SSH2::login() + * @var String + * @access private + */ + var $host; + + /** + * Port Number + * + * @see Net_SSH2::login() + * @var Integer + * @access private + */ + var $port; + /** * Default Constructor. * @@ -797,7 +828,6 @@ class Net_SSH2 include_once 'Crypt/Hash.php'; } - $this->last_packet = strtok(microtime(), ' ') + strtok(''); // == microtime(true) in PHP5 $this->message_numbers = array( 1 => 'NET_SSH2_MSG_DISCONNECT', 2 => 'NET_SSH2_MSG_IGNORE', @@ -868,11 +898,22 @@ class Net_SSH2 61 => 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE') ); + $this->host = $host; + $this->port = $port; + $this->timeout = $timeout; + } + + function _connect() + { + $timeout = $this->timeout; + + $this->last_packet = strtok(microtime(), ' ') + strtok(''); // == microtime(true) in PHP5 + $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838 - $this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout); + $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $timeout); if (!$this->fsock) { - user_error(rtrim("Cannot connect to $host. Error $errno. $errstr")); - return; + user_error(rtrim("Cannot connect to $this->host:$this->port. Error $errno. $errstr")); + return false; } $elapsed = strtok(microtime(), ' ') + strtok('') - $start; @@ -880,7 +921,7 @@ class Net_SSH2 if ($timeout <= 0) { user_error(rtrim("Cannot connect to $host. Timeout error")); - return; + return false; } $read = array($this->fsock); @@ -893,7 +934,7 @@ class Net_SSH2 // the !count() is done as a workaround for if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) { user_error(rtrim("Cannot connect to $host. Banner timeout")); - return; + return false; } /* According to the SSH2 specs, @@ -932,7 +973,7 @@ class Net_SSH2 if ($matches[1] != '1.99' && $matches[1] != '2.0') { user_error("Cannot connect to SSH $matches[1] servers"); - return; + return false; } fputs($this->fsock, $this->identifier . "\r\n"); @@ -940,19 +981,21 @@ class Net_SSH2 $response = $this->_get_binary_packet(); if ($response === false) { user_error('Connection closed by server'); - return; + return false; } if (ord($response[0]) != NET_SSH2_MSG_KEXINIT) { user_error('Expected SSH_MSG_KEXINIT'); - return; + return false; } if (!$this->_key_exchange($response)) { - return; + return false; } - $this->bitmap = NET_SSH2_MASK_CONSTRUCTOR; + $this->bitmap = NET_SSH2_MASK_CONNECTED; + + return true; } /** @@ -1694,6 +1737,13 @@ class Net_SSH2 */ function login($username) { + if (!($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR)) { + $this->bitmap != NET_SSH2_MASK_CONSTRUCTOR; + if (!$this->_connect()) { + return false; + } + } + $args = func_get_args(); return call_user_func_array(array(&$this, '_login'), $args); } @@ -1735,7 +1785,7 @@ class Net_SSH2 */ function _login_helper($username, $password = null) { - if (!($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR)) { + if (!($this->bitmap & NET_SSH2_MASK_CONNECTED)) { return false; } @@ -2687,7 +2737,7 @@ class Net_SSH2 } // see http://tools.ietf.org/html/rfc4252#section-5.4; only called when the encryption has been activated and when we haven't already logged in - if (($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR) && !($this->bitmap & NET_SSH2_MASK_LOGIN) && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) { + if (($this->bitmap & NET_SSH2_MASK_CONNECTED) && !($this->bitmap & NET_SSH2_MASK_LOGIN) && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) { $this->_string_shift($payload, 1); extract(unpack('Nlength', $this->_string_shift($payload, 4))); $this->banner_message = utf8_decode($this->_string_shift($payload, $length)); @@ -2695,7 +2745,7 @@ class Net_SSH2 } // only called when we've already logged in - if (($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR) && ($this->bitmap & NET_SSH2_MASK_LOGIN)) { + if (($this->bitmap & NET_SSH2_MASK_CONNECTED) && ($this->bitmap & NET_SSH2_MASK_LOGIN)) { switch (ord($payload[0])) { case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4 $this->_string_shift($payload, 1); @@ -2907,7 +2957,7 @@ class Net_SSH2 // currently, there's only one possible value for $data_type_code: NET_SSH2_EXTENDED_DATA_STDERR extract(unpack('Ndata_type_code/Nlength', $this->_string_shift($response, 8))); $data = $this->_string_shift($response, $length); - $this->stdErrorLog .= $data; + $this->stdErrorLog.= $data; if ($skip_extended || $this->quiet_mode) { break; }