mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-12-28 12:10:59 +00:00
commit
0a040e1c5c
@ -47,5 +47,10 @@
|
||||
"files": [
|
||||
"phpseclib/Crypt/Random.php"
|
||||
]
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.3-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -42,6 +42,13 @@
|
||||
* @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.
|
||||
*
|
||||
@ -55,8 +62,7 @@
|
||||
*/
|
||||
function crypt_random_string($length)
|
||||
{
|
||||
// PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster
|
||||
if ((PHP_OS & "\xDF\xDF\xDF") === 'WIN') {
|
||||
if (CRYPT_RANDOM_IS_WINDOWS) {
|
||||
// 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
|
||||
if (function_exists('mcrypt_create_iv') && function_exists('class_alias')) {
|
||||
|
@ -83,70 +83,7 @@ define('CRYPT_DES_MODE_CBC3', CRYPT_DES_MODE_CBC);
|
||||
* @access public
|
||||
* @package Crypt_TerraDES
|
||||
*/
|
||||
class Crypt_TripleDES {
|
||||
/**
|
||||
* 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";
|
||||
|
||||
class Crypt_TripleDES extends Crypt_DES {
|
||||
/**
|
||||
* The Crypt_DES objects
|
||||
*
|
||||
@ -155,87 +92,6 @@ class Crypt_TripleDES {
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@ -328,6 +184,10 @@ class Crypt_TripleDES {
|
||||
$this->paddable = true;
|
||||
$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[1]->setKey(substr($key, 8, 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;
|
||||
}
|
||||
@ -438,39 +314,6 @@ class Crypt_TripleDES {
|
||||
$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.
|
||||
*
|
||||
@ -565,6 +408,11 @@ class Crypt_TripleDES {
|
||||
return $this->des[0]->encrypt($plaintext);
|
||||
}
|
||||
|
||||
if ($this->use_inline_crypt) {
|
||||
$inline = $this->inline_crypt;
|
||||
return $inline('encrypt', $this, $plaintext);
|
||||
}
|
||||
|
||||
$des = $this->des;
|
||||
|
||||
$buffer = &$this->enbuffer;
|
||||
@ -612,7 +460,7 @@ class Crypt_TripleDES {
|
||||
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||
$buffer['encrypted'].= $key;
|
||||
}
|
||||
$key = $this->_string_shift($buffer['encrypted'], 8);
|
||||
$key = $this->_string_shift($buffer['encrypted']);
|
||||
$ciphertext.= $block ^ $key;
|
||||
}
|
||||
} else {
|
||||
@ -676,7 +524,7 @@ class Crypt_TripleDES {
|
||||
$xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT);
|
||||
$buffer['xor'].= $xor;
|
||||
}
|
||||
$key = $this->_string_shift($buffer['xor'], 8);
|
||||
$key = $this->_string_shift($buffer['xor']);
|
||||
$ciphertext.= $block ^ $key;
|
||||
}
|
||||
} else {
|
||||
@ -780,6 +628,11 @@ class Crypt_TripleDES {
|
||||
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
|
||||
}
|
||||
|
||||
if ($this->use_inline_crypt) {
|
||||
$inline = $this->inline_crypt;
|
||||
return $inline('decrypt', $this, $ciphertext);
|
||||
}
|
||||
|
||||
$des = $this->des;
|
||||
|
||||
$buffer = &$this->debuffer;
|
||||
@ -821,7 +674,7 @@ class Crypt_TripleDES {
|
||||
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||
$buffer['ciphertext'].= $key;
|
||||
}
|
||||
$key = $this->_string_shift($buffer['ciphertext'], 8);
|
||||
$key = $this->_string_shift($buffer['ciphertext']);
|
||||
$plaintext.= $block ^ $key;
|
||||
}
|
||||
} else {
|
||||
@ -890,7 +743,7 @@ class Crypt_TripleDES {
|
||||
$xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT);
|
||||
$buffer['xor'].= $xor;
|
||||
}
|
||||
$key = $this->_string_shift($buffer['xor'], 8);
|
||||
$key = $this->_string_shift($buffer['xor']);
|
||||
$plaintext.= $block ^ $key;
|
||||
}
|
||||
} else {
|
||||
@ -984,106 +837,6 @@ class Crypt_TripleDES {
|
||||
$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:
|
||||
|
@ -236,20 +236,20 @@ class Math_BigInteger {
|
||||
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
|
||||
* two's compliment. The sole exception to this is -10, which is treated the same as 10 is.
|
||||
*
|
||||
* Here's an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* <?php
|
||||
* include('Math/BigInteger.php');
|
||||
*
|
||||
* $a = new Math_BigInteger('0x32', 16); // 50 in base-16
|
||||
*
|
||||
* echo $a->toString(); // outputs 50
|
||||
* ?>
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* @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 Array $y_value
|
||||
* @param Boolean $y_negative
|
||||
* @param Integer $stop
|
||||
* @return Array
|
||||
* @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).
|
||||
*
|
||||
* @param Math_BigInteger $x
|
||||
* @return Integer < 0 if $this is less than $x; > 0 if $this is greater than $x, and 0 if they are equal.
|
||||
* @param Math_BigInteger $y
|
||||
* @return Integer < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
|
||||
* @access public
|
||||
* @see equals()
|
||||
* @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
|
||||
* shift, not, and rotates.
|
||||
*
|
||||
* @param Math_BigInteger $x
|
||||
* @param Integer $bits
|
||||
* @access public
|
||||
* @return Math_BigInteger
|
||||
*/
|
||||
@ -3510,6 +3511,7 @@ class Math_BigInteger {
|
||||
*
|
||||
* Removes leading zeros
|
||||
*
|
||||
* @param Array $value
|
||||
* @return Math_BigInteger
|
||||
* @access private
|
||||
*/
|
||||
|
341
phpseclib/Net/SCP.php
Normal file
341
phpseclib/Net/SCP.php
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
@ -1331,7 +1331,9 @@ class Net_SFTP extends Net_SSH2 {
|
||||
}
|
||||
|
||||
$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) {
|
||||
$dirs = explode('/', preg_replace('#/(?=/)|/$#', '', $dir));
|
||||
@ -1359,8 +1361,6 @@ class Net_SFTP extends Net_SSH2 {
|
||||
*/
|
||||
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))) {
|
||||
return false;
|
||||
}
|
||||
|
@ -112,6 +112,13 @@ if (!class_exists('Crypt_AES')) {
|
||||
require_once('Crypt/AES.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Include Crypt_Twofish
|
||||
*/
|
||||
if (!class_exists('Crypt_Twofish')) {
|
||||
require_once('Crypt/Twofish.php');
|
||||
}
|
||||
|
||||
/**#@+
|
||||
* Execution Bitmap Masks
|
||||
*
|
||||
@ -752,6 +759,18 @@ class Net_SSH2 {
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@ -958,20 +977,30 @@ class Net_SSH2 {
|
||||
'arcfour256',
|
||||
'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
|
||||
'aes192-cbc', // OPTIONAL AES with a 192-bit key
|
||||
'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key
|
||||
// CTR modes from <http://tools.ietf.org/html/rfc4344#section-4>:
|
||||
'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-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>:
|
||||
'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key
|
||||
'aes192-ctr', // RECOMMENDED AES with 192-bit key
|
||||
'aes256-ctr', // RECOMMENDED AES with 256-bit key
|
||||
'3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode
|
||||
'twofish128-ctr', // OPTIONAL Twofish in SDCTR mode, with 128-bit key
|
||||
'twofish192-ctr', // OPTIONAL Twofish with 192-bit key
|
||||
'twofish256-ctr', // OPTIONAL Twofish with 256-bit key
|
||||
|
||||
'3des-cbc', // REQUIRED three-key 3DES in CBC mode
|
||||
'none' // OPTIONAL no encryption; NOT RECOMMENDED
|
||||
'aes128-cbc', // RECOMMENDED AES with a 128-bit key
|
||||
'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(
|
||||
@ -1080,14 +1109,21 @@ class Net_SSH2 {
|
||||
break;
|
||||
case 'aes256-cbc':
|
||||
case 'aes256-ctr':
|
||||
case 'twofish-cbc':
|
||||
case 'twofish256-cbc':
|
||||
case 'twofish256-ctr':
|
||||
$decryptKeyLength = 32; // eg. 256 / 8
|
||||
break;
|
||||
case 'aes192-cbc':
|
||||
case 'aes192-ctr':
|
||||
case 'twofish192-cbc':
|
||||
case 'twofish192-ctr':
|
||||
$decryptKeyLength = 24; // eg. 192 / 8
|
||||
break;
|
||||
case 'aes128-cbc':
|
||||
case 'aes128-ctr':
|
||||
case 'twofish128-cbc':
|
||||
case 'twofish128-ctr':
|
||||
$decryptKeyLength = 16; // eg. 128 / 8
|
||||
break;
|
||||
case 'arcfour':
|
||||
@ -1115,14 +1151,21 @@ class Net_SSH2 {
|
||||
break;
|
||||
case 'aes256-cbc':
|
||||
case 'aes256-ctr':
|
||||
case 'twofish-cbc':
|
||||
case 'twofish256-cbc':
|
||||
case 'twofish256-ctr':
|
||||
$encryptKeyLength = 32;
|
||||
break;
|
||||
case 'aes192-cbc':
|
||||
case 'aes192-ctr':
|
||||
case 'twofish192-cbc':
|
||||
case 'twofish192-ctr':
|
||||
$encryptKeyLength = 24;
|
||||
break;
|
||||
case 'aes128-cbc':
|
||||
case 'aes128-ctr':
|
||||
case 'twofish128-cbc':
|
||||
case 'twofish128-ctr':
|
||||
$encryptKeyLength = 16;
|
||||
break;
|
||||
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]) {
|
||||
user_error('Sever Host Key Algorithm Mismatch');
|
||||
user_error('Server Host Key Algorithm Mismatch');
|
||||
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_block_size = 16; // eg. 128 / 8
|
||||
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 'arcfour128':
|
||||
case 'arcfour256':
|
||||
@ -1323,6 +1379,19 @@ class Net_SSH2 {
|
||||
$this->decrypt = new Crypt_AES(CRYPT_AES_MODE_CTR);
|
||||
$this->decrypt_block_size = 16;
|
||||
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 'arcfour128':
|
||||
case 'arcfour256':
|
||||
@ -1875,6 +1944,7 @@ class Net_SSH2 {
|
||||
* Setting $timeout to false or 0 will mean there is no timeout.
|
||||
*
|
||||
* @param Mixed $timeout
|
||||
* @access public
|
||||
*/
|
||||
function setTimeout($timeout)
|
||||
{
|
||||
@ -1883,8 +1953,11 @@ class Net_SSH2 {
|
||||
|
||||
/**
|
||||
* Get the output from stdError
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function getStdError(){
|
||||
function getStdError()
|
||||
{
|
||||
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) {
|
||||
$this->_string_shift($payload, 1);
|
||||
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();
|
||||
}
|
||||
|
||||
@ -3045,6 +3118,20 @@ class Net_SSH2 {
|
||||
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.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user