- improved error logging capability

git-svn-id: http://phpseclib.svn.sourceforge.net/svnroot/phpseclib/trunk@86 21d32557-59b3-4da0-833f-c5933fad653e
This commit is contained in:
Jim Wigginton 2010-02-12 23:02:13 +00:00
parent 66489c3733
commit 76e4066e94
2 changed files with 167 additions and 57 deletions

View File

@ -48,7 +48,7 @@
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMIX Jim Wigginton * @copyright MMIX Jim Wigginton
* @license http://www.gnu.org/licenses/lgpl.txt * @license http://www.gnu.org/licenses/lgpl.txt
* @version $Id: SFTP.php,v 1.15 2010-02-11 16:17:40 terrafrost Exp $ * @version $Id: SFTP.php,v 1.16 2010-02-12 23:02:13 terrafrost Exp $
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -202,6 +202,16 @@ class Net_SFTP extends Net_SSH2 {
*/ */
var $packet_log = array(); var $packet_log = array();
/**
* Error information
*
* @see Net_SFTP::getSFTPErrors()
* @see Net_SFTP::getLastSFTPError()
* @var String
* @access private
*/
var $errors = array();
/** /**
* Default Constructor. * Default Constructor.
* *
@ -253,7 +263,14 @@ class Net_SFTP extends Net_SSH2 {
); );
$this->status_codes = array( $this->status_codes = array(
0 => 'NET_SFTP_STATUS_OK', 0 => 'NET_SFTP_STATUS_OK',
1 => 'NET_SFTP_STATUS_EOF' 1 => 'NET_SFTP_STATUS_EOF',
2 => 'NET_SFTP_STATUS_NO_SUCH_FILE',
3 => 'NET_SFTP_STATUS_PERMISSION_DENIED',
4 => 'NET_SFTP_STATUS_FAILURE',
5 => 'NET_SFTP_STATUS_BAD_MESSAGE',
6 => 'NET_SFTP_STATUS_NO_CONNECTION',
7 => 'NET_SFTP_STATUS_CONNECTION_LOST',
8 => 'NET_SFTP_STATUS_OP_UNSUPPORTED'
); );
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-7.1 // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-7.1
// the order, in this case, matters quite a lot - see Net_SFTP::_parseAttributes() to understand why // the order, in this case, matters quite a lot - see Net_SFTP::_parseAttributes() to understand why
@ -477,10 +494,8 @@ class Net_SFTP extends Net_SSH2 {
$realpath = $this->_string_shift($response, $length); $realpath = $this->_string_shift($response, $length);
break; break;
case NET_SFTP_STATUS: case NET_SFTP_STATUS:
// skip over the status code - hopefully the error message will give us all the info we need, anyway extract(unpack('Nstatus/Nlength', $this->_string_shift($response, 8)));
$this->_string_shift($response, 4); $this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->debug_info.= "\r\n\r\nSSH_FXP_STATUS:\r\n" . $this->_string_shift($response, $length);
return false; return false;
default: default:
user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS', E_USER_NOTICE); user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS', E_USER_NOTICE);
@ -522,6 +537,8 @@ class Net_SFTP extends Net_SSH2 {
$handle = substr($response, 4); $handle = substr($response, 4);
break; break;
case NET_SFTP_STATUS: case NET_SFTP_STATUS:
extract(unpack('Nstatus/Nlength', $this->_string_shift($response, 8)));
$this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
return false; return false;
default: default:
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS', E_USER_NOTICE); user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS', E_USER_NOTICE);
@ -532,12 +549,19 @@ class Net_SFTP extends Net_SSH2 {
return false; return false;
} }
$this->_get_sftp_packet(); $response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) { if ($this->packet_type != NET_SFTP_STATUS) {
user_error('Expected SSH_FXP_STATUS', E_USER_NOTICE); user_error('Expected SSH_FXP_STATUS', E_USER_NOTICE);
return false; return false;
} }
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
if ($status != NET_SFTP_STATUS_OK) {
extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
return false;
}
$this->pwd = $dir; $this->pwd = $dir;
return true; return true;
} }
@ -575,6 +599,8 @@ class Net_SFTP extends Net_SSH2 {
break; break;
case NET_SFTP_STATUS: case NET_SFTP_STATUS:
// presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
extract(unpack('Nstatus/Nlength', $this->_string_shift($response, 8)));
$this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
return false; return false;
default: default:
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS', E_USER_NOTICE); user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS', E_USER_NOTICE);
@ -608,7 +634,7 @@ class Net_SFTP extends Net_SSH2 {
extract(unpack('Nstatus', $this->_string_shift($response, 4))); extract(unpack('Nstatus', $this->_string_shift($response, 4)));
if ($status != NET_SFTP_STATUS_EOF) { if ($status != NET_SFTP_STATUS_EOF) {
extract(unpack('Nlength', $this->_string_shift($response, 4))); extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->debug_info.= "\r\n\r\nSSH_FXP_STATUS:\r\n" . $this->_string_shift($response, $length); $this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
return false; return false;
} }
break 2; break 2;
@ -624,12 +650,19 @@ class Net_SFTP extends Net_SSH2 {
// "The client MUST release all resources associated with the handle regardless of the status." // "The client MUST release all resources associated with the handle regardless of the status."
// -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3 // -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3
$this->_get_sftp_packet(); $response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) { if ($this->packet_type != NET_SFTP_STATUS) {
user_error('Expected SSH_FXP_STATUS', E_USER_NOTICE); user_error('Expected SSH_FXP_STATUS', E_USER_NOTICE);
return false; return false;
} }
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
if ($status != NET_SFTP_STATUS_OK) {
extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
return false;
}
return $contents; return $contents;
} }
@ -668,12 +701,18 @@ class Net_SFTP extends Net_SSH2 {
-- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.6 -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.6
*/ */
$this->_get_sftp_packet(); $response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) { if ($this->packet_type != NET_SFTP_STATUS) {
user_error('Expected SSH_FXP_STATUS', E_USER_NOTICE); user_error('Expected SSH_FXP_STATUS', E_USER_NOTICE);
return false; return false;
} }
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
if ($status != NET_SFTP_STATUS_EOF) {
extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
}
// rather than return what the permissions *should* be, we'll return what they actually are. this will also // rather than return what the permissions *should* be, we'll return what they actually are. this will also
// tell us if the file actually exists. // tell us if the file actually exists.
// incidentally ,SFTPv4+ adds an additional 32-bit integer field - flags - to the following: // incidentally ,SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
@ -688,6 +727,8 @@ class Net_SFTP extends Net_SSH2 {
$attrs = $this->_parseAttributes($response); $attrs = $this->_parseAttributes($response);
return $attrs['permissions']; return $attrs['permissions'];
case NET_SFTP_STATUS: case NET_SFTP_STATUS:
extract(unpack('Nstatus/Nlength', $this->_string_shift($response, 8)));
$this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
return false; return false;
} }
@ -728,7 +769,7 @@ class Net_SFTP extends Net_SSH2 {
extract(unpack('Nstatus', $this->_string_shift($response, 4))); extract(unpack('Nstatus', $this->_string_shift($response, 4)));
if ($status != NET_SFTP_STATUS_OK) { if ($status != NET_SFTP_STATUS_OK) {
extract(unpack('Nlength', $this->_string_shift($response, 4))); extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->debug_info.= "\r\n\r\nSSH_FXP_STATUS:\r\n" . $this->_string_shift($response, $length); $this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
return false; return false;
} }
@ -766,6 +807,8 @@ class Net_SFTP extends Net_SSH2 {
extract(unpack('Nstatus', $this->_string_shift($response, 4))); extract(unpack('Nstatus', $this->_string_shift($response, 4)));
if ($status != NET_SFTP_STATUS_OK) { if ($status != NET_SFTP_STATUS_OK) {
// presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED? // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED?
extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
return false; return false;
} }
@ -815,9 +858,8 @@ class Net_SFTP extends Net_SSH2 {
$handle = substr($response, 4); $handle = substr($response, 4);
break; break;
case NET_SFTP_STATUS: case NET_SFTP_STATUS:
$this->_string_shift($response, 4); extract(unpack('Nstatus/Nlength', $this->_string_shift($response, 8)));
extract(unpack('Nlength', $this->_string_shift($response, 4))); $this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
$this->debug_info.= "\r\n\r\nSSH_FXP_STATUS:\r\n" . $this->_string_shift($response, $length);
return false; return false;
default: default:
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS', E_USER_NOTICE); user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS', E_USER_NOTICE);
@ -857,12 +899,18 @@ class Net_SFTP extends Net_SSH2 {
$i++; $i++;
} }
while ($i-- > 0){ while ($i--) {
$this->_get_sftp_packet(); $response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) { if ($this->packet_type != NET_SFTP_STATUS) {
user_error('Expected SSH_FXP_STATUS', E_USER_NOTICE); user_error('Expected SSH_FXP_STATUS', E_USER_NOTICE);
return false; return false;
} }
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
if ($status != NET_SFTP_STATUS_OK) {
extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
}
} }
if ($mode == NET_SFTP_LOCAL_FILE) { if ($mode == NET_SFTP_LOCAL_FILE) {
@ -873,12 +921,19 @@ class Net_SFTP extends Net_SSH2 {
return false; return false;
} }
$this->_get_sftp_packet(); $response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) { if ($this->packet_type != NET_SFTP_STATUS) {
user_error('Expected SSH_FXP_STATUS', E_USER_NOTICE); user_error('Expected SSH_FXP_STATUS', E_USER_NOTICE);
return false; return false;
} }
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
if ($status != NET_SFTP_STATUS_OK) {
extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
return false;
}
return true; return true;
} }
@ -916,6 +971,8 @@ class Net_SFTP extends Net_SSH2 {
$handle = substr($response, 4); $handle = substr($response, 4);
break; break;
case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
extract(unpack('Nstatus/Nlength', $this->_string_shift($response, 8)));
$this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
return false; return false;
default: default:
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS', E_USER_NOTICE); user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS', E_USER_NOTICE);
@ -933,13 +990,14 @@ class Net_SFTP extends Net_SSH2 {
$attrs = $this->_parseAttributes($response); $attrs = $this->_parseAttributes($response);
break; break;
case NET_SFTP_STATUS: case NET_SFTP_STATUS:
extract(unpack('Nstatus/Nlength', $this->_string_shift($response, 8)));
$this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
return false; return false;
default: default:
user_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS', E_USER_NOTICE); user_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS', E_USER_NOTICE);
return false; return false;
} }
if ($local_file !== false) { if ($local_file !== false) {
$fp = fopen($local_file, 'w'); $fp = fopen($local_file, 'w');
if (!$fp) { if (!$fp) {
@ -968,10 +1026,9 @@ class Net_SFTP extends Net_SSH2 {
} }
break; break;
case NET_SFTP_STATUS: case NET_SFTP_STATUS:
$this->_string_shift($response, 4); extract(unpack('Nstatus/Nlength', $this->_string_shift($response, 8)));
extract(unpack('Nlength', $this->_string_shift($response, 4))); $this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
$this->debug_info.= "\r\n\r\nSSH_FXP_STATUS:\r\n" . $this->_string_shift($response, $length); break 2;
return false;
default: default:
user_error('Expected SSH_FXP_DATA or SSH_FXP_STATUS', E_USER_NOTICE); user_error('Expected SSH_FXP_DATA or SSH_FXP_STATUS', E_USER_NOTICE);
return false; return false;
@ -982,12 +1039,19 @@ class Net_SFTP extends Net_SSH2 {
return false; return false;
} }
$this->_get_sftp_packet(); $response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) { if ($this->packet_type != NET_SFTP_STATUS) {
user_error('Expected SSH_FXP_STATUS', E_USER_NOTICE); user_error('Expected SSH_FXP_STATUS', E_USER_NOTICE);
return false; return false;
} }
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
if ($status != NET_SFTP_STATUS_OK) {
extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
return false;
}
if (isset($content)) { if (isset($content)) {
return $content; return $content;
} }
@ -1025,10 +1089,15 @@ class Net_SFTP extends Net_SSH2 {
return false; return false;
} }
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
// if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
return $status == NET_SFTP_STATUS_OK; extract(unpack('Nstatus', $this->_string_shift($response, 4)));
if ($status != NET_SFTP_STATUS_OK) {
extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
return false;
}
return true;
} }
/** /**
@ -1063,10 +1132,15 @@ class Net_SFTP extends Net_SSH2 {
return false; return false;
} }
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
// if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
return $status == NET_SFTP_STATUS_OK; extract(unpack('Nstatus', $this->_string_shift($response, 4)));
if ($status != NET_SFTP_STATUS_OK) {
extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->sftp_errors[] = $this->status_codes[$status] . ': ' . $this->_string_shift($response, $length);
return false;
}
return true;
} }
/** /**
@ -1198,12 +1272,6 @@ class Net_SFTP extends Net_SSH2 {
$this->packet_type = ord($this->_string_shift($this->packet_buffer)); $this->packet_type = ord($this->_string_shift($this->packet_buffer));
if (defined('NET_SFTP_LOGGING')) {
$this->packet_type_log[] = '<- ' . $this->packet_types[$this->packet_type] .
' (' . round($stop - $start, 4) . 's)';
$this->packet_log[] = $packet;
}
if ($this->request_id !== false) { if ($this->request_id !== false) {
$this->_string_shift($this->packet_buffer, 4); // remove the request id $this->_string_shift($this->packet_buffer, 4); // remove the request id
$length-= 5; // account for the request id and the packet type $length-= 5; // account for the request id and the packet type
@ -1211,7 +1279,15 @@ class Net_SFTP extends Net_SSH2 {
$length-= 1; // account for the packet type $length-= 1; // account for the packet type
} }
return $this->_string_shift($this->packet_buffer, $length); $packet = $this->_string_shift($this->packet_buffer, $length);
if (defined('NET_SFTP_LOGGING')) {
$this->packet_type_log[] = '<- ' . $this->packet_types[$this->packet_type] .
' (' . round($stop - $start, 4) . 's)';
$this->packet_log[] = $packet;
}
return $packet;
} }
/** /**
@ -1239,6 +1315,28 @@ class Net_SFTP extends Net_SSH2 {
return $return; return $return;
} }
/**
* Returns all errors
*
* @return String
* @access public
*/
function getSFTPErrors()
{
return $this->sftp_errors;
}
/**
* Returns the last error
*
* @return String
* @access public
*/
function getLastSFTPError()
{
return $this->sftp_errors[count($this->sftp_errors) - 1];
}
/** /**
* Get supported SFTP versions * Get supported SFTP versions
* *

View File

@ -60,7 +60,7 @@
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton * @copyright MMVII Jim Wigginton
* @license http://www.gnu.org/licenses/lgpl.txt * @license http://www.gnu.org/licenses/lgpl.txt
* @version $Id: SSH2.php,v 1.36 2010-02-11 07:02:51 terrafrost Exp $ * @version $Id: SSH2.php,v 1.37 2010-02-12 23:02:13 terrafrost Exp $
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -176,13 +176,14 @@ class Net_SSH2 {
var $bitmap = 0; var $bitmap = 0;
/** /**
* Debug Info * Error information
* *
* @see Net_SSH2::getDebugInfo() * @see Net_SSH2::getErrors()
* @see Net_SSH2::getLastError()
* @var String * @var String
* @access private * @access private
*/ */
var $debug_info = ''; var $errors = array();
/** /**
* Server Identifier * Server Identifier
@ -637,7 +638,7 @@ class Net_SSH2 {
$temp = ''; $temp = '';
while (!feof($this->fsock) && !preg_match('#^SSH-(\d\.\d+)#', $temp, $matches)) { while (!feof($this->fsock) && !preg_match('#^SSH-(\d\.\d+)#', $temp, $matches)) {
if (substr($temp, -2) == "\r\n") { if (substr($temp, -2) == "\r\n") {
$this->debug_info.= $temp; $this->errors[] = $temp;
$temp = ''; $temp = '';
} }
$temp.= fgets($this->fsock, 255); $temp.= fgets($this->fsock, 255);
@ -665,7 +666,7 @@ class Net_SSH2 {
} }
$this->server_identifier = trim($temp); $this->server_identifier = trim($temp);
$this->debug_info = utf8_decode($this->debug_info); $this->errors[] = utf8_decode($this->debug_info);
if ($matches[1] != '1.99' && $matches[1] != '2.0') { if ($matches[1] != '1.99' && $matches[1] != '2.0') {
user_error("Cannot connect to SSH $matches[1] servers", E_USER_NOTICE); user_error("Cannot connect to SSH $matches[1] servers", E_USER_NOTICE);
@ -1400,7 +1401,7 @@ class Net_SSH2 {
$this->message_number_log[count($this->message_number_log) - 1] = 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ'; $this->message_number_log[count($this->message_number_log) - 1] = 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ';
} }
extract(unpack('Nlength', $this->_string_shift($response, 4))); extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->debug_info.= "\r\n\r\nSSH_MSG_USERAUTH_PASSWD_CHANGEREQ:\r\n" . utf8_decode($this->_string_shift($response, $length)); $this->errors[] = 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ: ' . utf8_decode($this->_string_shift($response, $length));
return $this->_disconnect(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER); return $this->_disconnect(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER);
case NET_SSH2_MSG_USERAUTH_FAILURE: case NET_SSH2_MSG_USERAUTH_FAILURE:
// either the login is bad or the server employees multi-factor authentication // either the login is bad or the server employees multi-factor authentication
@ -1462,7 +1463,7 @@ class Net_SSH2 {
switch ($type) { switch ($type) {
case NET_SSH2_MSG_USERAUTH_FAILURE: case NET_SSH2_MSG_USERAUTH_FAILURE:
extract(unpack('Nlength', $this->_string_shift($response, 4))); extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->debug_info.= "\r\n\r\nSSH_MSG_USERAUTH_FAILURE:\r\n" . $this->_string_shift($response, $length); $this->errors[] = 'SSH_MSG_USERAUTH_FAILURE: ' . $this->_string_shift($response, $length);
return $this->_disconnect(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER); return $this->_disconnect(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER);
case NET_SSH2_MSG_USERAUTH_PK_OK: case NET_SSH2_MSG_USERAUTH_PK_OK:
// we'll just take it on faith that the public key blob and the public key algorithm name are as // we'll just take it on faith that the public key blob and the public key algorithm name are as
@ -1675,7 +1676,7 @@ class Net_SSH2 {
case NET_SSH2_MSG_DISCONNECT: case NET_SSH2_MSG_DISCONNECT:
$this->_string_shift($payload, 1); $this->_string_shift($payload, 1);
extract(unpack('Nreason_code/Nlength', $this->_string_shift($payload, 8))); extract(unpack('Nreason_code/Nlength', $this->_string_shift($payload, 8)));
$this->debug_info.= "\r\n\r\nSSH_MSG_DISCONNECT:\r\n" . $this->disconnect_reasons[$reason_code] . "\r\n" . utf8_decode($this->_string_shift($payload, $length)); $this->errors[] = 'SSH_MSG_DISCONNECT: ' . $this->disconnect_reasons[$reason_code] . "\r\n" . utf8_decode($this->_string_shift($payload, $length));
$this->bitmask = 0; $this->bitmask = 0;
return false; return false;
case NET_SSH2_MSG_IGNORE: case NET_SSH2_MSG_IGNORE:
@ -1684,7 +1685,7 @@ class Net_SSH2 {
case NET_SSH2_MSG_DEBUG: case NET_SSH2_MSG_DEBUG:
$this->_string_shift($payload, 2); $this->_string_shift($payload, 2);
extract(unpack('Nlength', $this->_string_shift($payload, 4))); extract(unpack('Nlength', $this->_string_shift($payload, 4)));
$this->debug_info.= "\r\n\r\nSSH_MSG_DEBUG:\r\n" . utf8_decode($this->_string_shift($payload, $length)); $this->errors[] = 'SSH_MSG_DEBUG: ' . utf8_decode($this->_string_shift($payload, $length));
$payload = $this->_get_binary_packet(); $payload = $this->_get_binary_packet();
break; break;
case NET_SSH2_MSG_UNIMPLEMENTED: case NET_SSH2_MSG_UNIMPLEMENTED:
@ -1703,7 +1704,7 @@ class Net_SSH2 {
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_CONSTRUCTOR) && !($this->bitmap & NET_SSH2_MASK_LOGIN) && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) {
$this->_string_shift($payload, 1); $this->_string_shift($payload, 1);
extract(unpack('Nlength', $this->_string_shift($payload, 4))); extract(unpack('Nlength', $this->_string_shift($payload, 4)));
$this->debug_info.= "\r\n\r\nSSH_MSG_USERAUTH_BANNER:\r\n" . utf8_decode($this->_string_shift($payload, $length)); $this->errors[] = 'SSH_MSG_USERAUTH_BANNER: ' . utf8_decode($this->_string_shift($payload, $length));
$payload = $this->_get_binary_packet(); $payload = $this->_get_binary_packet();
} }
@ -1713,7 +1714,7 @@ class Net_SSH2 {
case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4 case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4
$this->_string_shift($payload, 1); $this->_string_shift($payload, 1);
extract(unpack('Nlength', $this->_string_shift($payload))); extract(unpack('Nlength', $this->_string_shift($payload)));
$this->debug_info.= "\r\n\r\nSSH_MSG_GLOBAL_REQUEST:\r\n" . utf8_decode($this->_string_shift($payload, $length)); $this->errors[] = 'SSH_MSG_GLOBAL_REQUEST: ' . utf8_decode($this->_string_shift($payload, $length));
if (!$this->_send_binary_packet(pack('C', NET_SSH2_MSG_REQUEST_FAILURE))) { if (!$this->_send_binary_packet(pack('C', NET_SSH2_MSG_REQUEST_FAILURE))) {
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
@ -1724,7 +1725,7 @@ class Net_SSH2 {
case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1 case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1
$this->_string_shift($payload, 1); $this->_string_shift($payload, 1);
extract(unpack('N', $this->_string_shift($payload, 4))); extract(unpack('N', $this->_string_shift($payload, 4)));
$this->debug_info.= "\r\n\r\nSSH_MSG_CHANNEL_OPEN:\r\n" . utf8_decode($this->_string_shift($payload, $length)); $this->errors[] = 'SSH_MSG_CHANNEL_OPEN: ' . utf8_decode($this->_string_shift($payload, $length));
$this->_string_shift($payload, 4); // skip over client channel $this->_string_shift($payload, 4); // skip over client channel
extract(unpack('Nserver_channel', $this->_string_shift($payload, 4))); extract(unpack('Nserver_channel', $this->_string_shift($payload, 4)));
@ -1825,7 +1826,7 @@ class Net_SSH2 {
$data = $this->_string_shift($response, $length); $data = $this->_string_shift($response, $length);
switch ($data_type_code) { switch ($data_type_code) {
case NET_SSH2_EXTENDED_DATA_STDERR: case NET_SSH2_EXTENDED_DATA_STDERR:
$this->debug_info.= "\r\n\r\nSSH_MSG_CHANNEL_EXTENDED_DATA (SSH_EXTENDED_DATA_STDERR):\r\n" . $data; $this->errors[] = 'SSH_MSG_CHANNEL_EXTENDED_DATA (SSH_EXTENDED_DATA_STDERR): ' . $data;
} }
break; break;
case NET_SSH2_MSG_CHANNEL_REQUEST: case NET_SSH2_MSG_CHANNEL_REQUEST:
@ -1835,10 +1836,12 @@ class Net_SSH2 {
case 'exit-signal': case 'exit-signal':
$this->_string_shift($response, 1); $this->_string_shift($response, 1);
extract(unpack('Nlength', $this->_string_shift($response, 4))); extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->debug_info.= "\r\n\r\nSSH_MSG_CHANNEL_REQUEST (exit-signal):\r\nSIG" . $this->_string_shift($response, $length); $this->errors[] = 'SSH_MSG_CHANNEL_REQUEST (exit-signal): ' . $this->_string_shift($response, $length);
$this->_string_shift($response, 1); $this->_string_shift($response, 1);
extract(unpack('Nlength', $this->_string_shift($response, 4))); extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->debug_info.= "\r\n" . $this->_string_shift($response, $length); if ($length) {
$this->errors[count($this->errors)].= "\r\n" . $this->_string_shift($response, $length);
}
//case 'exit-status': //case 'exit-status':
default: default:
// "Some systems may not implement signals, in which case they SHOULD ignore this message." // "Some systems may not implement signals, in which case they SHOULD ignore this message."
@ -2072,16 +2075,25 @@ class Net_SSH2 {
} }
/** /**
* Returns Debug Information * Returns all errors
*
* If any debug information is sent by the server, this function can be used to access it.
* *
* @return String * @return String
* @access public * @access public
*/ */
function getDebugInfo() function getErrors()
{ {
return $this->debug_info; return $this->errors;
}
/**
* Returns the last error
*
* @return String
* @access public
*/
function getLastError()
{
return $this->errors[count($this->errors) - 1];
} }
/** /**