Merge pull request #806 from metaclassing/sshv1-exceptions

Exception support for SSHv1

* metaclassing/sshv1-exceptions:
  I misinterpreted the meaning of === true and messed up quotes on one throw
  Tried to replicate SSHv2 exception support into SSHv1
This commit is contained in:
Andreas Fischer 2015-09-07 00:39:26 +02:00
commit ef3d0a8ed0

View File

@ -537,14 +537,15 @@ class SSH1
* Connect to an SSHv1 server
*
* @return bool
* @throws \UnexpectedValueException on receipt of unexpected packets
* @throws \RuntimeException on other errors
* @access private
*/
function _connect()
{
$this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->connectionTimeout);
if (!$this->fsock) {
user_error(rtrim("Cannot connect to {$this->host}:{$this->port}. Error $errno. $errstr"));
return false;
throw new \RuntimeException(rtrim("Cannot connect to $host. Error $errno. $errstr"));
}
$this->server_identification = $init_line = fgets($this->fsock, 255);
@ -555,20 +556,17 @@ class SSH1
}
if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) {
user_error('Can only connect to SSH servers');
return false;
throw new \RuntimeException('Can only connect to SSH servers');
}
if ($parts[1][0] != 1) {
user_error("Cannot connect to SSH $parts[1] servers");
return false;
throw new \RuntimeException("Cannot connect to $parts[1] servers");
}
fputs($this->fsock, $this->identifier."\r\n");
$response = $this->_get_binary_packet();
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
user_error('Expected SSH_SMSG_PUBLIC_KEY');
return false;
throw new \UnexpectedValueException('Expected SSH_SMSG_PUBLIC_KEY');
}
$anti_spoofing_cookie = $this->_string_shift($response[self::RESPONSE_DATA], 8);
@ -652,8 +650,7 @@ class SSH1
$data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
if (!$this->_send_binary_packet($data)) {
user_error('Error sending SSH_CMSG_SESSION_KEY');
return false;
throw new \RuntimeException('Error sending SSH_CMSG_SESSION_KEY');
}
switch ($cipher) {
@ -682,8 +679,7 @@ class SSH1
$response = $this->_get_binary_packet();
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
user_error('Expected SSH_SMSG_SUCCESS');
return false;
throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS');
}
$this->bitmap = self::MASK_CONNECTED;
@ -697,6 +693,8 @@ class SSH1
* @param string $username
* @param string $password
* @return bool
* @throws \UnexpectedValueException on receipt of unexpected packets
* @throws \RuntimeException on other errors
* @access public
*/
function login($username, $password = '')
@ -715,8 +713,7 @@ class SSH1
$data = pack('CNa*', NET_SSH1_CMSG_USER, strlen($username), $username);
if (!$this->_send_binary_packet($data)) {
user_error('Error sending SSH_CMSG_USER');
return false;
throw new \RuntimeException('Error sending SSH_CMSG_USER');
}
$response = $this->_get_binary_packet();
@ -728,15 +725,13 @@ class SSH1
$this->bitmap |= self::MASK_LOGIN;
return true;
} elseif ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) {
user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
return false;
throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
}
$data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen($password), $password);
if (!$this->_send_binary_packet($data)) {
user_error('Error sending SSH_CMSG_AUTH_PASSWORD');
return false;
throw new \RuntimeException('Error sending SSH_CMSG_AUTH_PASSWORD');
}
// remove the username and password from the last logged packet
@ -756,8 +751,7 @@ class SSH1
} elseif ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) {
return false;
} else {
user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
return false;
throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
}
}
@ -792,20 +786,19 @@ class SSH1
* @see \phpseclib\Net\SSH1::interactiveWrite()
* @param string $cmd
* @return mixed
* @throws \RuntimeException on error sending command
* @access public
*/
function exec($cmd, $block = true)
{
if (!($this->bitmap & self::MASK_LOGIN)) {
user_error('Operation disallowed prior to login()');
return false;
throw new \RuntimeException('Operation disallowed prior to login()');
}
$data = pack('CNa*', NET_SSH1_CMSG_EXEC_CMD, strlen($cmd), $cmd);
if (!$this->_send_binary_packet($data)) {
user_error('Error sending SSH_CMSG_EXEC_CMD');
return false;
throw new \RuntimeException('Error sending SSH_CMSG_EXEC_CMD');
}
if (!$block) {
@ -841,6 +834,8 @@ class SSH1
* @see \phpseclib\Net\SSH1::interactiveRead()
* @see \phpseclib\Net\SSH1::interactiveWrite()
* @return bool
* @throws \UnexpectedValueException on receipt of unexpected packets
* @throws \RuntimeException on other errors
* @access private
*/
function _initShell()
@ -851,8 +846,7 @@ class SSH1
$data = pack('CNa*N4C', NET_SSH1_CMSG_REQUEST_PTY, strlen('vt100'), 'vt100', 24, 80, 0, 0, self::TTY_OP_END);
if (!$this->_send_binary_packet($data)) {
user_error('Error sending SSH_CMSG_REQUEST_PTY');
return false;
throw new \RuntimeException('Error sending SSH_CMSG_REQUEST_PTY');
}
$response = $this->_get_binary_packet();
@ -861,15 +855,13 @@ class SSH1
return false;
}
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
user_error('Expected SSH_SMSG_SUCCESS');
return false;
throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS');
}
$data = pack('C', NET_SSH1_CMSG_EXEC_SHELL);
if (!$this->_send_binary_packet($data)) {
user_error('Error sending SSH_CMSG_EXEC_SHELL');
return false;
throw new \RuntimeException('Error sending SSH_CMSG_EXEC_SHELL');
}
$this->bitmap |= self::MASK_SHELL;
@ -902,18 +894,17 @@ class SSH1
* @param string $expect
* @param int $mode
* @return bool
* @throws \RuntimeException on connection error
* @access public
*/
function read($expect, $mode = self::READ__SIMPLE)
{
if (!($this->bitmap & self::MASK_LOGIN)) {
user_error('Operation disallowed prior to login()');
return false;
throw new \RuntimeException('Operation disallowed prior to login()');
}
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
user_error('Unable to initiate an interactive shell session');
return false;
throw new \RuntimeException('Unable to initiate an interactive shell session');
}
$match = $expect;
@ -941,25 +932,23 @@ class SSH1
* @see \phpseclib\Net\SSH1::interactiveRead()
* @param string $cmd
* @return bool
* @throws \RuntimeException on connection error
* @access public
*/
function interactiveWrite($cmd)
{
if (!($this->bitmap & self::MASK_LOGIN)) {
user_error('Operation disallowed prior to login()');
return false;
throw new \RuntimeException('Operation disallowed prior to login()');
}
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
user_error('Unable to initiate an interactive shell session');
return false;
throw new \RuntimeException('Unable to initiate an interactive shell session');
}
$data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($cmd), $cmd);
if (!$this->_send_binary_packet($data)) {
user_error('Error sending SSH_CMSG_STDIN');
return false;
throw new \RuntimeException('Error sending SSH_CMSG_STDIN');
}
return true;
@ -976,18 +965,17 @@ class SSH1
*
* @see \phpseclib\Net\SSH1::interactiveRead()
* @return string
* @throws \RuntimeException on connection error
* @access public
*/
function interactiveRead()
{
if (!($this->bitmap & self::MASK_LOGIN)) {
user_error('Operation disallowed prior to login()');
return false;
throw new \RuntimeException('Operation disallowed prior to login()');
}
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
user_error('Unable to initiate an interactive shell session');
return false;
throw new \RuntimeException('Unable to initiate an interactive shell session');
}
$read = array($this->fsock);