Merge pull request #12 from phpseclib/master

Sync
This commit is contained in:
Hans-Jürgen Petrich 2013-05-04 19:29:05 -07:00
commit 0a040e1c5c
8 changed files with 1441 additions and 697 deletions

View File

@ -47,5 +47,10 @@
"files": [ "files": [
"phpseclib/Crypt/Random.php" "phpseclib/Crypt/Random.php"
] ]
},
"extra": {
"branch-alias": {
"dev-master": "0.3-dev"
}
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -42,6 +42,13 @@
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
/**
* "Is Windows" test
*
* @access private
*/
define('CRYPT_RANDOM_IS_WINDOWS', strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
/** /**
* Generate a random string. * Generate a random string.
* *
@ -55,8 +62,7 @@
*/ */
function crypt_random_string($length) function crypt_random_string($length)
{ {
// PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster if (CRYPT_RANDOM_IS_WINDOWS) {
if ((PHP_OS & "\xDF\xDF\xDF") === 'WIN') {
// method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call. // method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call.
// ie. class_alias is a function that was introduced in PHP 5.3 // ie. class_alias is a function that was introduced in PHP 5.3
if (function_exists('mcrypt_create_iv') && function_exists('class_alias')) { if (function_exists('mcrypt_create_iv') && function_exists('class_alias')) {

View File

@ -83,70 +83,7 @@ define('CRYPT_DES_MODE_CBC3', CRYPT_DES_MODE_CBC);
* @access public * @access public
* @package Crypt_TerraDES * @package Crypt_TerraDES
*/ */
class Crypt_TripleDES { class Crypt_TripleDES extends Crypt_DES {
/**
* The Three Keys
*
* @see Crypt_TripleDES::setKey()
* @var String
* @access private
*/
var $key = "\0\0\0\0\0\0\0\0";
/**
* The Encryption Mode
*
* @see Crypt_TripleDES::Crypt_TripleDES()
* @var Integer
* @access private
*/
var $mode = CRYPT_DES_MODE_CBC;
/**
* Continuous Buffer status
*
* @see Crypt_TripleDES::enableContinuousBuffer()
* @var Boolean
* @access private
*/
var $continuousBuffer = false;
/**
* Padding status
*
* @see Crypt_TripleDES::enablePadding()
* @var Boolean
* @access private
*/
var $padding = true;
/**
* The Initialization Vector
*
* @see Crypt_TripleDES::setIV()
* @var String
* @access private
*/
var $iv = "\0\0\0\0\0\0\0\0";
/**
* A "sliding" Initialization Vector
*
* @see Crypt_TripleDES::enableContinuousBuffer()
* @var String
* @access private
*/
var $encryptIV = "\0\0\0\0\0\0\0\0";
/**
* A "sliding" Initialization Vector
*
* @see Crypt_TripleDES::enableContinuousBuffer()
* @var String
* @access private
*/
var $decryptIV = "\0\0\0\0\0\0\0\0";
/** /**
* The Crypt_DES objects * The Crypt_DES objects
* *
@ -155,87 +92,6 @@ class Crypt_TripleDES {
*/ */
var $des; var $des;
/**
* mcrypt resource for encryption
*
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
*
* @see Crypt_TripleDES::encrypt()
* @var String
* @access private
*/
var $enmcrypt;
/**
* mcrypt resource for decryption
*
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
*
* @see Crypt_TripleDES::decrypt()
* @var String
* @access private
*/
var $demcrypt;
/**
* Does the enmcrypt resource need to be (re)initialized?
*
* @see Crypt_TripleDES::setKey()
* @see Crypt_TripleDES::setIV()
* @var Boolean
* @access private
*/
var $enchanged = true;
/**
* Does the demcrypt resource need to be (re)initialized?
*
* @see Crypt_TripleDES::setKey()
* @see Crypt_TripleDES::setIV()
* @var Boolean
* @access private
*/
var $dechanged = true;
/**
* Is the mode one that is paddable?
*
* @see Crypt_TripleDES::Crypt_TripleDES()
* @var Boolean
* @access private
*/
var $paddable = false;
/**
* Encryption buffer for CTR, OFB and CFB modes
*
* @see Crypt_TripleDES::encrypt()
* @var Array
* @access private
*/
var $enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
/**
* Decryption buffer for CTR, OFB and CFB modes
*
* @see Crypt_TripleDES::decrypt()
* @var Array
* @access private
*/
var $debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'demcrypt_init' => true);
/**
* mcrypt resource for CFB mode
*
* @see Crypt_TripleDES::encrypt()
* @see Crypt_TripleDES::decrypt()
* @var String
* @access private
*/
var $ecb;
/** /**
* Default Constructor. * Default Constructor.
* *
@ -328,6 +184,10 @@ class Crypt_TripleDES {
$this->paddable = true; $this->paddable = true;
$this->mode = CRYPT_DES_MODE_CBC; $this->mode = CRYPT_DES_MODE_CBC;
} }
if (function_exists('create_function') && is_callable('create_function')) {
$this->inline_crypt_setup(3);
$this->use_inline_crypt = true;
}
} }
} }
@ -362,6 +222,22 @@ class Crypt_TripleDES {
$this->des[0]->setKey(substr($key, 0, 8)); $this->des[0]->setKey(substr($key, 0, 8));
$this->des[1]->setKey(substr($key, 8, 8)); $this->des[1]->setKey(substr($key, 8, 8));
$this->des[2]->setKey(substr($key, 16, 8)); $this->des[2]->setKey(substr($key, 16, 8));
// Merge the three DES-1-dim-key-arrays for 3DES-inline-en/decrypting
if ($this->use_inline_crypt && $this->mode != CRYPT_DES_MODE_3CBC) {
$this->keys = array(
CRYPT_DES_ENCRYPT_1DIM => array_merge(
$this->des[0]->keys[CRYPT_DES_ENCRYPT_1DIM],
$this->des[1]->keys[CRYPT_DES_DECRYPT_1DIM],
$this->des[2]->keys[CRYPT_DES_ENCRYPT_1DIM]
),
CRYPT_DES_DECRYPT_1DIM => array_merge(
$this->des[2]->keys[CRYPT_DES_DECRYPT_1DIM],
$this->des[1]->keys[CRYPT_DES_ENCRYPT_1DIM],
$this->des[0]->keys[CRYPT_DES_DECRYPT_1DIM]
),
);
}
} }
$this->enchanged = $this->dechanged = true; $this->enchanged = $this->dechanged = true;
} }
@ -438,39 +314,6 @@ class Crypt_TripleDES {
$this->enchanged = $this->dechanged = true; $this->enchanged = $this->dechanged = true;
} }
/**
* Generate CTR XOR encryption key
*
* Encrypt the output of this and XOR it against the ciphertext / plaintext to get the
* plaintext / ciphertext in CTR mode.
*
* @see Crypt_TripleDES::decrypt()
* @see Crypt_TripleDES::encrypt()
* @access private
* @param String $iv
*/
function _generate_xor(&$iv)
{
$xor = $iv;
for ($j = 4; $j <= 8; $j+=4) {
$temp = substr($iv, -$j, 4);
switch ($temp) {
case "\xFF\xFF\xFF\xFF":
$iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4);
break;
case "\x7F\xFF\xFF\xFF":
$iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4);
break 2;
default:
extract(unpack('Ncount', $temp));
$iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);
break 2;
}
}
return $xor;
}
/** /**
* Encrypts a message. * Encrypts a message.
* *
@ -565,6 +408,11 @@ class Crypt_TripleDES {
return $this->des[0]->encrypt($plaintext); return $this->des[0]->encrypt($plaintext);
} }
if ($this->use_inline_crypt) {
$inline = $this->inline_crypt;
return $inline('encrypt', $this, $plaintext);
}
$des = $this->des; $des = $this->des;
$buffer = &$this->enbuffer; $buffer = &$this->enbuffer;
@ -612,7 +460,7 @@ class Crypt_TripleDES {
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT); $key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
$buffer['encrypted'].= $key; $buffer['encrypted'].= $key;
} }
$key = $this->_string_shift($buffer['encrypted'], 8); $key = $this->_string_shift($buffer['encrypted']);
$ciphertext.= $block ^ $key; $ciphertext.= $block ^ $key;
} }
} else { } else {
@ -676,7 +524,7 @@ class Crypt_TripleDES {
$xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT); $xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT);
$buffer['xor'].= $xor; $buffer['xor'].= $xor;
} }
$key = $this->_string_shift($buffer['xor'], 8); $key = $this->_string_shift($buffer['xor']);
$ciphertext.= $block ^ $key; $ciphertext.= $block ^ $key;
} }
} else { } else {
@ -780,6 +628,11 @@ class Crypt_TripleDES {
return $this->paddable ? $this->_unpad($plaintext) : $plaintext; return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
} }
if ($this->use_inline_crypt) {
$inline = $this->inline_crypt;
return $inline('decrypt', $this, $ciphertext);
}
$des = $this->des; $des = $this->des;
$buffer = &$this->debuffer; $buffer = &$this->debuffer;
@ -821,7 +674,7 @@ class Crypt_TripleDES {
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT); $key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
$buffer['ciphertext'].= $key; $buffer['ciphertext'].= $key;
} }
$key = $this->_string_shift($buffer['ciphertext'], 8); $key = $this->_string_shift($buffer['ciphertext']);
$plaintext.= $block ^ $key; $plaintext.= $block ^ $key;
} }
} else { } else {
@ -890,7 +743,7 @@ class Crypt_TripleDES {
$xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT); $xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT);
$buffer['xor'].= $xor; $buffer['xor'].= $xor;
} }
$key = $this->_string_shift($buffer['xor'], 8); $key = $this->_string_shift($buffer['xor']);
$plaintext.= $block ^ $key; $plaintext.= $block ^ $key;
} }
} else { } else {
@ -984,106 +837,6 @@ class Crypt_TripleDES {
$this->des[2]->disableContinuousBuffer(); $this->des[2]->disableContinuousBuffer();
} }
} }
/**
* Pad "packets".
*
* DES works by encrypting eight bytes at a time. If you ever need to encrypt or decrypt something that's not
* a multiple of eight, it becomes necessary to pad the input so that it's length is a multiple of eight.
*
* Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH1,
* where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
* away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
* transmitted separately)
*
* @see Crypt_TripleDES::disablePadding()
* @access public
*/
function enablePadding()
{
$this->padding = true;
}
/**
* Do not pad packets.
*
* @see Crypt_TripleDES::enablePadding()
* @access public
*/
function disablePadding()
{
$this->padding = false;
}
/**
* Pads a string
*
* Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize (8).
* 8 - (strlen($text) & 7) bytes are added, each of which is equal to chr(8 - (strlen($text) & 7)
*
* If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
* and padding will, hence forth, be enabled.
*
* @see Crypt_TripleDES::_unpad()
* @access private
*/
function _pad($text)
{
$length = strlen($text);
if (!$this->padding) {
if (($length & 7) == 0) {
return $text;
} else {
user_error("The plaintext's length ($length) is not a multiple of the block size (8)", E_USER_NOTICE);
$this->padding = true;
}
}
$pad = 8 - ($length & 7);
return str_pad($text, $length + $pad, chr($pad));
}
/**
* Unpads a string
*
* If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
* and false will be returned.
*
* @see Crypt_TripleDES::_pad()
* @access private
*/
function _unpad($text)
{
if (!$this->padding) {
return $text;
}
$length = ord($text[strlen($text) - 1]);
if (!$length || $length > 8) {
return false;
}
return substr($text, 0, -$length);
}
/**
* String Shift
*
* Inspired by array_shift
*
* @param String $string
* @param optional Integer $index
* @return String
* @access private
*/
function _string_shift(&$string, $index = 1)
{
$substr = substr($string, 0, $index);
$string = substr($string, $index);
return $substr;
}
} }
// vim: ts=4:sw=4:et: // vim: ts=4:sw=4:et:

View File

@ -236,20 +236,20 @@ class Math_BigInteger {
var $hex; var $hex;
/** /**
* Converts base-2, base-10, base-16, and binary strings (eg. base-256) to BigIntegers. * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers.
* *
* If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using
* two's compliment. The sole exception to this is -10, which is treated the same as 10 is. * two's compliment. The sole exception to this is -10, which is treated the same as 10 is.
* *
* Here's an example: * Here's an example:
* <code> * <code>
* <?php * &lt;?php
* include('Math/BigInteger.php'); * include('Math/BigInteger.php');
* *
* $a = new Math_BigInteger('0x32', 16); // 50 in base-16 * $a = new Math_BigInteger('0x32', 16); // 50 in base-16
* *
* echo $a->toString(); // outputs 50 * echo $a->toString(); // outputs 50
* ?> * ?&gt;
* </code> * </code>
* *
* @param optional $x base-10 number or base-$base number if $base set. * @param optional $x base-10 number or base-$base number if $base set.
@ -2137,6 +2137,7 @@ class Math_BigInteger {
* @param Boolean $x_negative * @param Boolean $x_negative
* @param Array $y_value * @param Array $y_value
* @param Boolean $y_negative * @param Boolean $y_negative
* @param Integer $stop
* @return Array * @return Array
* @access private * @access private
*/ */
@ -2629,8 +2630,8 @@ class Math_BigInteger {
* *
* Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y). * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y).
* *
* @param Math_BigInteger $x * @param Math_BigInteger $y
* @return Integer < 0 if $this is less than $x; > 0 if $this is greater than $x, and 0 if they are equal. * @return Integer < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
* @access public * @access public
* @see equals() * @see equals()
* @internal Could return $this->subtract($x), but that's not as fast as what we do do. * @internal Could return $this->subtract($x), but that's not as fast as what we do do.
@ -2709,7 +2710,7 @@ class Math_BigInteger {
* Some bitwise operations give different results depending on the precision being used. Examples include left * Some bitwise operations give different results depending on the precision being used. Examples include left
* shift, not, and rotates. * shift, not, and rotates.
* *
* @param Math_BigInteger $x * @param Integer $bits
* @access public * @access public
* @return Math_BigInteger * @return Math_BigInteger
*/ */
@ -3510,6 +3511,7 @@ class Math_BigInteger {
* *
* Removes leading zeros * Removes leading zeros
* *
* @param Array $value
* @return Math_BigInteger * @return Math_BigInteger
* @access private * @access private
*/ */

341
phpseclib/Net/SCP.php Normal file
View File

@ -0,0 +1,341 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Pure-PHP implementation of SCP.
*
* PHP versions 4 and 5
*
* The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include('Net/SCP.php');
* include('Net/SSH2.php');
*
* $ssh = new Net_SSH2('www.domain.tld');
* if (!$ssh->login('username', 'password')) {
* exit('bad login');
* }
* $scp = new Net_SCP($ssh);
* $scp->put('abcd', str_repeat('x', 1024*1024));
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @category Net
* @package Net_SCP
* @author Jim Wigginton <terrafrost@php.net>
* @copyright MMX Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**#@+
* @access public
* @see Net_SCP::put()
*/
/**
* Reads data from a local file.
*/
define('NET_SCP_LOCAL_FILE', 1);
/**
* Reads data from a string.
*/
define('NET_SCP_STRING', 2);
/**#@-*/
/**#@+
* @access private
* @see Net_SCP::_send()
* @see Net_SCP::_receive()
*/
/**
* SSH1 is being used.
*/
define('NET_SCP_SSH1', 1);
/**
* SSH2 is being used.
*/
define('NET_SCP_SSH2', 2);
/**#@-*/
/**
* Pure-PHP implementations of SCP.
*
* @author Jim Wigginton <terrafrost@php.net>
* @version 0.1.0
* @access public
* @package Net_SCP
*/
class Net_SCP {
/**
* SSH Object
*
* @var Object
* @access private
*/
var $ssh;
/**
* Packet Size
*
* @var Integer
* @access private
*/
var $packet_size;
/**
* Mode
*
* @var Integer
* @access private
*/
var $mode;
/**
* Default Constructor.
*
* Connects to an SSH server
*
* @param String $host
* @param optional Integer $port
* @param optional Integer $timeout
* @return Net_SCP
* @access public
*/
function Net_SCP($ssh)
{
if (!is_object($ssh)) {
return;
}
switch (strtolower(get_class($ssh))) {
case'net_ssh2':
$this->mode = NET_SCP_SSH2;
break;
case 'net_ssh1':
$this->packet_size = 50000;
$this->mode = NET_SCP_SSH1;
break;
default:
return;
}
$this->ssh = $ssh;
}
/**
* Uploads a file to the SCP server.
*
* By default, Net_SCP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
* So, for example, if you set $data to 'filename.ext' and then do Net_SCP::get(), you will get a file, twelve bytes
* long, containing 'filename.ext' as its contents.
*
* Setting $mode to NET_SFTP_LOCAL_FILE will change the above behavior. With NET_SFTP_LOCAL_FILE, $remote_file will
* contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
* large $remote_file will be, as well.
*
* Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
* care of that, yourself.
*
* @param String $remote_file
* @param String $data
* @param optional Integer $mode
* @return Boolean
* @access public
*/
function put($remote_file, $data, $mode = NET_SCP_STRING)
{
if (!isset($this->ssh)) {
return false;
}
$this->ssh->exec('scp -t ' . $remote_file, false); // -t = to
$temp = $this->_receive();
if ($temp !== chr(0)) {
return false;
}
if ($this->mode == NET_SCP_SSH2) {
$this->packet_size = $this->ssh->packet_size_client_to_server[NET_SSH2_CHANNEL_EXEC];
}
$remote_file = basename($remote_file);
$this->_send('C0644 ' . strlen($data) . ' ' . $remote_file . "\n");
$temp = $this->_receive();
if ($temp !== chr(0)) {
return false;
}
if ($mode == NET_SCP_STRING) {
$this->_send($data);
} else {
if (!is_file($data)) {
user_error("$data is not a valid file", E_USER_NOTICE);
return false;
}
$fp = @fopen($data, 'rb');
if (!$fp) {
return false;
}
$size = filesize($data);
for ($i = 0; $i < $length; $i++) {
$this->_send(fgets($fp, $this->packet_size));
}
fclose($fp);
}
$this->_close();
}
/**
* Downloads a file from the SCP server.
*
* Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if
* the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the
* operation
*
* @param String $remote_file
* @param optional String $local_file
* @return Mixed
* @access public
*/
function get($remote_file, $local_file = false)
{
if (!isset($this->ssh)) {
return false;
}
$this->ssh->exec('scp -f ' . $remote_file, false); // -f = from
$this->_send("\0");
if (!preg_match('#(?<perms>[^ ]+) (?<size>\d+) (?<name>.+)#', rtrim($this->_receive()), $info)) {
return false;
}
$this->_send("\0");
$size = 0;
if ($local_file !== false) {
$fp = @fopen($local_file, 'wb');
if (!$fp) {
return false;
}
}
$content = '';
while ($size < $info['size']) {
$data = $this->_receive();
// SCP usually seems to split stuff out into 16k chunks
$size+= strlen($data);
if ($local_file === false) {
$content.= $data;
} else {
fputs($fp, $data);
}
}
$this->_close();
if ($local_file !== false) {
fclose($fp);
return true;
}
return $content;
}
/**
* Sends a packet to an SSH server
*
* @param String $data
* @access private
*/
function _send($data)
{
switch ($this->mode) {
case NET_SCP_SSH2:
$this->ssh->_send_channel_packet(NET_SSH2_CHANNEL_EXEC, $data);
break;
case NET_SCP_SSH1:
$data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($data), $data);
$this->ssh->_send_binary_packet($data);
}
}
/**
* Receives a packet from an SSH server
*
* @return String
* @access private
*/
function _receive()
{
switch ($this->mode) {
case NET_SCP_SSH2:
return $this->ssh->_get_channel_packet(NET_SSH2_CHANNEL_EXEC, true);
case NET_SCP_SSH1:
if (!$this->ssh->bitmap) {
return false;
}
while (true) {
$response = $this->ssh->_get_binary_packet();
switch ($response[NET_SSH1_RESPONSE_TYPE]) {
case NET_SSH1_SMSG_STDOUT_DATA:
extract(unpack('Nlength', $response[NET_SSH1_RESPONSE_DATA]));
return $this->ssh->_string_shift($response[NET_SSH1_RESPONSE_DATA], $length);
case NET_SSH1_SMSG_STDERR_DATA:
break;
case NET_SSH1_SMSG_EXITSTATUS:
$this->ssh->_send_binary_packet(chr(NET_SSH1_CMSG_EXIT_CONFIRMATION));
fclose($this->ssh->fsock);
$this->ssh->bitmap = 0;
return false;
default:
user_error('Unknown packet received', E_USER_NOTICE);
return false;
}
}
}
}
/**
* Closes the connection to an SSH server
*
* @access private
*/
function _close()
{
switch ($this->mode) {
case NET_SCP_SSH2:
$this->ssh->_close_channel(NET_SSH2_CHANNEL_EXEC);
break;
case NET_SCP_SSH1:
$this->ssh->disconnect();
}
}
}

View File

@ -1331,7 +1331,9 @@ class Net_SFTP extends Net_SSH2 {
} }
$dir = $this->_realpath($dir); $dir = $this->_realpath($dir);
$attr = $mode == -1 ? chr(0) : pack('N2', NET_SFTP_ATTR_PERMISSIONS, $mode & 07777); // by not providing any permissions, hopefully the server will use the logged in users umask - their
// default permissions.
$attr = $mode == -1 ? "\0\0\0\0" : pack('N2', NET_SFTP_ATTR_PERMISSIONS, $mode & 07777);
if ($recursive) { if ($recursive) {
$dirs = explode('/', preg_replace('#/(?=/)|/$#', '', $dir)); $dirs = explode('/', preg_replace('#/(?=/)|/$#', '', $dir));
@ -1359,8 +1361,6 @@ class Net_SFTP extends Net_SSH2 {
*/ */
function _mkdir_helper($dir, $attr) function _mkdir_helper($dir, $attr)
{ {
// by not providing any permissions, hopefully the server will use the logged in users umask - their
// default permissions.
if (!$this->_send_sftp_packet(NET_SFTP_MKDIR, pack('Na*a*', strlen($dir), $dir, $attr))) { if (!$this->_send_sftp_packet(NET_SFTP_MKDIR, pack('Na*a*', strlen($dir), $dir, $attr))) {
return false; return false;
} }
@ -2205,4 +2205,4 @@ class Net_SFTP extends Net_SSH2 {
$this->pwd = false; $this->pwd = false;
parent::_disconnect($reason); parent::_disconnect($reason);
} }
} }

View File

@ -112,6 +112,13 @@ if (!class_exists('Crypt_AES')) {
require_once('Crypt/AES.php'); require_once('Crypt/AES.php');
} }
/**
* Include Crypt_Twofish
*/
if (!class_exists('Crypt_Twofish')) {
require_once('Crypt/Twofish.php');
}
/**#@+ /**#@+
* Execution Bitmap Masks * Execution Bitmap Masks
* *
@ -752,6 +759,18 @@ class Net_SSH2 {
*/ */
var $keyboard_requests_responses = array(); var $keyboard_requests_responses = array();
/**
* Banner Message
*
* Quoting from the RFC, "in some jurisdictions, sending a warning message before
* authentication may be relevant for getting legal protection."
*
* @see Net_SSH2::_filter()
* @see Net_SSH2::getBannerMessage()
* @access private
*/
var $banner_message = '';
/** /**
* Default Constructor. * Default Constructor.
* *
@ -958,20 +977,30 @@ class Net_SSH2 {
'arcfour256', 'arcfour256',
'arcfour128', 'arcfour128',
'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key 'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key
'aes128-cbc', // RECOMMENDED AES with a 128-bit key // CTR modes from <http://tools.ietf.org/html/rfc4344#section-4>:
'aes192-cbc', // OPTIONAL AES with a 192-bit key 'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key
'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key 'aes192-ctr', // RECOMMENDED AES with 192-bit key
'aes256-ctr', // RECOMMENDED AES with 256-bit key
// from <http://tools.ietf.org/html/rfc4344#section-4>: 'twofish128-ctr', // OPTIONAL Twofish in SDCTR mode, with 128-bit key
'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key 'twofish192-ctr', // OPTIONAL Twofish with 192-bit key
'aes192-ctr', // RECOMMENDED AES with 192-bit key 'twofish256-ctr', // OPTIONAL Twofish with 256-bit key
'aes256-ctr', // RECOMMENDED AES with 256-bit key
'3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode
'3des-cbc', // REQUIRED three-key 3DES in CBC mode 'aes128-cbc', // RECOMMENDED AES with a 128-bit key
'none' // OPTIONAL no encryption; NOT RECOMMENDED 'aes192-cbc', // OPTIONAL AES with a 192-bit key
'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key
'twofish128-cbc', // OPTIONAL Twofish with a 128-bit key
'twofish192-cbc', // OPTIONAL Twofish with a 192-bit key
'twofish256-cbc',
'twofish-cbc', // OPTIONAL alias for "twofish256-cbc"
// (this is being retained for historical reasons)
'3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode
'3des-cbc', // REQUIRED three-key 3DES in CBC mode
'none' // OPTIONAL no encryption; NOT RECOMMENDED
); );
static $mac_algorithms = array( static $mac_algorithms = array(
@ -1080,14 +1109,21 @@ class Net_SSH2 {
break; break;
case 'aes256-cbc': case 'aes256-cbc':
case 'aes256-ctr': case 'aes256-ctr':
case 'twofish-cbc':
case 'twofish256-cbc':
case 'twofish256-ctr':
$decryptKeyLength = 32; // eg. 256 / 8 $decryptKeyLength = 32; // eg. 256 / 8
break; break;
case 'aes192-cbc': case 'aes192-cbc':
case 'aes192-ctr': case 'aes192-ctr':
case 'twofish192-cbc':
case 'twofish192-ctr':
$decryptKeyLength = 24; // eg. 192 / 8 $decryptKeyLength = 24; // eg. 192 / 8
break; break;
case 'aes128-cbc': case 'aes128-cbc':
case 'aes128-ctr': case 'aes128-ctr':
case 'twofish128-cbc':
case 'twofish128-ctr':
$decryptKeyLength = 16; // eg. 128 / 8 $decryptKeyLength = 16; // eg. 128 / 8
break; break;
case 'arcfour': case 'arcfour':
@ -1115,14 +1151,21 @@ class Net_SSH2 {
break; break;
case 'aes256-cbc': case 'aes256-cbc':
case 'aes256-ctr': case 'aes256-ctr':
case 'twofish-cbc':
case 'twofish256-cbc':
case 'twofish256-ctr':
$encryptKeyLength = 32; $encryptKeyLength = 32;
break; break;
case 'aes192-cbc': case 'aes192-cbc':
case 'aes192-ctr': case 'aes192-ctr':
case 'twofish192-cbc':
case 'twofish192-ctr':
$encryptKeyLength = 24; $encryptKeyLength = 24;
break; break;
case 'aes128-cbc': case 'aes128-cbc':
case 'aes128-ctr': case 'aes128-ctr':
case 'twofish128-cbc':
case 'twofish128-ctr':
$encryptKeyLength = 16; $encryptKeyLength = 16;
break; break;
case 'arcfour': case 'arcfour':
@ -1248,7 +1291,7 @@ class Net_SSH2 {
} }
if ($public_key_format != $server_host_key_algorithms[$i] || $this->signature_format != $server_host_key_algorithms[$i]) { if ($public_key_format != $server_host_key_algorithms[$i] || $this->signature_format != $server_host_key_algorithms[$i]) {
user_error('Sever Host Key Algorithm Mismatch'); user_error('Server Host Key Algorithm Mismatch');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
} }
@ -1295,6 +1338,19 @@ class Net_SSH2 {
$this->encrypt = new Crypt_AES(CRYPT_AES_MODE_CTR); $this->encrypt = new Crypt_AES(CRYPT_AES_MODE_CTR);
$this->encrypt_block_size = 16; // eg. 128 / 8 $this->encrypt_block_size = 16; // eg. 128 / 8
break; break;
case 'twofish128-cbc':
case 'twofish192-cbc':
case 'twofish256-cbc':
case 'twofish-cbc':
$this->encrypt = new Crypt_Twofish();
$this->encrypt_block_size = 16;
break;
case 'twofish128-ctr':
case 'twofish192-ctr':
case 'twofish256-ctr':
$this->encrypt = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR);
$this->encrypt_block_size = 16;
break;
case 'arcfour': case 'arcfour':
case 'arcfour128': case 'arcfour128':
case 'arcfour256': case 'arcfour256':
@ -1323,6 +1379,19 @@ class Net_SSH2 {
$this->decrypt = new Crypt_AES(CRYPT_AES_MODE_CTR); $this->decrypt = new Crypt_AES(CRYPT_AES_MODE_CTR);
$this->decrypt_block_size = 16; $this->decrypt_block_size = 16;
break; break;
case 'twofish128-cbc':
case 'twofish192-cbc':
case 'twofish256-cbc':
case 'twofish-cbc':
$this->decrypt = new Crypt_Twofish();
$this->decrypt_block_size = 16;
break;
case 'twofish128-ctr':
case 'twofish192-ctr':
case 'twofish256-ctr':
$this->decrypt = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR);
$this->decrypt_block_size = 16;
break;
case 'arcfour': case 'arcfour':
case 'arcfour128': case 'arcfour128':
case 'arcfour256': case 'arcfour256':
@ -1875,6 +1944,7 @@ class Net_SSH2 {
* Setting $timeout to false or 0 will mean there is no timeout. * Setting $timeout to false or 0 will mean there is no timeout.
* *
* @param Mixed $timeout * @param Mixed $timeout
* @access public
*/ */
function setTimeout($timeout) function setTimeout($timeout)
{ {
@ -1883,8 +1953,11 @@ class Net_SSH2 {
/** /**
* Get the output from stdError * Get the output from stdError
*
* @access public
*/ */
function getStdError(){ function getStdError()
{
return $this->stdErrorLog; return $this->stdErrorLog;
} }
@ -2313,7 +2386,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->errors[] = 'SSH_MSG_USERAUTH_BANNER: ' . utf8_decode($this->_string_shift($payload, $length)); $this->banner_message = utf8_decode($this->_string_shift($payload, $length));
$payload = $this->_get_binary_packet(); $payload = $this->_get_binary_packet();
} }
@ -3045,6 +3118,20 @@ class Net_SSH2 {
return $this->languages_client_to_server; return $this->languages_client_to_server;
} }
/**
* Returns the banner message.
*
* Quoting from the RFC, "in some jurisdictions, sending a warning message before
* authentication may be relevant for getting legal protection."
*
* @return String
* @access public
*/
function getBannerMessage()
{
return $this->banner_message;
}
/** /**
* Returns the server public host key. * Returns the server public host key.
* *