- add logging to Net_SSH1 and fixed a bug in Crypt_DES (thanks, Suby!)

git-svn-id: http://phpseclib.svn.sourceforge.net/svnroot/phpseclib/trunk@113 21d32557-59b3-4da0-833f-c5933fad653e
This commit is contained in:
Jim Wigginton 2010-08-08 05:06:38 +00:00
parent 3ef15724be
commit f088d89712
3 changed files with 213 additions and 35 deletions

View File

@ -53,7 +53,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: DES.php,v 1.12 2010-02-09 06:10:26 terrafrost Exp $ * @version $Id: DES.php,v 1.13 2010-08-08 05:06:38 terrafrost Exp $
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -210,14 +210,24 @@ class Crypt_DES {
var $demcrypt; var $demcrypt;
/** /**
* Does the (en|de)mcrypt resource need to be (re)initialized? * Does the enmcrypt resource need to be (re)initialized?
* *
* @see setKey() * @see setKey()
* @see setIV() * @see setIV()
* @var Boolean * @var Boolean
* @access private * @access private
*/ */
var $changed = true; var $enchanged = true;
/**
* Does the demcrypt resource need to be (re)initialized?
*
* @see setKey()
* @see setIV()
* @var Boolean
* @access private
*/
var $dechanged = true;
/** /**
* Default Constructor. * Default Constructor.
@ -370,12 +380,12 @@ class Crypt_DES {
} }
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) { if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
if ($this->changed) { if ($this->enchanged) {
if (!isset($this->enmcrypt)) { if (!isset($this->enmcrypt)) {
$this->enmcrypt = mcrypt_module_open(MCRYPT_DES, '', $this->mode, ''); $this->enmcrypt = mcrypt_module_open(MCRYPT_DES, '', $this->mode, '');
} }
mcrypt_generic_init($this->enmcrypt, $this->keys, $this->encryptIV); mcrypt_generic_init($this->enmcrypt, $this->keys, $this->encryptIV);
$this->changed = false; $this->enchanged = false;
} }
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext); $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
@ -443,12 +453,12 @@ class Crypt_DES {
} }
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) { if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
if ($this->changed) { if ($this->dechanged) {
if (!isset($this->demcrypt)) { if (!isset($this->demcrypt)) {
$this->demcrypt = mcrypt_module_open(MCRYPT_DES, '', $this->mode, ''); $this->demcrypt = mcrypt_module_open(MCRYPT_DES, '', $this->mode, '');
} }
mcrypt_generic_init($this->demcrypt, $this->keys, $this->decryptIV); mcrypt_generic_init($this->demcrypt, $this->keys, $this->decryptIV);
$this->changed = false; $this->dechanged = false;
} }
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext); $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);

View File

@ -47,14 +47,14 @@
* @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: TripleDES.php,v 1.13 2010-02-26 03:40:25 terrafrost Exp $ * @version $Id: TripleDES.php,v 1.14 2010-08-08 05:06:38 terrafrost Exp $
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
/** /**
* Include Crypt_DES * Include Crypt_DES
*/ */
require_once 'DES.php'; require_once('DES.php');
/** /**
* Encrypt / decrypt using inner chaining * Encrypt / decrypt using inner chaining

View File

@ -65,7 +65,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: SSH1.php,v 1.15 2010-03-22 22:01:38 terrafrost Exp $ * @version $Id: SSH1.php,v 1.16 2010-08-08 05:06:38 terrafrost Exp $
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -101,28 +101,6 @@ require_once('Crypt/RC4.php');
*/ */
require_once('Crypt/Random.php'); require_once('Crypt/Random.php');
/**#@+
* Protocol Flags
*
* @access private
*/
define('NET_SSH1_MSG_DISCONNECT', 1);
define('NET_SSH1_SMSG_PUBLIC_KEY', 2);
define('NET_SSH1_CMSG_SESSION_KEY', 3);
define('NET_SSH1_CMSG_USER', 4);
define('NET_SSH1_CMSG_AUTH_PASSWORD', 9);
define('NET_SSH1_CMSG_REQUEST_PTY', 10);
define('NET_SSH1_CMSG_EXEC_SHELL', 12);
define('NET_SSH1_CMSG_EXEC_CMD', 13);
define('NET_SSH1_SMSG_SUCCESS', 14);
define('NET_SSH1_SMSG_FAILURE', 15);
define('NET_SSH1_CMSG_STDIN_DATA', 16);
define('NET_SSH1_SMSG_STDOUT_DATA', 17);
define('NET_SSH1_SMSG_STDERR_DATA', 18);
define('NET_SSH1_SMSG_EXITSTATUS', 20);
define('NET_SSH1_CMSG_EXIT_CONFIRMATION', 33);
/**#@-*/
/**#@+ /**#@+
* Encryption Methods * Encryption Methods
* *
@ -245,6 +223,20 @@ define('NET_SSH1_MASK_LOGIN', 0x00000002);
define('NET_SSH1_MASK_SHELL', 0x00000004); define('NET_SSH1_MASK_SHELL', 0x00000004);
/**#@-*/ /**#@-*/
/**#@+
* @access public
* @see Net_SSH1::getLog()
*/
/**
* Returns the message numbers
*/
define('NET_SSH1_LOG_SIMPLE', 1);
/**
* Returns the message content
*/
define('NET_SSH1_LOG_COMPLEX', 2);
/**#@-*/
/** /**
* Pure-PHP implementation of SSHv1. * Pure-PHP implementation of SSHv1.
* *
@ -281,7 +273,7 @@ class Net_SSH1 {
/** /**
* Execution Bitmap * Execution Bitmap
* *
* The bits that are set reprsent functions that have been called already. This is used to determine * The bits that are set represent functions that have been called already. This is used to determine
* if a requisite function has been successfully executed. If not, an error should be thrown. * if a requisite function has been successfully executed. If not, an error should be thrown.
* *
* @var Integer * @var Integer
@ -377,6 +369,33 @@ class Net_SSH1 {
*/ */
var $server_identification = ''; var $server_identification = '';
/**
* Protocol Flags
*
* @see Net_SSH1::Net_SSH1()
* @var Array
* @access private
*/
var $protocol_flags = array();
/**
* Protocol Flag Log
*
* @see Net_SSH1::getLog()
* @var Array
* @access private
*/
var $protocol_flag_log = array();
/**
* Message Log
*
* @see Net_SSH1::getLog()
* @var Array
* @access private
*/
var $message_log = array();
/** /**
* Default Constructor. * Default Constructor.
* *
@ -391,6 +410,26 @@ class Net_SSH1 {
*/ */
function Net_SSH1($host, $port = 22, $timeout = 10, $cipher = NET_SSH1_CIPHER_3DES) function Net_SSH1($host, $port = 22, $timeout = 10, $cipher = NET_SSH1_CIPHER_3DES)
{ {
$this->protocol_flags = array(
1 => 'NET_SSH1_MSG_DISCONNECT',
2 => 'NET_SSH1_SMSG_PUBLIC_KEY',
3 => 'NET_SSH1_CMSG_SESSION_KEY',
4 => 'NET_SSH1_CMSG_USER',
9 => 'NET_SSH1_CMSG_AUTH_PASSWORD',
10 => 'NET_SSH1_CMSG_REQUEST_PTY',
12 => 'NET_SSH1_CMSG_EXEC_SHELL',
13 => 'NET_SSH1_CMSG_EXEC_CMD',
14 => 'NET_SSH1_SMSG_SUCCESS',
15 => 'NET_SSH1_SMSG_FAILURE',
16 => 'NET_SSH1_CMSG_STDIN_DATA',
17 => 'NET_SSH1_SMSG_STDOUT_DATA',
18 => 'NET_SSH1_SMSG_STDERR_DATA',
20 => 'NET_SSH1_SMSG_EXITSTATUS',
33 => 'NET_SSH1_CMSG_EXIT_CONFIRMATION'
);
$this->_define_array($this->protocol_flags);
$this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout); $this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout);
if (!$this->fsock) { if (!$this->fsock) {
user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"), E_USER_NOTICE); user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"), E_USER_NOTICE);
@ -398,6 +437,17 @@ class Net_SSH1 {
} }
$this->server_identification = $init_line = fgets($this->fsock, 255); $this->server_identification = $init_line = fgets($this->fsock, 255);
if (defined('NET_SSH1_LOGGING')) {
$this->protocol_flags_log[] = '<-';
$this->protocol_flags_log[] = '->';
if (NET_SSH1_LOGGING == NET_SSH1_LOG_COMPLEX) {
$this->message_log[] = $this->server_identification;
$this->message_log[] = $this->identifier . "\r\n";
}
}
if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) { if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) {
user_error('Can only connect to SSH servers', E_USER_NOTICE); user_error('Can only connect to SSH servers', E_USER_NOTICE);
return; return;
@ -825,7 +875,9 @@ class Net_SSH1 {
$padding_length = 8 - ($temp['length'] & 7); $padding_length = 8 - ($temp['length'] & 7);
$length = $temp['length'] + $padding_length; $length = $temp['length'] + $padding_length;
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
$raw = fread($this->fsock, $length); $raw = fread($this->fsock, $length);
$stop = strtok(microtime(), ' ') + strtok('');
if ($this->crypto !== false) { if ($this->crypto !== false) {
$raw = $this->crypto->decrypt($raw); $raw = $this->crypto->decrypt($raw);
@ -842,8 +894,19 @@ class Net_SSH1 {
// return false; // return false;
//} //}
$type = ord($type);
if (defined('NET_SSH1_LOGGING')) {
$temp = isset($this->protocol_flags[$type]) ? $this->protocol_flags[$type] : 'UNKNOWN';
$this->protocol_flags_log[] = '<- ' . $temp .
' (' . round($stop - $start, 4) . 's)';
if (NET_SSH1_LOGGING == NET_SSH1_LOG_COMPLEX) {
$this->message_log[] = $data;
}
}
return array( return array(
NET_SSH1_RESPONSE_TYPE => ord($type), NET_SSH1_RESPONSE_TYPE => $type,
NET_SSH1_RESPONSE_DATA => $data NET_SSH1_RESPONSE_DATA => $data
); );
} }
@ -881,7 +944,20 @@ class Net_SSH1 {
$packet = pack('Na*', $length, $data); $packet = pack('Na*', $length, $data);
return strlen($packet) == fputs($this->fsock, $packet); $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
$result = strlen($packet) == fputs($this->fsock, $packet);
$stop = strtok(microtime(), ' ') + strtok('');
if (defined('NET_SSH1_LOGGING')) {
$temp = isset($this->protocol_flags[ord($data[0])]) ? $this->protocol_flags[ord($data[0])] : 'UNKNOWN';
$this->protocol_flags_log[] = '-> ' . $temp .
' (' . round($stop - $start, 4) . 's)';
if (NET_SSH1_LOGGING == NET_SSH1_LOG_COMPLEX) {
$this->message_log[] = substr($data, 1);
}
}
return $result;
} }
/** /**
@ -1054,6 +1130,98 @@ class Net_SSH1 {
return $m->toBytes(); return $m->toBytes();
} }
/**
* Define Array
*
* Takes any number of arrays whose indices are integers and whose values are strings and defines a bunch of
* named constants from it, using the value as the name of the constant and the index as the value of the constant.
* If any of the constants that would be defined already exists, none of the constants will be defined.
*
* @param Array $array
* @access private
*/
function _define_array()
{
$args = func_get_args();
foreach ($args as $arg) {
foreach ($arg as $key=>$value) {
if (!defined($value)) {
define($value, $key);
} else {
break 2;
}
}
}
}
/**
* Returns a log of the packets that have been sent and received.
*
* Returns a string if NET_SSH2_LOGGING == NET_SSH2_LOG_COMPLEX, an array if NET_SSH2_LOGGING == NET_SSH2_LOG_SIMPLE and false if !defined('NET_SSH2_LOGGING')
*
* @access public
* @return String or Array
*/
function getLog()
{
if (!defined('NET_SSH1_LOGGING')) {
return false;
}
switch (NET_SSH1_LOGGING) {
case NET_SSH1_LOG_SIMPLE:
return $this->message_number_log;
break;
case NET_SSH1_LOG_COMPLEX:
return $this->_format_log($this->message_log, $this->protocol_flags_log);
break;
default:
return false;
}
}
/**
* Formats a log for printing
*
* @param Array $message_log
* @param Array $message_number_log
* @access private
* @return String
*/
function _format_log($message_log, $message_number_log)
{
static $boundary = ':', $long_width = 65, $short_width = 16;
$output = '';
for ($i = 0; $i < count($message_log); $i++) {
$output.= $message_number_log[$i] . "\r\n";
$current_log = $message_log[$i];
$j = 0;
do {
if (!empty($current_log)) {
$output.= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0 ';
}
$fragment = $this->_string_shift($current_log, $short_width);
$hex = substr(
preg_replace(
'#(.)#es',
'"' . $boundary . '" . str_pad(dechex(ord(substr("\\1", -1))), 2, "0", STR_PAD_LEFT)',
$fragment),
strlen($boundary)
);
// replace non ASCII printable characters with dots
// http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters
// also replace < with a . since < messes up the output on web browsers
$raw = preg_replace('#[^\x20-\x7E]|<#', '.', $fragment);
$output.= str_pad($hex, $long_width - $short_width, ' ') . $raw . "\r\n";
$j++;
} while (!empty($current_log));
$output.= "\r\n";
}
return $output;
}
/** /**
* Return the server key public exponent * Return the server key public exponent
* *