Merge branch 'develop' of git@github.com:LDAPAccountManager/lam.git into develop

This commit is contained in:
Roland Gruber 2017-09-24 09:49:02 +02:00
commit d521f60f66
63 changed files with 33816 additions and 34310 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
/.settings/
/.buildpath
/.project
/.Readme.md.html

View File

@ -3,9 +3,16 @@ LDAP Account Manager
LDAP Account Manager (LAM) is a webfrontend for managing entries (e.g. users, groups, DHCP settings) stored in an LDAP directory. LAM was designed to make LDAP management as easy as possible for the user. It abstracts from the technical details of LDAP and allows persons without technical background to manage LDAP entries. If needed, power users may still directly edit LDAP entries via the integrated LDAP browser.
![LAM](https://www.ldap-account-manager.org/lamcms/sites/default/files/styles/slideshow/public/userList.png)
![LAM](https://www.ldap-account-manager.org/lamcms/sites/default/files/styles/slideshow/public/user_0.png)
# Download
You can get the newest version at https://www.ldap-account-manager.org/.
# Documentation
Please see the [documentation area](https://www.ldap-account-manager.org/lamcms/documentation).
# Source code
There are two modules. Usually, you only need the files inside "lam".

View File

@ -1,3 +1,7 @@
December 2017
- PHP 5.6 and Internet Explorer 11 or later required
19.09.2017 6.1
- Automatically trim input fields to avoid trailing/leading spaces
- LAM Pro:
@ -8,11 +12,13 @@
-> Password modify page reports error on password change when posixAccount is present for users
-> Nginx configuration files did not include "fastcgi_param SCRIPT_FILENAME $request_filename;" (193)
20.07.2017 6.0.1
- Fixed bugs:
-> Configuration file fills up with empty values
-> Tool visibility settings
26.06.2017 6.0
- Support multiple configurations for same account type
- PHP 7.1 compatibility

View File

@ -15,7 +15,7 @@ LAM - Readme
https://www.ldap-account-manager.org/
Copyright (C) 2003 - 2016 Roland Gruber <post@rolandgruber.de>
Copyright (C) 2003 - 2017 Roland Gruber <post@rolandgruber.de>
Installation and documentation:
Please see the LAM manual in docs/manual/index.html.

View File

@ -1,4 +1,4 @@
This software is copyright (c) 2003 - 2016 by Roland Gruber
This software is copyright (c) 2003 - 2017 by Roland Gruber
If you purchased a copy of LDAP Account Manager Pro then the following
files are licensed under the conditions which you accepted at purchase

View File

@ -15,7 +15,7 @@
<itemizedlist>
<listitem>
<para>Apache/Nginx webserver (SSL recommended) with PHP module (PHP
(&gt;= 5.4.0) with ldap, gettext, xml, openssl and optional
(&gt;= 5.6.0) with ldap, gettext, xml, openssl and optional
OpenSSL)</para>
</listitem>
@ -44,7 +44,7 @@
</listitem>
<listitem>
<para>Internet Explorer 9 <emphasis role="bold">(compatibility
<para>Internet Explorer 11 <emphasis role="bold">(compatibility
mode turned off)</emphasis></para>
</listitem>

View File

@ -63,7 +63,7 @@
<itemizedlist>
<listitem>
<para>PHP (&gt;= 5.4.0)</para>
<para>PHP (&gt;= 5.6.0)</para>
</listitem>
<listitem>
@ -85,7 +85,7 @@
</listitem>
<listitem>
<para>Internet Explorer 9<emphasis role="bold"> (compatibility mode
<para>Internet Explorer 11<emphasis role="bold"> (compatibility mode
turned off)</emphasis></para>
</listitem>

View File

@ -1,197 +1,126 @@
<?php
/**
* Pure-PHP implementation of AES.
*
* Uses mcrypt, if available/possible, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
*
* NOTE: Since AES.php is (for compatibility and phpseclib-historical reasons) virtually
* just a wrapper to Rijndael.php you may consider using Rijndael.php instead of
* to save one include_once().
*
* If {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
* {@link self::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
* it'll be null-padded to 192-bits and 192 bits will be the key length until {@link self::setKey() setKey()}
* is called, again, at which point, it'll be recalculated.
*
* Since Crypt_AES extends Crypt_Rijndael, some functions are available to be called that, in the context of AES, don't
* make a whole lot of sense. {@link self::setBlockLength() setBlockLength()}, for instance. Calling that function,
* however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/AES.php';
*
* $aes = new Crypt_AES();
*
* $aes->setKey('abcdefghijklmnop');
*
* $size = 10 * 1024;
* $plaintext = '';
* for ($i = 0; $i < $size; $i++) {
* $plaintext.= 'a';
* }
*
* echo $aes->decrypt($aes->encrypt($plaintext));
* ?>
* </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 Crypt
* @package Crypt_AES
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2008 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Rijndael
*/
if (!class_exists('Crypt_Rijndael')) {
include_once 'Rijndael.php';
}
/**#@+
* @access public
* @see self::encrypt()
* @see self::decrypt()
*/
/**
* Encrypt / decrypt using the Counter mode.
*
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
*/
define('CRYPT_AES_MODE_CTR', CRYPT_MODE_CTR);
/**
* Encrypt / decrypt using the Electronic Code Book mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
*/
define('CRYPT_AES_MODE_ECB', CRYPT_MODE_ECB);
/**
* Encrypt / decrypt using the Code Book Chaining mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
*/
define('CRYPT_AES_MODE_CBC', CRYPT_MODE_CBC);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
define('CRYPT_AES_MODE_CFB', CRYPT_MODE_CFB);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
define('CRYPT_AES_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/
/**
* Pure-PHP implementation of AES.
*
* @package Crypt_AES
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Crypt_AES extends Crypt_Rijndael
{
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var string
* @access private
*/
var $const_namespace = 'AES';
/**
* Dummy function
*
* Since Crypt_AES extends Crypt_Rijndael, this function is, technically, available, but it doesn't do anything.
*
* @see Crypt_Rijndael::setBlockLength()
* @access public
* @param int $length
*/
function setBlockLength($length)
{
return;
}
/**
* Sets the key length
*
* Valid key lengths are 128, 192, and 256. If the length is less than 128, it will be rounded up to
* 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
*
* @see Crypt_Rijndael:setKeyLength()
* @access public
* @param int $length
*/
function setKeyLength($length)
{
switch ($length) {
case 160:
$length = 192;
break;
case 224:
$length = 256;
}
parent::setKeyLength($length);
}
/**
* Sets the key.
*
* Rijndael supports five different key lengths, AES only supports three.
*
* @see Crypt_Rijndael:setKey()
* @see setKeyLength()
* @access public
* @param string $key
*/
function setKey($key)
{
parent::setKey($key);
if (!$this->explicit_key_length) {
$length = strlen($key);
switch (true) {
case $length <= 16:
$this->key_length = 16;
break;
case $length <= 24:
$this->key_length = 24;
break;
default:
$this->key_length = 32;
}
$this->_setEngine();
}
}
}
<?php
/**
* Pure-PHP implementation of AES.
*
* Uses mcrypt, if available/possible, and an internal implementation, otherwise.
*
* PHP version 5
*
* NOTE: Since AES.php is (for compatibility and phpseclib-historical reasons) virtually
* just a wrapper to Rijndael.php you may consider using Rijndael.php instead of
* to save one include_once().
*
* If {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
* {@link self::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
* it'll be null-padded to 192-bits and 192 bits will be the key length until {@link self::setKey() setKey()}
* is called, again, at which point, it'll be recalculated.
*
* Since \phpseclib\Crypt\AES extends \phpseclib\Crypt\Rijndael, some functions are available to be called that, in the context of AES, don't
* make a whole lot of sense. {@link self::setBlockLength() setBlockLength()}, for instance. Calling that function,
* however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'vendor/autoload.php';
*
* $aes = new \phpseclib\Crypt\AES();
*
* $aes->setKey('abcdefghijklmnop');
*
* $size = 10 * 1024;
* $plaintext = '';
* for ($i = 0; $i < $size; $i++) {
* $plaintext.= 'a';
* }
*
* echo $aes->decrypt($aes->encrypt($plaintext));
* ?>
* </code>
*
* @category Crypt
* @package AES
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2008 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Crypt;
/**
* Pure-PHP implementation of AES.
*
* @package AES
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class AES extends Rijndael
{
/**
* Dummy function
*
* Since \phpseclib\Crypt\AES extends \phpseclib\Crypt\Rijndael, this function is, technically, available, but it doesn't do anything.
*
* @see \phpseclib\Crypt\Rijndael::setBlockLength()
* @access public
* @param int $length
*/
function setBlockLength($length)
{
return;
}
/**
* Sets the key length
*
* Valid key lengths are 128, 192, and 256. If the length is less than 128, it will be rounded up to
* 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
*
* @see \phpseclib\Crypt\Rijndael:setKeyLength()
* @access public
* @param int $length
*/
function setKeyLength($length)
{
switch ($length) {
case 160:
$length = 192;
break;
case 224:
$length = 256;
}
parent::setKeyLength($length);
}
/**
* Sets the key.
*
* Rijndael supports five different key lengths, AES only supports three.
*
* @see \phpseclib\Crypt\Rijndael:setKey()
* @see setKeyLength()
* @access public
* @param string $key
*/
function setKey($key)
{
parent::setKey($key);
if (!$this->explicit_key_length) {
$length = strlen($key);
switch (true) {
case $length <= 16:
$this->key_length = 16;
break;
case $length <= 24:
$this->key_length = 24;
break;
default:
$this->key_length = 32;
}
$this->_setEngine();
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,352 +1,342 @@
<?php
/**
* Pure-PHP implementation of RC4.
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
*
* Useful resources are as follows:
*
* - {@link http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt ARCFOUR Algorithm}
* - {@link http://en.wikipedia.org/wiki/RC4 - Wikipedia: RC4}
*
* RC4 is also known as ARCFOUR or ARC4. The reason is elaborated upon at Wikipedia. This class is named RC4 and not
* ARCFOUR or ARC4 because RC4 is how it is referred to in the SSH1 specification.
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/RC4.php';
*
* $rc4 = new Crypt_RC4();
*
* $rc4->setKey('abcdefgh');
*
* $size = 10 * 1024;
* $plaintext = '';
* for ($i = 0; $i < $size; $i++) {
* $plaintext.= 'a';
* }
*
* echo $rc4->decrypt($rc4->encrypt($plaintext));
* ?>
* </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 Crypt
* @package Crypt_RC4
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Base
*
* Base cipher class
*/
if (!class_exists('Crypt_Base')) {
include_once 'Base.php';
}
/**#@+
* @access private
* @see self::_crypt()
*/
define('CRYPT_RC4_ENCRYPT', 0);
define('CRYPT_RC4_DECRYPT', 1);
/**#@-*/
/**
* Pure-PHP implementation of RC4.
*
* @package Crypt_RC4
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Crypt_RC4 extends Crypt_Base
{
/**
* Block Length of the cipher
*
* RC4 is a stream cipher
* so we the block_size to 0
*
* @see Crypt_Base::block_size
* @var int
* @access private
*/
var $block_size = 0;
/**
* Key Length (in bytes)
*
* @see Crypt_RC4::setKeyLength()
* @var int
* @access private
*/
var $key_length = 128; // = 1024 bits
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var string
* @access private
*/
var $const_namespace = 'RC4';
/**
* The mcrypt specific name of the cipher
*
* @see Crypt_Base::cipher_name_mcrypt
* @var string
* @access private
*/
var $cipher_name_mcrypt = 'arcfour';
/**
* Holds whether performance-optimized $inline_crypt() can/should be used.
*
* @see Crypt_Base::inline_crypt
* @var mixed
* @access private
*/
var $use_inline_crypt = false; // currently not available
/**
* The Key
*
* @see self::setKey()
* @var string
* @access private
*/
var $key = "\0";
/**
* The Key Stream for decryption and encryption
*
* @see self::setKey()
* @var array
* @access private
*/
var $stream;
/**
* Default Constructor.
*
* Determines whether or not the mcrypt extension should be used.
*
* @see Crypt_Base::Crypt_Base()
* @return Crypt_RC4
* @access public
*/
function Crypt_RC4()
{
parent::Crypt_Base(CRYPT_MODE_STREAM);
}
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see Crypt_Base::Crypt_Base()
* @param int $engine
* @access public
* @return bool
*/
function isValidEngine($engine)
{
switch ($engine) {
case CRYPT_ENGINE_OPENSSL:
switch (strlen($this->key)) {
case 5:
$this->cipher_name_openssl = 'rc4-40';
break;
case 8:
$this->cipher_name_openssl = 'rc4-64';
break;
case 16:
$this->cipher_name_openssl = 'rc4';
break;
default:
return false;
}
}
return parent::isValidEngine($engine);
}
/**
* Dummy function.
*
* Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1].
* If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before
* calling setKey().
*
* [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol,
* the IV's are relatively easy to predict, an attack described by
* {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir}
* can be used to quickly guess at the rest of the key. The following links elaborate:
*
* {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
* {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
*
* @param string $iv
* @see self::setKey()
* @access public
*/
function setIV($iv)
{
}
/**
* Sets the key length
*
* Keys can be between 1 and 256 bytes long.
*
* @access public
* @param int $length
*/
function setKeyLength($length)
{
if ($length < 8) {
$this->key_length = 1;
} elseif ($length > 2048) {
$this->key_length = 256;
} else {
$this->key_length = $length >> 3;
}
parent::setKeyLength($length);
}
/**
* Encrypts a message.
*
* @see Crypt_Base::decrypt()
* @see self::_crypt()
* @access public
* @param string $plaintext
* @return string $ciphertext
*/
function encrypt($plaintext)
{
if ($this->engine != CRYPT_ENGINE_INTERNAL) {
return parent::encrypt($plaintext);
}
return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT);
}
/**
* Decrypts a message.
*
* $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
* At least if the continuous buffer is disabled.
*
* @see Crypt_Base::encrypt()
* @see self::_crypt()
* @access public
* @param string $ciphertext
* @return string $plaintext
*/
function decrypt($ciphertext)
{
if ($this->engine != CRYPT_ENGINE_INTERNAL) {
return parent::decrypt($ciphertext);
}
return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT);
}
/**
* Setup the key (expansion)
*
* @see Crypt_Base::_setupKey()
* @access private
*/
function _setupKey()
{
$key = $this->key;
$keyLength = strlen($key);
$keyStream = range(0, 255);
$j = 0;
for ($i = 0; $i < 256; $i++) {
$j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255;
$temp = $keyStream[$i];
$keyStream[$i] = $keyStream[$j];
$keyStream[$j] = $temp;
}
$this->stream = array();
$this->stream[CRYPT_RC4_DECRYPT] = $this->stream[CRYPT_RC4_ENCRYPT] = array(
0, // index $i
0, // index $j
$keyStream
);
}
/**
* Encrypts or decrypts a message.
*
* @see self::encrypt()
* @see self::decrypt()
* @access private
* @param string $text
* @param int $mode
* @return string $text
*/
function _crypt($text, $mode)
{
if ($this->changed) {
$this->_setup();
$this->changed = false;
}
$stream = &$this->stream[$mode];
if ($this->continuousBuffer) {
$i = &$stream[0];
$j = &$stream[1];
$keyStream = &$stream[2];
} else {
$i = $stream[0];
$j = $stream[1];
$keyStream = $stream[2];
}
$len = strlen($text);
for ($k = 0; $k < $len; ++$k) {
$i = ($i + 1) & 255;
$ksi = $keyStream[$i];
$j = ($j + $ksi) & 255;
$ksj = $keyStream[$j];
$keyStream[$i] = $ksj;
$keyStream[$j] = $ksi;
$text[$k] = $text[$k] ^ chr($keyStream[($ksj + $ksi) & 255]);
}
return $text;
}
}
<?php
/**
* Pure-PHP implementation of RC4.
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
* PHP version 5
*
* Useful resources are as follows:
*
* - {@link http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt ARCFOUR Algorithm}
* - {@link http://en.wikipedia.org/wiki/RC4 - Wikipedia: RC4}
*
* RC4 is also known as ARCFOUR or ARC4. The reason is elaborated upon at Wikipedia. This class is named RC4 and not
* ARCFOUR or ARC4 because RC4 is how it is referred to in the SSH1 specification.
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'vendor/autoload.php';
*
* $rc4 = new \phpseclib\Crypt\RC4();
*
* $rc4->setKey('abcdefgh');
*
* $size = 10 * 1024;
* $plaintext = '';
* for ($i = 0; $i < $size; $i++) {
* $plaintext.= 'a';
* }
*
* echo $rc4->decrypt($rc4->encrypt($plaintext));
* ?>
* </code>
*
* @category Crypt
* @package RC4
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Crypt;
/**
* Pure-PHP implementation of RC4.
*
* @package RC4
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class RC4 extends Base
{
/**#@+
* @access private
* @see \phpseclib\Crypt\RC4::_crypt()
*/
const ENCRYPT = 0;
const DECRYPT = 1;
/**#@-*/
/**
* Block Length of the cipher
*
* RC4 is a stream cipher
* so we the block_size to 0
*
* @see \phpseclib\Crypt\Base::block_size
* @var int
* @access private
*/
var $block_size = 0;
/**
* Key Length (in bytes)
*
* @see \phpseclib\Crypt\RC4::setKeyLength()
* @var int
* @access private
*/
var $key_length = 128; // = 1024 bits
/**
* The mcrypt specific name of the cipher
*
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt
* @var string
* @access private
*/
var $cipher_name_mcrypt = 'arcfour';
/**
* Holds whether performance-optimized $inline_crypt() can/should be used.
*
* @see \phpseclib\Crypt\Base::inline_crypt
* @var mixed
* @access private
*/
var $use_inline_crypt = false; // currently not available
/**
* The Key
*
* @see self::setKey()
* @var string
* @access private
*/
var $key = "\0";
/**
* The Key Stream for decryption and encryption
*
* @see self::setKey()
* @var array
* @access private
*/
var $stream;
/**
* Default Constructor.
*
* Determines whether or not the mcrypt extension should be used.
*
* @see \phpseclib\Crypt\Base::__construct()
* @return \phpseclib\Crypt\RC4
* @access public
*/
function __construct()
{
parent::__construct(Base::MODE_STREAM);
}
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
*
* @see \phpseclib\Crypt\Base::__construct()
* @param int $engine
* @access public
* @return bool
*/
function isValidEngine($engine)
{
if ($engine == Base::ENGINE_OPENSSL) {
if (version_compare(PHP_VERSION, '5.3.7') >= 0) {
$this->cipher_name_openssl = 'rc4-40';
} else {
switch (strlen($this->key)) {
case 5:
$this->cipher_name_openssl = 'rc4-40';
break;
case 8:
$this->cipher_name_openssl = 'rc4-64';
break;
case 16:
$this->cipher_name_openssl = 'rc4';
break;
default:
return false;
}
}
}
return parent::isValidEngine($engine);
}
/**
* Dummy function.
*
* Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1].
* If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before
* calling setKey().
*
* [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol,
* the IV's are relatively easy to predict, an attack described by
* {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir}
* can be used to quickly guess at the rest of the key. The following links elaborate:
*
* {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
* {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
*
* @param string $iv
* @see self::setKey()
* @access public
*/
function setIV($iv)
{
}
/**
* Sets the key length
*
* Keys can be between 1 and 256 bytes long.
*
* @access public
* @param int $length
*/
function setKeyLength($length)
{
if ($length < 8) {
$this->key_length = 1;
} elseif ($length > 2048) {
$this->key_length = 256;
} else {
$this->key_length = $length >> 3;
}
parent::setKeyLength($length);
}
/**
* Encrypts a message.
*
* @see \phpseclib\Crypt\Base::decrypt()
* @see self::_crypt()
* @access public
* @param string $plaintext
* @return string $ciphertext
*/
function encrypt($plaintext)
{
if ($this->engine != Base::ENGINE_INTERNAL) {
return parent::encrypt($plaintext);
}
return $this->_crypt($plaintext, self::ENCRYPT);
}
/**
* Decrypts a message.
*
* $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
* At least if the continuous buffer is disabled.
*
* @see \phpseclib\Crypt\Base::encrypt()
* @see self::_crypt()
* @access public
* @param string $ciphertext
* @return string $plaintext
*/
function decrypt($ciphertext)
{
if ($this->engine != Base::ENGINE_INTERNAL) {
return parent::decrypt($ciphertext);
}
return $this->_crypt($ciphertext, self::DECRYPT);
}
/**
* Encrypts a block
*
* @access private
* @param string $in
*/
function _encryptBlock($in)
{
// RC4 does not utilize this method
}
/**
* Decrypts a block
*
* @access private
* @param string $in
*/
function _decryptBlock($in)
{
// RC4 does not utilize this method
}
/**
* Setup the key (expansion)
*
* @see \phpseclib\Crypt\Base::_setupKey()
* @access private
*/
function _setupKey()
{
$key = $this->key;
$keyLength = strlen($key);
$keyStream = range(0, 255);
$j = 0;
for ($i = 0; $i < 256; $i++) {
$j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255;
$temp = $keyStream[$i];
$keyStream[$i] = $keyStream[$j];
$keyStream[$j] = $temp;
}
$this->stream = array();
$this->stream[self::DECRYPT] = $this->stream[self::ENCRYPT] = array(
0, // index $i
0, // index $j
$keyStream
);
}
/**
* Encrypts or decrypts a message.
*
* @see self::encrypt()
* @see self::decrypt()
* @access private
* @param string $text
* @param int $mode
* @return string $text
*/
function _crypt($text, $mode)
{
if ($this->changed) {
$this->_setup();
$this->changed = false;
}
$stream = &$this->stream[$mode];
if ($this->continuousBuffer) {
$i = &$stream[0];
$j = &$stream[1];
$keyStream = &$stream[2];
} else {
$i = $stream[0];
$j = $stream[1];
$keyStream = $stream[2];
}
$len = strlen($text);
for ($k = 0; $k < $len; ++$k) {
$i = ($i + 1) & 255;
$ksi = $keyStream[$i];
$j = ($j + $ksi) & 255;
$ksj = $keyStream[$j];
$keyStream[$i] = $ksj;
$keyStream[$j] = $ksi;
$text[$k] = $text[$k] ^ chr($keyStream[($ksj + $ksi) & 255]);
}
return $text;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,334 +1,270 @@
<?php
/**
* Random Number Generator
*
* The idea behind this function is that it can be easily replaced with your own crypt_random_string()
* function. eg. maybe you have a better source of entropy for creating the initial states or whatever.
*
* PHP versions 4 and 5
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/Random.php';
*
* echo bin2hex(crypt_random_string(8));
* ?>
* </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 Crypt
* @package Crypt_Random
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
// laravel is a PHP framework that utilizes phpseclib. laravel workbenches may, independently,
// have phpseclib as a requirement as well. if you're developing such a program you may encounter
// a "Cannot redeclare crypt_random_string()" error.
if (!function_exists('crypt_random_string')) {
/**
* "Is Windows" test
*
* @access private
*/
define('CRYPT_RANDOM_IS_WINDOWS', strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
/**
* Generate a random string.
*
* Although microoptimizations are generally discouraged as they impair readability this function is ripe with
* microoptimizations because this function has the potential of being called a huge number of times.
* eg. for RSA key generation.
*
* @param int $length
* @return string
* @access public
*/
function crypt_random_string($length)
{
if (CRYPT_RANDOM_IS_WINDOWS) {
// method 1. prior to PHP 5.3, mcrypt_create_iv() would call rand() on windows
if (extension_loaded('mcrypt') && version_compare(PHP_VERSION, '5.3.0', '>=')) {
return mcrypt_create_iv($length);
}
// method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was,
// to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4
// openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both
// call php_win32_get_random_bytes():
//
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392
//
// php_win32_get_random_bytes() is defined thusly:
//
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80
//
// we're calling it, all the same, in the off chance that the mcrypt extension is not available
if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
return openssl_random_pseudo_bytes($length);
}
} else {
// method 1. the fastest
if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.0', '>=')) {
return openssl_random_pseudo_bytes($length);
}
// method 2
static $fp = true;
if ($fp === true) {
// warning's will be output unles the error suppression operator is used. errors such as
// "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc.
$fp = @fopen('/dev/urandom', 'rb');
}
if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource()
return fread($fp, $length);
}
// method 3. pretty much does the same thing as method 2 per the following url:
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391
// surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're
// not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir
// restrictions or some such
if (extension_loaded('mcrypt')) {
return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
}
}
// at this point we have no choice but to use a pure-PHP CSPRNG
// cascade entropy across multiple PHP instances by fixing the session and collecting all
// environmental variables, including the previous session data and the current session
// data.
//
// mt_rand seeds itself by looking at the PID and the time, both of which are (relatively)
// easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but
// PHP isn't low level to be able to use those as sources and on a web server there's not likely
// going to be a ton of keyboard or mouse action. web servers do have one thing that we can use
// however, a ton of people visiting the website. obviously you don't want to base your seeding
// soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled
// by the user and (2) this isn't just looking at the data sent by the current user - it's based
// on the data sent by all users. one user requests the page and a hash of their info is saved.
// another user visits the page and the serialization of their data is utilized along with the
// server envirnment stuff and a hash of the previous http request data (which itself utilizes
// a hash of the session data before that). certainly an attacker should be assumed to have
// full control over his own http requests. he, however, is not going to have control over
// everyone's http requests.
static $crypto = false, $v;
if ($crypto === false) {
// save old session data
$old_session_id = session_id();
$old_use_cookies = ini_get('session.use_cookies');
$old_session_cache_limiter = session_cache_limiter();
$_OLD_SESSION = isset($_SESSION) ? $_SESSION : false;
if ($old_session_id != '') {
session_write_close();
}
session_id(1);
ini_set('session.use_cookies', 0);
session_cache_limiter('');
session_start();
$v = $seed = $_SESSION['seed'] = pack('H*', sha1(
(isset($_SERVER) ? phpseclib_safe_serialize($_SERVER) : '') .
(isset($_POST) ? phpseclib_safe_serialize($_POST) : '') .
(isset($_GET) ? phpseclib_safe_serialize($_GET) : '') .
(isset($_COOKIE) ? phpseclib_safe_serialize($_COOKIE) : '') .
phpseclib_safe_serialize($GLOBALS) .
phpseclib_safe_serialize($_SESSION) .
phpseclib_safe_serialize($_OLD_SESSION)
));
if (!isset($_SESSION['count'])) {
$_SESSION['count'] = 0;
}
$_SESSION['count']++;
session_write_close();
// restore old session data
if ($old_session_id != '') {
session_id($old_session_id);
session_start();
ini_set('session.use_cookies', $old_use_cookies);
session_cache_limiter($old_session_cache_limiter);
} else {
if ($_OLD_SESSION !== false) {
$_SESSION = $_OLD_SESSION;
unset($_OLD_SESSION);
} else {
unset($_SESSION);
}
}
// in SSH2 a shared secret and an exchange hash are generated through the key exchange process.
// the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C.
// if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the
// original hash and the current hash. we'll be emulating that. for more info see the following URL:
//
// http://tools.ietf.org/html/rfc4253#section-7.2
//
// see the is_string($crypto) part for an example of how to expand the keys
$key = pack('H*', sha1($seed . 'A'));
$iv = pack('H*', sha1($seed . 'C'));
// ciphers are used as per the nist.gov link below. also, see this link:
//
// http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
switch (true) {
case phpseclib_resolve_include_path('Crypt/AES.php'):
if (!class_exists('Crypt_AES')) {
include_once 'AES.php';
}
$crypto = new Crypt_AES(CRYPT_AES_MODE_CTR);
break;
case phpseclib_resolve_include_path('Crypt/Twofish.php'):
if (!class_exists('Crypt_Twofish')) {
include_once 'Twofish.php';
}
$crypto = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR);
break;
case phpseclib_resolve_include_path('Crypt/Blowfish.php'):
if (!class_exists('Crypt_Blowfish')) {
include_once 'Blowfish.php';
}
$crypto = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR);
break;
case phpseclib_resolve_include_path('Crypt/TripleDES.php'):
if (!class_exists('Crypt_TripleDES')) {
include_once 'TripleDES.php';
}
$crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
break;
case phpseclib_resolve_include_path('Crypt/DES.php'):
if (!class_exists('Crypt_DES')) {
include_once 'DES.php';
}
$crypto = new Crypt_DES(CRYPT_DES_MODE_CTR);
break;
case phpseclib_resolve_include_path('Crypt/RC4.php'):
if (!class_exists('Crypt_RC4')) {
include_once 'RC4.php';
}
$crypto = new Crypt_RC4();
break;
default:
user_error('crypt_random_string requires at least one symmetric cipher be loaded');
return false;
}
$crypto->setKey($key);
$crypto->setIV($iv);
$crypto->enableContinuousBuffer();
}
//return $crypto->encrypt(str_repeat("\0", $length));
// the following is based off of ANSI X9.31:
//
// http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
//
// OpenSSL uses that same standard for it's random numbers:
//
// http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c
// (do a search for "ANS X9.31 A.2.4")
$result = '';
while (strlen($result) < $length) {
$i = $crypto->encrypt(microtime()); // strlen(microtime()) == 21
$r = $crypto->encrypt($i ^ $v); // strlen($v) == 20
$v = $crypto->encrypt($r ^ $i); // strlen($r) == 20
$result.= $r;
}
return substr($result, 0, $length);
}
}
if (!function_exists('phpseclib_safe_serialize')) {
/**
* Safely serialize variables
*
* If a class has a private __sleep() method it'll give a fatal error on PHP 5.2 and earlier.
* PHP 5.3 will emit a warning.
*
* @param mixed $arr
* @access public
*/
function phpseclib_safe_serialize(&$arr)
{
if (is_object($arr)) {
return '';
}
if (!is_array($arr)) {
return serialize($arr);
}
// prevent circular array recursion
if (isset($arr['__phpseclib_marker'])) {
return '';
}
$safearr = array();
$arr['__phpseclib_marker'] = true;
foreach (array_keys($arr) as $key) {
// do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage
if ($key !== '__phpseclib_marker') {
$safearr[$key] = phpseclib_safe_serialize($arr[$key]);
}
}
unset($arr['__phpseclib_marker']);
return serialize($safearr);
}
}
if (!function_exists('phpseclib_resolve_include_path')) {
/**
* Resolve filename against the include path.
*
* Wrapper around stream_resolve_include_path() (which was introduced in
* PHP 5.3.2) with fallback implementation for earlier PHP versions.
*
* @param string $filename
* @return string|false
* @access public
*/
function phpseclib_resolve_include_path($filename)
{
if (function_exists('stream_resolve_include_path')) {
return stream_resolve_include_path($filename);
}
// handle non-relative paths
if (file_exists($filename)) {
return realpath($filename);
}
$paths = PATH_SEPARATOR == ':' ?
preg_split('#(?<!phar):#', get_include_path()) :
explode(PATH_SEPARATOR, get_include_path());
foreach ($paths as $prefix) {
// path's specified in include_path don't always end in /
$ds = substr($prefix, -1) == DIRECTORY_SEPARATOR ? '' : DIRECTORY_SEPARATOR;
$file = $prefix . $ds . $filename;
if (file_exists($file)) {
return realpath($file);
}
}
return false;
}
}
<?php
/**
* Random Number Generator
*
* PHP version 5
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'vendor/autoload.php';
*
* echo bin2hex(\phpseclib\Crypt\Random::string(8));
* ?>
* </code>
*
* @category Crypt
* @package Random
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Crypt;
/**
* Pure-PHP Random Number Generator
*
* @package Random
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Random
{
/**
* Generate a random string.
*
* Although microoptimizations are generally discouraged as they impair readability this function is ripe with
* microoptimizations because this function has the potential of being called a huge number of times.
* eg. for RSA key generation.
*
* @param int $length
* @return string
*/
static function string($length)
{
if (version_compare(PHP_VERSION, '7.0.0', '>=')) {
try {
return \random_bytes($length);
} catch (\Throwable $e) {
// If a sufficient source of randomness is unavailable, random_bytes() will throw an
// object that implements the Throwable interface (Exception, TypeError, Error).
// We don't actually need to do anything here. The string() method should just continue
// as normal. Note, however, that if we don't have a sufficient source of randomness for
// random_bytes(), most of the other calls here will fail too, so we'll end up using
// the PHP implementation.
}
}
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
// 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 (extension_loaded('mcrypt') && function_exists('class_alias')) {
return @mcrypt_create_iv($length);
}
// method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was,
// to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4
// openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both
// call php_win32_get_random_bytes():
//
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392
//
// php_win32_get_random_bytes() is defined thusly:
//
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80
//
// we're calling it, all the same, in the off chance that the mcrypt extension is not available
if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
return openssl_random_pseudo_bytes($length);
}
} else {
// method 1. the fastest
if (extension_loaded('openssl')) {
return openssl_random_pseudo_bytes($length);
}
// method 2
static $fp = true;
if ($fp === true) {
// warning's will be output unles the error suppression operator is used. errors such as
// "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc.
$fp = @fopen('/dev/urandom', 'rb');
}
if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource()
return fread($fp, $length);
}
// method 3. pretty much does the same thing as method 2 per the following url:
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391
// surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're
// not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir
// restrictions or some such
if (extension_loaded('mcrypt')) {
return @mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
}
}
// at this point we have no choice but to use a pure-PHP CSPRNG
// cascade entropy across multiple PHP instances by fixing the session and collecting all
// environmental variables, including the previous session data and the current session
// data.
//
// mt_rand seeds itself by looking at the PID and the time, both of which are (relatively)
// easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but
// PHP isn't low level to be able to use those as sources and on a web server there's not likely
// going to be a ton of keyboard or mouse action. web servers do have one thing that we can use
// however, a ton of people visiting the website. obviously you don't want to base your seeding
// soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled
// by the user and (2) this isn't just looking at the data sent by the current user - it's based
// on the data sent by all users. one user requests the page and a hash of their info is saved.
// another user visits the page and the serialization of their data is utilized along with the
// server envirnment stuff and a hash of the previous http request data (which itself utilizes
// a hash of the session data before that). certainly an attacker should be assumed to have
// full control over his own http requests. he, however, is not going to have control over
// everyone's http requests.
static $crypto = false, $v;
if ($crypto === false) {
// save old session data
$old_session_id = session_id();
$old_use_cookies = ini_get('session.use_cookies');
$old_session_cache_limiter = session_cache_limiter();
$_OLD_SESSION = isset($_SESSION) ? $_SESSION : false;
if ($old_session_id != '') {
session_write_close();
}
session_id(1);
ini_set('session.use_cookies', 0);
session_cache_limiter('');
session_start();
$v = $seed = $_SESSION['seed'] = pack('H*', sha1(
(isset($_SERVER) ? phpseclib_safe_serialize($_SERVER) : '') .
(isset($_POST) ? phpseclib_safe_serialize($_POST) : '') .
(isset($_GET) ? phpseclib_safe_serialize($_GET) : '') .
(isset($_COOKIE) ? phpseclib_safe_serialize($_COOKIE) : '') .
phpseclib_safe_serialize($GLOBALS) .
phpseclib_safe_serialize($_SESSION) .
phpseclib_safe_serialize($_OLD_SESSION)
));
if (!isset($_SESSION['count'])) {
$_SESSION['count'] = 0;
}
$_SESSION['count']++;
session_write_close();
// restore old session data
if ($old_session_id != '') {
session_id($old_session_id);
session_start();
ini_set('session.use_cookies', $old_use_cookies);
session_cache_limiter($old_session_cache_limiter);
} else {
if ($_OLD_SESSION !== false) {
$_SESSION = $_OLD_SESSION;
unset($_OLD_SESSION);
} else {
unset($_SESSION);
}
}
// in SSH2 a shared secret and an exchange hash are generated through the key exchange process.
// the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C.
// if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the
// original hash and the current hash. we'll be emulating that. for more info see the following URL:
//
// http://tools.ietf.org/html/rfc4253#section-7.2
//
// see the is_string($crypto) part for an example of how to expand the keys
$key = pack('H*', sha1($seed . 'A'));
$iv = pack('H*', sha1($seed . 'C'));
// ciphers are used as per the nist.gov link below. also, see this link:
//
// http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
switch (true) {
case class_exists('\phpseclib\Crypt\AES'):
$crypto = new AES(Base::MODE_CTR);
break;
case class_exists('\phpseclib\Crypt\Twofish'):
$crypto = new Twofish(Base::MODE_CTR);
break;
case class_exists('\phpseclib\Crypt\Blowfish'):
$crypto = new Blowfish(Base::MODE_CTR);
break;
case class_exists('\phpseclib\Crypt\TripleDES'):
$crypto = new TripleDES(Base::MODE_CTR);
break;
case class_exists('\phpseclib\Crypt\DES'):
$crypto = new DES(Base::MODE_CTR);
break;
case class_exists('\phpseclib\Crypt\RC4'):
$crypto = new RC4();
break;
default:
user_error(__CLASS__ . ' requires at least one symmetric cipher be loaded');
return false;
}
$crypto->setKey($key);
$crypto->setIV($iv);
$crypto->enableContinuousBuffer();
}
//return $crypto->encrypt(str_repeat("\0", $length));
// the following is based off of ANSI X9.31:
//
// http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
//
// OpenSSL uses that same standard for it's random numbers:
//
// http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c
// (do a search for "ANS X9.31 A.2.4")
$result = '';
while (strlen($result) < $length) {
$i = $crypto->encrypt(microtime()); // strlen(microtime()) == 21
$r = $crypto->encrypt($i ^ $v); // strlen($v) == 20
$v = $crypto->encrypt($r ^ $i); // strlen($r) == 20
$result.= $r;
}
return substr($result, 0, $length);
}
}
if (!function_exists('phpseclib_safe_serialize')) {
/**
* Safely serialize variables
*
* If a class has a private __sleep() method it'll give a fatal error on PHP 5.2 and earlier.
* PHP 5.3 will emit a warning.
*
* @param mixed $arr
* @access public
*/
function phpseclib_safe_serialize(&$arr)
{
if (is_object($arr)) {
return '';
}
if (!is_array($arr)) {
return serialize($arr);
}
// prevent circular array recursion
if (isset($arr['__phpseclib_marker'])) {
return '';
}
$safearr = array();
$arr['__phpseclib_marker'] = true;
foreach (array_keys($arr) as $key) {
// do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage
if ($key !== '__phpseclib_marker') {
$safearr[$key] = phpseclib_safe_serialize($arr[$key]);
}
}
unset($arr['__phpseclib_marker']);
return serialize($safearr);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,505 +1,460 @@
<?php
/**
* Pure-PHP implementation of Triple DES.
*
* Uses mcrypt, if available, and an internal implementation, otherwise. Operates in the EDE3 mode (encrypt-decrypt-encrypt).
*
* PHP versions 4 and 5
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'Crypt/TripleDES.php';
*
* $des = new Crypt_TripleDES();
*
* $des->setKey('abcdefghijklmnopqrstuvwx');
*
* $size = 10 * 1024;
* $plaintext = '';
* for ($i = 0; $i < $size; $i++) {
* $plaintext.= 'a';
* }
*
* echo $des->decrypt($des->encrypt($plaintext));
* ?>
* </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 Crypt
* @package Crypt_TripleDES
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_DES
*/
if (!class_exists('Crypt_DES')) {
include_once 'DES.php';
}
/**#@+
* @access public
* @see self::Crypt_TripleDES()
*/
/**
* Encrypt / decrypt using inner chaining
*
* Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (CRYPT_DES_MODE_CBC3).
*/
define('CRYPT_MODE_3CBC', -2);
/**
* BC version of the above.
*/
define('CRYPT_DES_MODE_3CBC', -2);
/**
* Encrypt / decrypt using outer chaining
*
* Outer chaining is used by SSH-2 and when the mode is set to CRYPT_DES_MODE_CBC.
*/
define('CRYPT_MODE_CBC3', CRYPT_MODE_CBC);
/**
* BC version of the above.
*/
define('CRYPT_DES_MODE_CBC3', CRYPT_MODE_CBC3);
/**#@-*/
/**
* Pure-PHP implementation of Triple DES.
*
* @package Crypt_TripleDES
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Crypt_TripleDES extends Crypt_DES
{
/**
* Key Length (in bytes)
*
* @see Crypt_TripleDES::setKeyLength()
* @var int
* @access private
*/
var $key_length = 24;
/**
* The default salt used by setPassword()
*
* @see Crypt_Base::password_default_salt
* @see Crypt_Base::setPassword()
* @var string
* @access private
*/
var $password_default_salt = 'phpseclib';
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_DES::const_namespace
* @see Crypt_Base::const_namespace
* @var string
* @access private
*/
var $const_namespace = 'DES';
/**
* The mcrypt specific name of the cipher
*
* @see Crypt_DES::cipher_name_mcrypt
* @see Crypt_Base::cipher_name_mcrypt
* @var string
* @access private
*/
var $cipher_name_mcrypt = 'tripledes';
/**
* Optimizing value while CFB-encrypting
*
* @see Crypt_Base::cfb_init_len
* @var int
* @access private
*/
var $cfb_init_len = 750;
/**
* max possible size of $key
*
* @see self::setKey()
* @see Crypt_DES::setKey()
* @var string
* @access private
*/
var $key_length_max = 24;
/**
* Internal flag whether using CRYPT_DES_MODE_3CBC or not
*
* @var bool
* @access private
*/
var $mode_3cbc;
/**
* The Crypt_DES objects
*
* Used only if $mode_3cbc === true
*
* @var array
* @access private
*/
var $des;
/**
* Default Constructor.
*
* Determines whether or not the mcrypt extension should be used.
*
* $mode could be:
*
* - CRYPT_DES_MODE_ECB
*
* - CRYPT_DES_MODE_CBC
*
* - CRYPT_DES_MODE_CTR
*
* - CRYPT_DES_MODE_CFB
*
* - CRYPT_DES_MODE_OFB
*
* - CRYPT_DES_MODE_3CBC
*
* If not explicitly set, CRYPT_DES_MODE_CBC will be used.
*
* @see Crypt_DES::Crypt_DES()
* @see Crypt_Base::Crypt_Base()
* @param int $mode
* @access public
*/
function Crypt_TripleDES($mode = CRYPT_MODE_CBC)
{
switch ($mode) {
// In case of CRYPT_DES_MODE_3CBC, we init as CRYPT_DES_MODE_CBC
// and additional flag us internally as 3CBC
case CRYPT_DES_MODE_3CBC:
parent::Crypt_Base(CRYPT_MODE_CBC);
$this->mode_3cbc = true;
// This three $des'es will do the 3CBC work (if $key > 64bits)
$this->des = array(
new Crypt_DES(CRYPT_MODE_CBC),
new Crypt_DES(CRYPT_MODE_CBC),
new Crypt_DES(CRYPT_MODE_CBC),
);
// we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects
$this->des[0]->disablePadding();
$this->des[1]->disablePadding();
$this->des[2]->disablePadding();
break;
// If not 3CBC, we init as usual
default:
parent::Crypt_Base($mode);
}
}
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see Crypt_Base::Crypt_Base()
* @param int $engine
* @access public
* @return bool
*/
function isValidEngine($engine)
{
if ($engine == CRYPT_ENGINE_OPENSSL) {
$this->cipher_name_openssl_ecb = 'des-ede3';
$mode = $this->_openssl_translate_mode();
$this->cipher_name_openssl = $mode == 'ecb' ? 'des-ede3' : 'des-ede3-' . $mode;
}
return parent::isValidEngine($engine);
}
/**
* Sets the initialization vector. (optional)
*
* SetIV is not required when CRYPT_DES_MODE_ECB is being used. If not explicitly set, it'll be assumed
* to be all zero's.
*
* @see Crypt_Base::setIV()
* @access public
* @param string $iv
*/
function setIV($iv)
{
parent::setIV($iv);
if ($this->mode_3cbc) {
$this->des[0]->setIV($iv);
$this->des[1]->setIV($iv);
$this->des[2]->setIV($iv);
}
}
/**
* Sets the key length.
*
* Valid key lengths are 64, 128 and 192
*
* @see Crypt_Base:setKeyLength()
* @access public
* @param int $length
*/
function setKeyLength($length)
{
$length >>= 3;
switch (true) {
case $length <= 8:
$this->key_length = 8;
break;
case $length <= 16:
$this->key_length = 16;
break;
default:
$this->key_length = 24;
}
parent::setKeyLength($length);
}
/**
* Sets the key.
*
* Keys can be of any length. Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or
* 192-bit (eg. strlen($key) == 24) keys. This function pads and truncates $key as appropriate.
*
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
*
* If the key is not explicitly set, it'll be assumed to be all null bytes.
*
* @access public
* @see Crypt_DES::setKey()
* @see Crypt_Base::setKey()
* @param string $key
*/
function setKey($key)
{
$length = $this->explicit_key_length ? $this->key_length : strlen($key);
if ($length > 8) {
$key = str_pad(substr($key, 0, 24), 24, chr(0));
// if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
// http://php.net/function.mcrypt-encrypt#47973
$key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
} else {
$key = str_pad($key, 8, chr(0));
}
parent::setKey($key);
// And in case of CRYPT_DES_MODE_3CBC:
// if key <= 64bits we not need the 3 $des to work,
// because we will then act as regular DES-CBC with just a <= 64bit key.
// So only if the key > 64bits (> 8 bytes) we will call setKey() for the 3 $des.
if ($this->mode_3cbc && $length > 8) {
$this->des[0]->setKey(substr($key, 0, 8));
$this->des[1]->setKey(substr($key, 8, 8));
$this->des[2]->setKey(substr($key, 16, 8));
}
}
/**
* Encrypts a message.
*
* @see Crypt_Base::encrypt()
* @access public
* @param string $plaintext
* @return string $cipertext
*/
function encrypt($plaintext)
{
// parent::en/decrypt() is able to do all the work for all modes and keylengths,
// except for: CRYPT_MODE_3CBC (inner chaining CBC) with a key > 64bits
// if the key is smaller then 8, do what we'd normally do
if ($this->mode_3cbc && strlen($this->key) > 8) {
return $this->des[2]->encrypt(
$this->des[1]->decrypt(
$this->des[0]->encrypt(
$this->_pad($plaintext)
)
)
);
}
return parent::encrypt($plaintext);
}
/**
* Decrypts a message.
*
* @see Crypt_Base::decrypt()
* @access public
* @param string $ciphertext
* @return string $plaintext
*/
function decrypt($ciphertext)
{
if ($this->mode_3cbc && strlen($this->key) > 8) {
return $this->_unpad(
$this->des[0]->decrypt(
$this->des[1]->encrypt(
$this->des[2]->decrypt(
str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, "\0")
)
)
)
);
}
return parent::decrypt($ciphertext);
}
/**
* Treat consecutive "packets" as if they are a continuous buffer.
*
* Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
* will yield different outputs:
*
* <code>
* echo $des->encrypt(substr($plaintext, 0, 8));
* echo $des->encrypt(substr($plaintext, 8, 8));
* </code>
* <code>
* echo $des->encrypt($plaintext);
* </code>
*
* The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
* another, as demonstrated with the following:
*
* <code>
* $des->encrypt(substr($plaintext, 0, 8));
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
* </code>
* <code>
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
* </code>
*
* With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
* outputs. The reason is due to the fact that the initialization vector's change after every encryption /
* decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
*
* Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
* encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
* continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
* however, they are also less intuitive and more likely to cause you problems.
*
* @see Crypt_Base::enableContinuousBuffer()
* @see self::disableContinuousBuffer()
* @access public
*/
function enableContinuousBuffer()
{
parent::enableContinuousBuffer();
if ($this->mode_3cbc) {
$this->des[0]->enableContinuousBuffer();
$this->des[1]->enableContinuousBuffer();
$this->des[2]->enableContinuousBuffer();
}
}
/**
* Treat consecutive packets as if they are a discontinuous buffer.
*
* The default behavior.
*
* @see Crypt_Base::disableContinuousBuffer()
* @see self::enableContinuousBuffer()
* @access public
*/
function disableContinuousBuffer()
{
parent::disableContinuousBuffer();
if ($this->mode_3cbc) {
$this->des[0]->disableContinuousBuffer();
$this->des[1]->disableContinuousBuffer();
$this->des[2]->disableContinuousBuffer();
}
}
/**
* Creates the key schedule
*
* @see Crypt_DES::_setupKey()
* @see Crypt_Base::_setupKey()
* @access private
*/
function _setupKey()
{
switch (true) {
// if $key <= 64bits we configure our internal pure-php cipher engine
// to act as regular [1]DES, not as 3DES. mcrypt.so::tripledes does the same.
case strlen($this->key) <= 8:
$this->des_rounds = 1;
break;
// otherwise, if $key > 64bits, we configure our engine to work as 3DES.
default:
$this->des_rounds = 3;
// (only) if 3CBC is used we have, of course, to setup the $des[0-2] keys also separately.
if ($this->mode_3cbc) {
$this->des[0]->_setupKey();
$this->des[1]->_setupKey();
$this->des[2]->_setupKey();
// because $des[0-2] will, now, do all the work we can return here
// not need unnecessary stress parent::_setupKey() with our, now unused, $key.
return;
}
}
// setup our key
parent::_setupKey();
}
/**
* Sets the internal crypt engine
*
* @see Crypt_Base::Crypt_Base()
* @see Crypt_Base::setPreferredEngine()
* @param int $engine
* @access public
* @return int
*/
function setPreferredEngine($engine)
{
if ($this->mode_3cbc) {
$this->des[0]->setPreferredEngine($engine);
$this->des[1]->setPreferredEngine($engine);
$this->des[2]->setPreferredEngine($engine);
}
return parent::setPreferredEngine($engine);
}
}
<?php
/**
* Pure-PHP implementation of Triple DES.
*
* Uses mcrypt, if available, and an internal implementation, otherwise. Operates in the EDE3 mode (encrypt-decrypt-encrypt).
*
* PHP version 5
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'vendor/autoload.php';
*
* $des = new \phpseclib\Crypt\TripleDES();
*
* $des->setKey('abcdefghijklmnopqrstuvwx');
*
* $size = 10 * 1024;
* $plaintext = '';
* for ($i = 0; $i < $size; $i++) {
* $plaintext.= 'a';
* }
*
* echo $des->decrypt($des->encrypt($plaintext));
* ?>
* </code>
*
* @category Crypt
* @package TripleDES
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Crypt;
/**
* Pure-PHP implementation of Triple DES.
*
* @package TripleDES
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class TripleDES extends DES
{
/**
* Encrypt / decrypt using inner chaining
*
* Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (self::MODE_CBC3).
*/
const MODE_3CBC = -2;
/**
* Encrypt / decrypt using outer chaining
*
* Outer chaining is used by SSH-2 and when the mode is set to \phpseclib\Crypt\Base::MODE_CBC.
*/
const MODE_CBC3 = Base::MODE_CBC;
/**
* Key Length (in bytes)
*
* @see \phpseclib\Crypt\TripleDES::setKeyLength()
* @var int
* @access private
*/
var $key_length = 24;
/**
* The default salt used by setPassword()
*
* @see \phpseclib\Crypt\Base::password_default_salt
* @see \phpseclib\Crypt\Base::setPassword()
* @var string
* @access private
*/
var $password_default_salt = 'phpseclib';
/**
* The mcrypt specific name of the cipher
*
* @see \phpseclib\Crypt\DES::cipher_name_mcrypt
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt
* @var string
* @access private
*/
var $cipher_name_mcrypt = 'tripledes';
/**
* Optimizing value while CFB-encrypting
*
* @see \phpseclib\Crypt\Base::cfb_init_len
* @var int
* @access private
*/
var $cfb_init_len = 750;
/**
* max possible size of $key
*
* @see self::setKey()
* @see \phpseclib\Crypt\DES::setKey()
* @var string
* @access private
*/
var $key_length_max = 24;
/**
* Internal flag whether using self::MODE_3CBC or not
*
* @var bool
* @access private
*/
var $mode_3cbc;
/**
* The \phpseclib\Crypt\DES objects
*
* Used only if $mode_3cbc === true
*
* @var array
* @access private
*/
var $des;
/**
* Default Constructor.
*
* Determines whether or not the mcrypt extension should be used.
*
* $mode could be:
*
* - \phpseclib\Crypt\Base::MODE_ECB
*
* - \phpseclib\Crypt\Base::MODE_CBC
*
* - \phpseclib\Crypt\Base::MODE_CTR
*
* - \phpseclib\Crypt\Base::MODE_CFB
*
* - \phpseclib\Crypt\Base::MODE_OFB
*
* - \phpseclib\Crypt\TripleDES::MODE_3CBC
*
* If not explicitly set, \phpseclib\Crypt\Base::MODE_CBC will be used.
*
* @see \phpseclib\Crypt\DES::__construct()
* @see \phpseclib\Crypt\Base::__construct()
* @param int $mode
* @access public
*/
function __construct($mode = Base::MODE_CBC)
{
switch ($mode) {
// In case of self::MODE_3CBC, we init as CRYPT_DES_MODE_CBC
// and additional flag us internally as 3CBC
case self::MODE_3CBC:
parent::__construct(Base::MODE_CBC);
$this->mode_3cbc = true;
// This three $des'es will do the 3CBC work (if $key > 64bits)
$this->des = array(
new DES(Base::MODE_CBC),
new DES(Base::MODE_CBC),
new DES(Base::MODE_CBC),
);
// we're going to be doing the padding, ourselves, so disable it in the \phpseclib\Crypt\DES objects
$this->des[0]->disablePadding();
$this->des[1]->disablePadding();
$this->des[2]->disablePadding();
break;
// If not 3CBC, we init as usual
default:
parent::__construct($mode);
}
}
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
*
* @see \phpseclib\Crypt\Base::__construct()
* @param int $engine
* @access public
* @return bool
*/
function isValidEngine($engine)
{
if ($engine == self::ENGINE_OPENSSL) {
$this->cipher_name_openssl_ecb = 'des-ede3';
$mode = $this->_openssl_translate_mode();
$this->cipher_name_openssl = $mode == 'ecb' ? 'des-ede3' : 'des-ede3-' . $mode;
}
return parent::isValidEngine($engine);
}
/**
* Sets the initialization vector. (optional)
*
* SetIV is not required when \phpseclib\Crypt\Base::MODE_ECB is being used. If not explicitly set, it'll be assumed
* to be all zero's.
*
* @see \phpseclib\Crypt\Base::setIV()
* @access public
* @param string $iv
*/
function setIV($iv)
{
parent::setIV($iv);
if ($this->mode_3cbc) {
$this->des[0]->setIV($iv);
$this->des[1]->setIV($iv);
$this->des[2]->setIV($iv);
}
}
/**
* Sets the key length.
*
* Valid key lengths are 64, 128 and 192
*
* @see \phpseclib\Crypt\Base:setKeyLength()
* @access public
* @param int $length
*/
function setKeyLength($length)
{
$length >>= 3;
switch (true) {
case $length <= 8:
$this->key_length = 8;
break;
case $length <= 16:
$this->key_length = 16;
break;
default:
$this->key_length = 24;
}
parent::setKeyLength($length);
}
/**
* Sets the key.
*
* Keys can be of any length. Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or
* 192-bit (eg. strlen($key) == 24) keys. This function pads and truncates $key as appropriate.
*
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
*
* If the key is not explicitly set, it'll be assumed to be all null bytes.
*
* @access public
* @see \phpseclib\Crypt\DES::setKey()
* @see \phpseclib\Crypt\Base::setKey()
* @param string $key
*/
function setKey($key)
{
$length = $this->explicit_key_length ? $this->key_length : strlen($key);
if ($length > 8) {
$key = str_pad(substr($key, 0, 24), 24, chr(0));
// if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
// http://php.net/function.mcrypt-encrypt#47973
$key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
} else {
$key = str_pad($key, 8, chr(0));
}
parent::setKey($key);
// And in case of self::MODE_3CBC:
// if key <= 64bits we not need the 3 $des to work,
// because we will then act as regular DES-CBC with just a <= 64bit key.
// So only if the key > 64bits (> 8 bytes) we will call setKey() for the 3 $des.
if ($this->mode_3cbc && $length > 8) {
$this->des[0]->setKey(substr($key, 0, 8));
$this->des[1]->setKey(substr($key, 8, 8));
$this->des[2]->setKey(substr($key, 16, 8));
}
}
/**
* Encrypts a message.
*
* @see \phpseclib\Crypt\Base::encrypt()
* @access public
* @param string $plaintext
* @return string $cipertext
*/
function encrypt($plaintext)
{
// parent::en/decrypt() is able to do all the work for all modes and keylengths,
// except for: self::MODE_3CBC (inner chaining CBC) with a key > 64bits
// if the key is smaller then 8, do what we'd normally do
if ($this->mode_3cbc && strlen($this->key) > 8) {
return $this->des[2]->encrypt(
$this->des[1]->decrypt(
$this->des[0]->encrypt(
$this->_pad($plaintext)
)
)
);
}
return parent::encrypt($plaintext);
}
/**
* Decrypts a message.
*
* @see \phpseclib\Crypt\Base::decrypt()
* @access public
* @param string $ciphertext
* @return string $plaintext
*/
function decrypt($ciphertext)
{
if ($this->mode_3cbc && strlen($this->key) > 8) {
return $this->_unpad(
$this->des[0]->decrypt(
$this->des[1]->encrypt(
$this->des[2]->decrypt(
str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, "\0")
)
)
)
);
}
return parent::decrypt($ciphertext);
}
/**
* Treat consecutive "packets" as if they are a continuous buffer.
*
* Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
* will yield different outputs:
*
* <code>
* echo $des->encrypt(substr($plaintext, 0, 8));
* echo $des->encrypt(substr($plaintext, 8, 8));
* </code>
* <code>
* echo $des->encrypt($plaintext);
* </code>
*
* The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
* another, as demonstrated with the following:
*
* <code>
* $des->encrypt(substr($plaintext, 0, 8));
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
* </code>
* <code>
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
* </code>
*
* With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
* outputs. The reason is due to the fact that the initialization vector's change after every encryption /
* decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
*
* Put another way, when the continuous buffer is enabled, the state of the \phpseclib\Crypt\DES() object changes after each
* encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
* continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
* however, they are also less intuitive and more likely to cause you problems.
*
* @see \phpseclib\Crypt\Base::enableContinuousBuffer()
* @see self::disableContinuousBuffer()
* @access public
*/
function enableContinuousBuffer()
{
parent::enableContinuousBuffer();
if ($this->mode_3cbc) {
$this->des[0]->enableContinuousBuffer();
$this->des[1]->enableContinuousBuffer();
$this->des[2]->enableContinuousBuffer();
}
}
/**
* Treat consecutive packets as if they are a discontinuous buffer.
*
* The default behavior.
*
* @see \phpseclib\Crypt\Base::disableContinuousBuffer()
* @see self::enableContinuousBuffer()
* @access public
*/
function disableContinuousBuffer()
{
parent::disableContinuousBuffer();
if ($this->mode_3cbc) {
$this->des[0]->disableContinuousBuffer();
$this->des[1]->disableContinuousBuffer();
$this->des[2]->disableContinuousBuffer();
}
}
/**
* Creates the key schedule
*
* @see \phpseclib\Crypt\DES::_setupKey()
* @see \phpseclib\Crypt\Base::_setupKey()
* @access private
*/
function _setupKey()
{
switch (true) {
// if $key <= 64bits we configure our internal pure-php cipher engine
// to act as regular [1]DES, not as 3DES. mcrypt.so::tripledes does the same.
case strlen($this->key) <= 8:
$this->des_rounds = 1;
break;
// otherwise, if $key > 64bits, we configure our engine to work as 3DES.
default:
$this->des_rounds = 3;
// (only) if 3CBC is used we have, of course, to setup the $des[0-2] keys also separately.
if ($this->mode_3cbc) {
$this->des[0]->_setupKey();
$this->des[1]->_setupKey();
$this->des[2]->_setupKey();
// because $des[0-2] will, now, do all the work we can return here
// not need unnecessary stress parent::_setupKey() with our, now unused, $key.
return;
}
}
// setup our key
parent::_setupKey();
}
/**
* Sets the internal crypt engine
*
* @see \phpseclib\Crypt\Base::__construct()
* @see \phpseclib\Crypt\Base::setPreferredEngine()
* @param int $engine
* @access public
* @return int
*/
function setPreferredEngine($engine)
{
if ($this->mode_3cbc) {
$this->des[0]->setPreferredEngine($engine);
$this->des[1]->setPreferredEngine($engine);
$this->des[2]->setPreferredEngine($engine);
}
return parent::setPreferredEngine($engine);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,47 @@
<?php
/**
* Pure-PHP ASN.1 Parser
*
* PHP version 5
*
* @category File
* @package ASN1
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2012 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\File\ASN1;
/**
* ASN.1 Element
*
* Bypass normal encoding rules in phpseclib\File\ASN1::encodeDER()
*
* @package ASN1
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Element
{
/**
* Raw element value
*
* @var string
* @access private
*/
var $element;
/**
* Constructor
*
* @param string $encoded
* @return \phpseclib\File\ASN1\Element
* @access public
*/
function __construct($encoded)
{
$this->element = $encoded;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,360 +1,337 @@
<?php
/**
* 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 2010 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**#@+
* @access public
* @see self::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 self::_send()
* @see self::_receive()
*/
/**
* SSH1 is being used.
*/
define('NET_SCP_SSH1', 1);
/**
* SSH2 is being used.
*/
define('NET_SCP_SSH2', 2);
/**#@-*/
/**
* Pure-PHP implementations of SCP.
*
* @package Net_SCP
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Net_SCP
{
/**
* SSH Object
*
* @var object
* @access private
*/
var $ssh;
/**
* Packet Size
*
* @var int
* @access private
*/
var $packet_size;
/**
* Mode
*
* @var int
* @access private
*/
var $mode;
/**
* Default Constructor.
*
* Connects to an SSH server
*
* @param string $host
* @param int $port
* @param int $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_SCP_LOCAL_FILE will change the above behavior. With NET_SCP_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 int $mode
* @param callable $callback
* @return bool
* @access public
*/
function put($remote_file, $data, $mode = NET_SCP_STRING, $callback = null)
{
if (!isset($this->ssh)) {
return false;
}
if (!$this->ssh->exec('scp -t ' . escapeshellarg($remote_file), false)) { // -t = to
return false;
}
$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] - 4;
}
$remote_file = basename($remote_file);
if ($mode == NET_SCP_STRING) {
$size = strlen($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);
}
$this->_send('C0644 ' . $size . ' ' . $remote_file . "\n");
$temp = $this->_receive();
if ($temp !== chr(0)) {
return false;
}
$sent = 0;
while ($sent < $size) {
$temp = $mode & NET_SCP_STRING ? substr($data, $sent, $this->packet_size) : fread($fp, $this->packet_size);
$this->_send($temp);
$sent+= strlen($temp);
if (is_callable($callback)) {
call_user_func($callback, $sent);
}
}
$this->_close();
if ($mode != NET_SCP_STRING) {
fclose($fp);
}
return true;
}
/**
* 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 string $local_file
* @return mixed
* @access public
*/
function get($remote_file, $local_file = false)
{
if (!isset($this->ssh)) {
return false;
}
if (!$this->ssh->exec('scp -f ' . escapeshellarg($remote_file), false)) { // -f = from
return false;
}
$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, true);
break;
case NET_SCP_SSH1:
$this->ssh->disconnect();
}
}
}
<?php
/**
* Pure-PHP implementation of SCP.
*
* PHP version 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 'vendor/autoload.php';
*
* $ssh = new \phpseclib\Net\SSH2('www.domain.tld');
* if (!$ssh->login('username', 'password')) {
* exit('bad login');
* }
* $scp = new \phpseclib\Net\SCP($ssh);
*
* $scp->put('abcd', str_repeat('x', 1024*1024));
* ?>
* </code>
*
* @category Net
* @package SCP
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2010 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Net;
/**
* Pure-PHP implementations of SCP.
*
* @package SCP
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class SCP
{
/**#@+
* @access public
* @see \phpseclib\Net\SCP::put()
*/
/**
* Reads data from a local file.
*/
const SOURCE_LOCAL_FILE = 1;
/**
* Reads data from a string.
*/
const SOURCE_STRING = 2;
/**#@-*/
/**#@+
* @access private
* @see \phpseclib\Net\SCP::_send()
* @see \phpseclib\Net\SCP::_receive()
*/
/**
* SSH1 is being used.
*/
const MODE_SSH1 = 1;
/**
* SSH2 is being used.
*/
const MODE_SSH2 = 2;
/**#@-*/
/**
* SSH Object
*
* @var object
* @access private
*/
var $ssh;
/**
* Packet Size
*
* @var int
* @access private
*/
var $packet_size;
/**
* Mode
*
* @var int
* @access private
*/
var $mode;
/**
* Default Constructor.
*
* Connects to an SSH server
*
* @param \phpseclib\Net\SSH1|\phpseclib\Net\SSH2 $ssh
* @return \phpseclib\Net\SCP
* @access public
*/
function __construct($ssh)
{
if ($ssh instanceof SSH2) {
$this->mode = self::MODE_SSH2;
} elseif ($ssh instanceof SSH1) {
$this->packet_size = 50000;
$this->mode = self::MODE_SSH1;
} else {
return;
}
$this->ssh = $ssh;
}
/**
* Uploads a file to the SCP server.
*
* By default, \phpseclib\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 \phpseclib\Net\SCP::get(), you will get a file, twelve bytes
* long, containing 'filename.ext' as its contents.
*
* Setting $mode to self::SOURCE_LOCAL_FILE will change the above behavior. With self::SOURCE_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 int $mode
* @param callable $callback
* @return bool
* @access public
*/
function put($remote_file, $data, $mode = self::SOURCE_STRING, $callback = null)
{
if (!isset($this->ssh)) {
return false;
}
if (!$this->ssh->exec('scp -t ' . escapeshellarg($remote_file), false)) { // -t = to
return false;
}
$temp = $this->_receive();
if ($temp !== chr(0)) {
return false;
}
if ($this->mode == self::MODE_SSH2) {
$this->packet_size = $this->ssh->packet_size_client_to_server[SSH2::CHANNEL_EXEC] - 4;
}
$remote_file = basename($remote_file);
if ($mode == self::SOURCE_STRING) {
$size = strlen($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);
}
$this->_send('C0644 ' . $size . ' ' . $remote_file . "\n");
$temp = $this->_receive();
if ($temp !== chr(0)) {
return false;
}
$sent = 0;
while ($sent < $size) {
$temp = $mode & self::SOURCE_STRING ? substr($data, $sent, $this->packet_size) : fread($fp, $this->packet_size);
$this->_send($temp);
$sent+= strlen($temp);
if (is_callable($callback)) {
call_user_func($callback, $sent);
}
}
$this->_close();
if ($mode != self::SOURCE_STRING) {
fclose($fp);
}
return true;
}
/**
* 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 string $local_file
* @return mixed
* @access public
*/
function get($remote_file, $local_file = false)
{
if (!isset($this->ssh)) {
return false;
}
if (!$this->ssh->exec('scp -f ' . escapeshellarg($remote_file), false)) { // -f = from
return false;
}
$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 self::MODE_SSH2:
$this->ssh->_send_channel_packet(SSH2::CHANNEL_EXEC, $data);
break;
case self::MODE_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 self::MODE_SSH2:
return $this->ssh->_get_channel_packet(SSH2::CHANNEL_EXEC, true);
case self::MODE_SSH1:
if (!$this->ssh->bitmap) {
return false;
}
while (true) {
$response = $this->ssh->_get_binary_packet();
switch ($response[SSH1::RESPONSE_TYPE]) {
case NET_SSH1_SMSG_STDOUT_DATA:
if (strlen($response[SSH1::RESPONSE_DATA]) < 4) {
return false;
}
extract(unpack('Nlength', $response[SSH1::RESPONSE_DATA]));
return $this->ssh->_string_shift($response[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 self::MODE_SSH2:
$this->ssh->_close_channel(SSH2::CHANNEL_EXEC, true);
break;
case self::MODE_SSH1:
$this->ssh->disconnect();
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,463 +1,308 @@
<?php
/**
* Pure-PHP ssh-agent client.
*
* PHP versions 4 and 5
*
* Here are some examples of how to use this library:
* <code>
* <?php
* include 'System/SSH/Agent.php';
* include 'Net/SSH2.php';
*
* $agent = new System_SSH_Agent();
*
* $ssh = new Net_SSH2('www.domain.tld');
* if (!$ssh->login('username', $agent)) {
* exit('Login Failed');
* }
*
* echo $ssh->exec('pwd');
* echo $ssh->exec('ls -la');
* ?>
* </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 System
* @package System_SSH_Agent
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2014 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent
*/
/**#@+
* Message numbers
*
* @access private
*/
// to request SSH1 keys you have to use SSH_AGENTC_REQUEST_RSA_IDENTITIES (1)
define('SYSTEM_SSH_AGENTC_REQUEST_IDENTITIES', 11);
// this is the SSH2 response; the SSH1 response is SSH_AGENT_RSA_IDENTITIES_ANSWER (2).
define('SYSTEM_SSH_AGENT_IDENTITIES_ANSWER', 12);
define('SYSTEM_SSH_AGENT_FAILURE', 5);
// the SSH1 request is SSH_AGENTC_RSA_CHALLENGE (3)
define('SYSTEM_SSH_AGENTC_SIGN_REQUEST', 13);
// the SSH1 response is SSH_AGENT_RSA_RESPONSE (4)
define('SYSTEM_SSH_AGENT_SIGN_RESPONSE', 14);
/**@+
* Agent forwarding status
*
* @access private
*/
// no forwarding requested and not active
define('SYSTEM_SSH_AGENT_FORWARD_NONE', 0);
// request agent forwarding when opportune
define('SYSTEM_SSH_AGENT_FORWARD_REQUEST', 1);
// forwarding has been request and is active
define('SYSTEM_SSH_AGENT_FORWARD_ACTIVE', 2);
/**#@-*/
/**
* Pure-PHP ssh-agent client identity object
*
* Instantiation should only be performed by System_SSH_Agent class.
* This could be thought of as implementing an interface that Crypt_RSA
* implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something.
* The methods in this interface would be getPublicKey, setSignatureMode
* and sign since those are the methods phpseclib looks for to perform
* public key authentication.
*
* @package System_SSH_Agent
* @author Jim Wigginton <terrafrost@php.net>
* @access internal
*/
class System_SSH_Agent_Identity
{
/**
* Key Object
*
* @var Crypt_RSA
* @access private
* @see self::getPublicKey()
*/
var $key;
/**
* Key Blob
*
* @var string
* @access private
* @see self::sign()
*/
var $key_blob;
/**
* Socket Resource
*
* @var resource
* @access private
* @see self::sign()
*/
var $fsock;
/**
* Default Constructor.
*
* @param resource $fsock
* @return System_SSH_Agent_Identity
* @access private
*/
function System_SSH_Agent_Identity($fsock)
{
$this->fsock = $fsock;
}
/**
* Set Public Key
*
* Called by System_SSH_Agent::requestIdentities()
*
* @param Crypt_RSA $key
* @access private
*/
function setPublicKey($key)
{
$this->key = $key;
$this->key->setPublicKey();
}
/**
* Set Public Key
*
* Called by System_SSH_Agent::requestIdentities(). The key blob could be extracted from $this->key
* but this saves a small amount of computation.
*
* @param string $key_blob
* @access private
*/
function setPublicKeyBlob($key_blob)
{
$this->key_blob = $key_blob;
}
/**
* Get Public Key
*
* Wrapper for $this->key->getPublicKey()
*
* @param int $format optional
* @return mixed
* @access public
*/
function getPublicKey($format = null)
{
return !isset($format) ? $this->key->getPublicKey() : $this->key->getPublicKey($format);
}
/**
* Set Signature Mode
*
* Doesn't do anything as ssh-agent doesn't let you pick and choose the signature mode. ie.
* ssh-agent's only supported mode is CRYPT_RSA_SIGNATURE_PKCS1
*
* @param int $mode
* @access public
*/
function setSignatureMode($mode)
{
}
/**
* Create a signature
*
* See "2.6.2 Protocol 2 private key signature request"
*
* @param string $message
* @return string
* @access public
*/
function sign($message)
{
// the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE
$packet = pack('CNa*Na*N', SYSTEM_SSH_AGENTC_SIGN_REQUEST, strlen($this->key_blob), $this->key_blob, strlen($message), $message, 0);
$packet = pack('Na*', strlen($packet), $packet);
if (strlen($packet) != fputs($this->fsock, $packet)) {
user_error('Connection closed during signing');
}
$length = current(unpack('N', fread($this->fsock, 4)));
$type = ord(fread($this->fsock, 1));
if ($type != SYSTEM_SSH_AGENT_SIGN_RESPONSE) {
user_error('Unable to retreive signature');
}
$signature_blob = fread($this->fsock, $length - 1);
// the only other signature format defined - ssh-dss - is the same length as ssh-rsa
// the + 12 is for the other various SSH added length fields
return substr($signature_blob, strlen('ssh-rsa') + 12);
}
}
/**
* Pure-PHP ssh-agent client identity factory
*
* requestIdentities() method pumps out System_SSH_Agent_Identity objects
*
* @package System_SSH_Agent
* @author Jim Wigginton <terrafrost@php.net>
* @access internal
*/
class System_SSH_Agent
{
/**
* Socket Resource
*
* @var resource
* @access private
*/
var $fsock;
/**
* Agent forwarding status
*
* @access private
*/
var $forward_status = SYSTEM_SSH_AGENT_FORWARD_NONE;
/**
* Buffer for accumulating forwarded authentication
* agent data arriving on SSH data channel destined
* for agent unix socket
*
* @access private
*/
var $socket_buffer = '';
/**
* Tracking the number of bytes we are expecting
* to arrive for the agent socket on the SSH data
* channel
*/
var $expected_bytes = 0;
/**
* Default Constructor
*
* @return System_SSH_Agent
* @access public
*/
function System_SSH_Agent()
{
switch (true) {
case isset($_SERVER['SSH_AUTH_SOCK']):
$address = $_SERVER['SSH_AUTH_SOCK'];
break;
case isset($_ENV['SSH_AUTH_SOCK']):
$address = $_ENV['SSH_AUTH_SOCK'];
break;
default:
user_error('SSH_AUTH_SOCK not found');
return false;
}
$this->fsock = fsockopen('unix://' . $address, 0, $errno, $errstr);
if (!$this->fsock) {
user_error("Unable to connect to ssh-agent (Error $errno: $errstr)");
}
}
/**
* Request Identities
*
* See "2.5.2 Requesting a list of protocol 2 keys"
* Returns an array containing zero or more System_SSH_Agent_Identity objects
*
* @return array
* @access public
*/
function requestIdentities()
{
if (!$this->fsock) {
return array();
}
$packet = pack('NC', 1, SYSTEM_SSH_AGENTC_REQUEST_IDENTITIES);
if (strlen($packet) != fputs($this->fsock, $packet)) {
user_error('Connection closed while requesting identities');
}
$length = current(unpack('N', fread($this->fsock, 4)));
$type = ord(fread($this->fsock, 1));
if ($type != SYSTEM_SSH_AGENT_IDENTITIES_ANSWER) {
user_error('Unable to request identities');
}
$identities = array();
$keyCount = current(unpack('N', fread($this->fsock, 4)));
for ($i = 0; $i < $keyCount; $i++) {
$length = current(unpack('N', fread($this->fsock, 4)));
$key_blob = fread($this->fsock, $length);
$key_str = 'ssh-rsa ' . base64_encode($key_blob);
$length = current(unpack('N', fread($this->fsock, 4)));
if ($length) {
$key_str.= ' ' . fread($this->fsock, $length);
}
$length = current(unpack('N', substr($key_blob, 0, 4)));
$key_type = substr($key_blob, 4, $length);
switch ($key_type) {
case 'ssh-rsa':
if (!class_exists('Crypt_RSA')) {
include_once 'Crypt/RSA.php';
}
$key = new Crypt_RSA();
$key->loadKey($key_str);
break;
case 'ssh-dss':
// not currently supported
break;
}
// resources are passed by reference by default
if (isset($key)) {
$identity = new System_SSH_Agent_Identity($this->fsock);
$identity->setPublicKey($key);
$identity->setPublicKeyBlob($key_blob);
$identities[] = $identity;
unset($key);
}
}
return $identities;
}
/**
* Signal that agent forwarding should
* be requested when a channel is opened
*
* @param Net_SSH2 $ssh
* @return bool
* @access public
*/
function startSSHForwarding($ssh)
{
if ($this->forward_status == SYSTEM_SSH_AGENT_FORWARD_NONE) {
$this->forward_status = SYSTEM_SSH_AGENT_FORWARD_REQUEST;
}
}
/**
* Request agent forwarding of remote server
*
* @param Net_SSH2 $ssh
* @return bool
* @access private
*/
function _request_forwarding($ssh)
{
$request_channel = $ssh->_get_open_channel();
if ($request_channel === false) {
return false;
}
$packet = pack(
'CNNa*C',
NET_SSH2_MSG_CHANNEL_REQUEST,
$ssh->server_channels[$request_channel],
strlen('auth-agent-req@openssh.com'),
'auth-agent-req@openssh.com',
1
);
$ssh->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_REQUEST;
if (!$ssh->_send_binary_packet($packet)) {
return false;
}
$response = $ssh->_get_channel_packet($request_channel);
if ($response === false) {
return false;
}
$ssh->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_OPEN;
$this->forward_status = SYSTEM_SSH_AGENT_FORWARD_ACTIVE;
return true;
}
/**
* On successful channel open
*
* This method is called upon successful channel
* open to give the SSH Agent an opportunity
* to take further action. i.e. request agent forwarding
*
* @param Net_SSH2 $ssh
* @access private
*/
function _on_channel_open($ssh)
{
if ($this->forward_status == SYSTEM_SSH_AGENT_FORWARD_REQUEST) {
$this->_request_forwarding($ssh);
}
}
/**
* Forward data to SSH Agent and return data reply
*
* @param string $data
* @return data from SSH Agent
* @access private
*/
function _forward_data($data)
{
if ($this->expected_bytes > 0) {
$this->socket_buffer.= $data;
$this->expected_bytes -= strlen($data);
} else {
$agent_data_bytes = current(unpack('N', $data));
$current_data_bytes = strlen($data);
$this->socket_buffer = $data;
if ($current_data_bytes != $agent_data_bytes + 4) {
$this->expected_bytes = ($agent_data_bytes + 4) - $current_data_bytes;
return false;
}
}
if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) {
user_error('Connection closed attempting to forward data to SSH agent');
}
$this->socket_buffer = '';
$this->expected_bytes = 0;
$agent_reply_bytes = current(unpack('N', fread($this->fsock, 4)));
$agent_reply_data = fread($this->fsock, $agent_reply_bytes);
$agent_reply_data = current(unpack('a*', $agent_reply_data));
return pack('Na*', $agent_reply_bytes, $agent_reply_data);
}
}
<?php
/**
* Pure-PHP ssh-agent client.
*
* PHP version 5
*
* Here are some examples of how to use this library:
* <code>
* <?php
* include 'vendor/autoload.php';
*
* $agent = new \phpseclib\System\SSH\Agent();
*
* $ssh = new \phpseclib\Net\SSH2('www.domain.tld');
* if (!$ssh->login('username', $agent)) {
* exit('Login Failed');
* }
*
* echo $ssh->exec('pwd');
* echo $ssh->exec('ls -la');
* ?>
* </code>
*
* @category System
* @package SSH\Agent
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2014 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent
*/
namespace phpseclib\System\SSH;
use phpseclib\Crypt\RSA;
use phpseclib\System\SSH\Agent\Identity;
/**
* Pure-PHP ssh-agent client identity factory
*
* requestIdentities() method pumps out \phpseclib\System\SSH\Agent\Identity objects
*
* @package SSH\Agent
* @author Jim Wigginton <terrafrost@php.net>
* @access internal
*/
class Agent
{
/**#@+
* Message numbers
*
* @access private
*/
// to request SSH1 keys you have to use SSH_AGENTC_REQUEST_RSA_IDENTITIES (1)
const SSH_AGENTC_REQUEST_IDENTITIES = 11;
// this is the SSH2 response; the SSH1 response is SSH_AGENT_RSA_IDENTITIES_ANSWER (2).
const SSH_AGENT_IDENTITIES_ANSWER = 12;
// the SSH1 request is SSH_AGENTC_RSA_CHALLENGE (3)
const SSH_AGENTC_SIGN_REQUEST = 13;
// the SSH1 response is SSH_AGENT_RSA_RESPONSE (4)
const SSH_AGENT_SIGN_RESPONSE = 14;
/**#@-*/
/**@+
* Agent forwarding status
*
* @access private
*/
// no forwarding requested and not active
const FORWARD_NONE = 0;
// request agent forwarding when opportune
const FORWARD_REQUEST = 1;
// forwarding has been request and is active
const FORWARD_ACTIVE = 2;
/**#@-*/
/**
* Unused
*/
const SSH_AGENT_FAILURE = 5;
/**
* Socket Resource
*
* @var resource
* @access private
*/
var $fsock;
/**
* Agent forwarding status
*
* @access private
*/
var $forward_status = self::FORWARD_NONE;
/**
* Buffer for accumulating forwarded authentication
* agent data arriving on SSH data channel destined
* for agent unix socket
*
* @access private
*/
var $socket_buffer = '';
/**
* Tracking the number of bytes we are expecting
* to arrive for the agent socket on the SSH data
* channel
*/
var $expected_bytes = 0;
/**
* Default Constructor
*
* @return \phpseclib\System\SSH\Agent
* @access public
*/
function __construct()
{
switch (true) {
case isset($_SERVER['SSH_AUTH_SOCK']):
$address = $_SERVER['SSH_AUTH_SOCK'];
break;
case isset($_ENV['SSH_AUTH_SOCK']):
$address = $_ENV['SSH_AUTH_SOCK'];
break;
default:
user_error('SSH_AUTH_SOCK not found');
return false;
}
$this->fsock = fsockopen('unix://' . $address, 0, $errno, $errstr);
if (!$this->fsock) {
user_error("Unable to connect to ssh-agent (Error $errno: $errstr)");
}
}
/**
* Request Identities
*
* See "2.5.2 Requesting a list of protocol 2 keys"
* Returns an array containing zero or more \phpseclib\System\SSH\Agent\Identity objects
*
* @return array
* @access public
*/
function requestIdentities()
{
if (!$this->fsock) {
return array();
}
$packet = pack('NC', 1, self::SSH_AGENTC_REQUEST_IDENTITIES);
if (strlen($packet) != fputs($this->fsock, $packet)) {
user_error('Connection closed while requesting identities');
}
$length = current(unpack('N', fread($this->fsock, 4)));
$type = ord(fread($this->fsock, 1));
if ($type != self::SSH_AGENT_IDENTITIES_ANSWER) {
user_error('Unable to request identities');
}
$identities = array();
$keyCount = current(unpack('N', fread($this->fsock, 4)));
for ($i = 0; $i < $keyCount; $i++) {
$length = current(unpack('N', fread($this->fsock, 4)));
$key_blob = fread($this->fsock, $length);
$key_str = 'ssh-rsa ' . base64_encode($key_blob);
$length = current(unpack('N', fread($this->fsock, 4)));
if ($length) {
$key_str.= ' ' . fread($this->fsock, $length);
}
$length = current(unpack('N', substr($key_blob, 0, 4)));
$key_type = substr($key_blob, 4, $length);
switch ($key_type) {
case 'ssh-rsa':
$key = new RSA();
$key->loadKey($key_str);
break;
case 'ssh-dss':
// not currently supported
break;
}
// resources are passed by reference by default
if (isset($key)) {
$identity = new Identity($this->fsock);
$identity->setPublicKey($key);
$identity->setPublicKeyBlob($key_blob);
$identities[] = $identity;
unset($key);
}
}
return $identities;
}
/**
* Signal that agent forwarding should
* be requested when a channel is opened
*
* @param Net_SSH2 $ssh
* @return bool
* @access public
*/
function startSSHForwarding($ssh)
{
if ($this->forward_status == self::FORWARD_NONE) {
$this->forward_status = self::FORWARD_REQUEST;
}
}
/**
* Request agent forwarding of remote server
*
* @param Net_SSH2 $ssh
* @return bool
* @access private
*/
function _request_forwarding($ssh)
{
$request_channel = $ssh->_get_open_channel();
if ($request_channel === false) {
return false;
}
$packet = pack(
'CNNa*C',
NET_SSH2_MSG_CHANNEL_REQUEST,
$ssh->server_channels[$request_channel],
strlen('auth-agent-req@openssh.com'),
'auth-agent-req@openssh.com',
1
);
$ssh->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_REQUEST;
if (!$ssh->_send_binary_packet($packet)) {
return false;
}
$response = $ssh->_get_channel_packet($request_channel);
if ($response === false) {
return false;
}
$ssh->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_OPEN;
$this->forward_status = self::FORWARD_ACTIVE;
return true;
}
/**
* On successful channel open
*
* This method is called upon successful channel
* open to give the SSH Agent an opportunity
* to take further action. i.e. request agent forwarding
*
* @param Net_SSH2 $ssh
* @access private
*/
function _on_channel_open($ssh)
{
if ($this->forward_status == self::FORWARD_REQUEST) {
$this->_request_forwarding($ssh);
}
}
/**
* Forward data to SSH Agent and return data reply
*
* @param string $data
* @return data from SSH Agent
* @access private
*/
function _forward_data($data)
{
if ($this->expected_bytes > 0) {
$this->socket_buffer.= $data;
$this->expected_bytes -= strlen($data);
} else {
$agent_data_bytes = current(unpack('N', $data));
$current_data_bytes = strlen($data);
$this->socket_buffer = $data;
if ($current_data_bytes != $agent_data_bytes + 4) {
$this->expected_bytes = ($agent_data_bytes + 4) - $current_data_bytes;
return false;
}
}
if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) {
user_error('Connection closed attempting to forward data to SSH agent');
}
$this->socket_buffer = '';
$this->expected_bytes = 0;
$agent_reply_bytes = current(unpack('N', fread($this->fsock, 4)));
$agent_reply_data = fread($this->fsock, $agent_reply_bytes);
$agent_reply_data = current(unpack('a*', $agent_reply_data));
return pack('Na*', $agent_reply_bytes, $agent_reply_data);
}
}

View File

@ -0,0 +1,158 @@
<?php
/**
* Pure-PHP ssh-agent client.
*
* PHP version 5
*
* @category System
* @package SSH\Agent
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2009 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent
*/
namespace phpseclib\System\SSH\Agent;
use phpseclib\System\SSH\Agent;
/**
* Pure-PHP ssh-agent client identity object
*
* Instantiation should only be performed by \phpseclib\System\SSH\Agent class.
* This could be thought of as implementing an interface that phpseclib\Crypt\RSA
* implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something.
* The methods in this interface would be getPublicKey and sign since those are the
* methods phpseclib looks for to perform public key authentication.
*
* @package SSH\Agent
* @author Jim Wigginton <terrafrost@php.net>
* @access internal
*/
class Identity
{
/**
* Key Object
*
* @var \phpseclib\Crypt\RSA
* @access private
* @see self::getPublicKey()
*/
var $key;
/**
* Key Blob
*
* @var string
* @access private
* @see self::sign()
*/
var $key_blob;
/**
* Socket Resource
*
* @var resource
* @access private
* @see self::sign()
*/
var $fsock;
/**
* Default Constructor.
*
* @param resource $fsock
* @return \phpseclib\System\SSH\Agent\Identity
* @access private
*/
function __construct($fsock)
{
$this->fsock = $fsock;
}
/**
* Set Public Key
*
* Called by \phpseclib\System\SSH\Agent::requestIdentities()
*
* @param \phpseclib\Crypt\RSA $key
* @access private
*/
function setPublicKey($key)
{
$this->key = $key;
$this->key->setPublicKey();
}
/**
* Set Public Key
*
* Called by \phpseclib\System\SSH\Agent::requestIdentities(). The key blob could be extracted from $this->key
* but this saves a small amount of computation.
*
* @param string $key_blob
* @access private
*/
function setPublicKeyBlob($key_blob)
{
$this->key_blob = $key_blob;
}
/**
* Get Public Key
*
* Wrapper for $this->key->getPublicKey()
*
* @param int $format optional
* @return mixed
* @access public
*/
function getPublicKey($format = null)
{
return !isset($format) ? $this->key->getPublicKey() : $this->key->getPublicKey($format);
}
/**
* Set Signature Mode
*
* Doesn't do anything as ssh-agent doesn't let you pick and choose the signature mode. ie.
* ssh-agent's only supported mode is \phpseclib\Crypt\RSA::SIGNATURE_PKCS1
*
* @param int $mode
* @access public
*/
function setSignatureMode($mode)
{
}
/**
* Create a signature
*
* See "2.6.2 Protocol 2 private key signature request"
*
* @param string $message
* @return string
* @access public
*/
function sign($message)
{
// the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE
$packet = pack('CNa*Na*N', Agent::SSH_AGENTC_SIGN_REQUEST, strlen($this->key_blob), $this->key_blob, strlen($message), $message, 0);
$packet = pack('Na*', strlen($packet), $packet);
if (strlen($packet) != fputs($this->fsock, $packet)) {
user_error('Connection closed during signing');
}
$length = current(unpack('N', fread($this->fsock, 4)));
$type = ord(fread($this->fsock, 1));
if ($type != Agent::SSH_AGENT_SIGN_RESPONSE) {
user_error('Unable to retrieve signature');
}
$signature_blob = fread($this->fsock, $length - 1);
// the only other signature format defined - ssh-dss - is the same length as ssh-rsa
// the + 12 is for the other various SSH added length fields
return substr($signature_blob, strlen('ssh-rsa') + 12);
}
}

View File

@ -1,39 +0,0 @@
<?php
/**
* Pure-PHP ssh-agent client wrapper
*
* PHP versions 4 and 5
*
* Originally System_SSH_Agent was accessed as System/SSH_Agent.php instead of
* System/SSH/Agent.php. The problem with this is that PSR0 compatible autoloaders
* don't support that kind of directory layout hence the package being moved and
* this "alias" being created to maintain backwards compatibility.
*
* 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 System
* @package System_SSH_Agent
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2014 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent
*/
require_once 'SSH/Agent.php';

View File

@ -1,6 +1,6 @@
# minimalist openssl.cnf file for use with phpseclib
HOME = .
RANDFILE = $ENV::HOME/.rnd
[ v3_ca ]
# minimalist openssl.cnf file for use with phpseclib
HOME = .
RANDFILE = $ENV::HOME/.rnd
[ v3_ca ]

View File

@ -460,10 +460,6 @@ function get_preg($argument, $regexp) {
$language = $_SESSION['language'];
$language2 = explode ('.', $language);
setlocale(LC_ALL, $language2[0]);
// workaround for buggy PHP with Turkish
if (($language == 'tr_TR.utf8') && (version_compare(phpversion(), '5.5') < 0)) {
setlocale(LC_CTYPE, 'en_GB');
}
// First we check "positive" cases
$pregexpr = '';
switch ($regexp) {
@ -592,10 +588,6 @@ function get_preg($argument, $regexp) {
if (preg_match($pregexpr, $argument)) {
/* Bug in php preg_match doesn't work correct with utf8 */
setlocale(LC_ALL, $language);
// workaround for buggy PHP with Turkish
if (($language == 'tr_TR.utf8') && (version_compare(phpversion(), '5.5') < 0)) {
setlocale(LC_CTYPE, 'en_GB');
}
return true;
}
// Now we check "negative" cases, characters which are not allowed
@ -615,18 +607,10 @@ function get_preg($argument, $regexp) {
if (!preg_match($pregexpr, $argument)) {
/* Bug in php preg_match doesn't work correct with utf8 */
setlocale(LC_ALL, $language);
// workaround for buggy PHP with Turkish
if (($language == 'tr_TR.utf8') && (version_compare(phpversion(), '5.5') < 0)) {
setlocale(LC_CTYPE, 'en_GB');
}
return true;
}
/* Bug in php preg_match doesn't work correct with utf8 */
setlocale(LC_ALL, $language);
// workaround for buggy PHP with Turkish
if (($language == 'tr_TR.utf8') && (version_compare(phpversion(), '5.5') < 0)) {
setlocale(LC_CTYPE, 'en_GB');
}
return false;
}

View File

@ -36,8 +36,8 @@ include_once("../lib/status.inc");
/** config */
include_once("../lib/config.inc");
// check if PHP >= 5.4.0
if (version_compare(phpversion(), '5.4.0') < 0) {
// check if PHP >= 5.6.0
if (version_compare(phpversion(), '5.6.0') < 0) {
echo "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n\n";
echo "<html>\n<head>\n";
echo "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n";
@ -47,7 +47,7 @@ if (version_compare(phpversion(), '5.4.0') < 0) {
echo "<link rel=\"icon\" href=\"../graphics/logo136.png\">\n";
echo "<title>LDAP Account Manager</title>\n";
echo "</head><body>\n";
StatusMessage("ERROR", "LAM needs a PHP 5 version which is greater or equal than 5.4.0.", "Please upgrade your PHP installation. The found version is " . phpversion());
StatusMessage("ERROR", "LAM needs a PHP 5 version which is greater or equal than 5.6.0.", "Please upgrade your PHP installation. The found version is " . phpversion());
echo "<br><br>";
echo "</body></html>";
exit();

View File

@ -73,10 +73,6 @@ function setlanguage() {
}
putenv("LANG=" . $code); // e.g. LANG=de_DE
setlocale(LC_ALL, $code); // set LC_ALL
// workaround for buggy PHP with Turkish
if (($code == 'tr_TR.utf8') && (version_compare(phpversion(), '5.5') < 0)) {
setlocale(LC_CTYPE, 'en_GB');
}
$locdir = substr(__FILE__, 0, strlen(__FILE__) - 15) . "/locale"; // set path to translations
bindtextdomain("messages", $locdir);
bind_textdomain_codeset("messages", $encoding);

View File

@ -1,129 +0,0 @@
<?php
/*
$Id$
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2004 - 2016 Roland Gruber
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* This file includes functions to control lamdaemon.
*
* @author Tilo Lutz
* @author Roland Gruber
* @author Thomas Manninger
*
* @package modules
*/
/**
* Sends commands to lamdaemon script.
*
* @param array $command command to execute
* @param string $server remote server
* @return array Output of lamdaemon
*
*/
function lamdaemon($command, $server) {
if ($server == '') {
return array();
}
// add phpseclib to include path
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . '/3rdParty/phpseclib');
include_once('Net/SSH2.php');
try {
$handle = lamConnectSSH($server);
}
catch (Exception $e) {
return array("ERROR," . $e->getMessage() . "," . $server);
}
$output = $handle->exec("sudo " . $_SESSION['config']->get_scriptPath() . ' ' . escapeshellarg($command));
return array($output);
}
/**
* Connects to the given SSH server.
*
* @param String $server server name (e.g. localhost or localhost,1234)
* @return object handle
*/
function lamConnectSSH($server) {
// add phpseclib to include path
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . '/3rdParty/phpseclib');
include_once('Net/SSH2.php');
include_once('Crypt/RSA.php');
$serverNameParts = explode(",", $server);
$handle = false;
if (sizeof($serverNameParts) > 1) {
$handle = @new Net_SSH2($serverNameParts[0], $serverNameParts[1]);
}
else {
$handle = @new Net_SSH2($server);
}
if (!$handle) {
throw new Exception(_("Unable to connect to remote server!"));
}
lamLoginSSH($handle);
return $handle;
}
/**
* Performs a login to the provided SSH handle.
*
* @param handle $handle SSH handle
* @throws Exception login failed
*/
function lamLoginSSH($handle) {
$username = $_SESSION['config']->getScriptUserName();
$credentials = $_SESSION['ldap']->decrypt_login();
if (empty($username)) {
// get user name from current LAM user
$sr = @ldap_read($_SESSION['ldap']->server(), $credentials[0], "objectClass=posixAccount", array('uid'), 0, 0, 0, LDAP_DEREF_NEVER);
if ($sr) {
$entry = @ldap_get_entries($_SESSION['ldap']->server(), $sr);
$username = $entry[0]['uid'][0];
}
if (empty($username)) {
throw new Exception(sprintf(_("Your LAM admin user (%s) must be a valid Unix account to work with lamdaemon!"), getAbstractDN($credentials[0])));
}
}
$password = $credentials[1];
$keyPath = $_SESSION['config']->getScriptSSHKey();
if (!empty($keyPath)) {
// use key authentication
if (!file_exists($keyPath) || !is_readable($keyPath)) {
throw new Exception(sprintf(_("Unable to read %s."), htmlspecialchars($keyPath)));
}
$key = file_get_contents($keyPath);
$rsa = new Crypt_RSA();
$keyPassword = $_SESSION['config']->getScriptSSHKeyPassword();
if (!empty($keyPassword)) {
$rsa->setPassword($keyPassword);
}
if (!$rsa->loadKey($key)) {
throw new Exception(sprintf(_("Unable to load key %s."), htmlspecialchars($keyPath)));
}
$password = $rsa;
}
$login = @$handle->login($username, $password);
if (!$login) {
throw new Exception(_("Unable to login to remote server!"));
}
}
?>

View File

@ -45,8 +45,8 @@ include_once("account.inc");
include_once("baseModule.inc");
/** access to LDAP server */
include_once("ldap.inc");
/** lamdaemon functions */
include_once("lamdaemon.inc");
/** remote functions */
include_once("remote.inc");
/** security functions */
include_once("security.inc");
/** meta HTML classes */
@ -532,10 +532,12 @@ function buildUploadAccounts($type, $data, $ids, $selectedModules) {
}
}
if (sizeof($errors) > 0) {
for ($i = 0; (($i < sizeof($errors)) || ($i > 49)); $i++) call_user_func_array("StatusMessage", $errors[$i]);
for ($i = 0; (($i < sizeof($errors)) || ($i > 49)); $i++) {
call_user_func_array("StatusMessage", $errors[$i]);
}
return false;
}
else return $partialAccounts;
return $partialAccounts;
}
/**

View File

@ -475,7 +475,7 @@ class courierMailAccount extends baseModule {
'description' => _('Home directory'),
'help' => 'homeDirectory',
'example' => _('/home/smiller'),
'required' => 'true'
'required' => true
);
}
return $return;

View File

@ -248,7 +248,7 @@ By default, the nodes are configured as H-Nodes which fits for small networks. I
'help' => 'subnet',
'example' => '192.168.10.0',
'required' => true,
'unique' => 'true'
'unique' => true
),
array(
'name' => 'dhcp_settings_domainName',

View File

@ -161,7 +161,7 @@ class eduPerson extends baseModule {
'description' => _('Principal name'),
'help' => 'eduPersonPrincipalName',
'example' => _('user@company.com'),
'unique' => 'true'
'unique' => true
),
array(
'name' => 'eduPerson_primaryAffiliation',

View File

@ -32,7 +32,7 @@ $Id$
*
* @package modules
*/
class kolabSharedFolder extends baseModule { // TODO folder type
class kolabSharedFolder extends baseModule {
/** cache for mailHost values */
private $mailHostCache = null;
@ -49,7 +49,6 @@ class kolabSharedFolder extends baseModule { // TODO folder type
// call parent constructor
parent::__construct($scope);
$this->folderTypes = array(
// TODO reactivate types when stable 3.1 is released
/*_('Shared address book') => 'addressbook',
_('Shared calendar') => 'calendar',
_('Shared journal') => 'journal',

View File

@ -186,10 +186,8 @@ class posixAccount extends baseModule implements passwordService {
$loginShellsHelp = new htmlHelpLink('loginShells', get_class($this));
$loginShellsHelp->alignment = htmlElement::ALIGN_TOP;
$selfServiceContainer->addElement($loginShellsHelp, true);
if (version_compare(phpversion(), '5.4.26') >= 0) {
$selfServiceContainer->addElement(new htmlTableExtendedInputCheckbox('posixAccount_useOldPwd', false, _('Password change with old password')));
$selfServiceContainer->addElement(new htmlHelpLink('useOldPwd', get_class($this)), true);
}
$selfServiceContainer->addElement(new htmlTableExtendedInputCheckbox('posixAccount_useOldPwd', false, _('Password change with old password')));
$selfServiceContainer->addElement(new htmlHelpLink('useOldPwd', get_class($this)), true);
$return['selfServiceSettings'] = $selfServiceContainer;
}
// profile checks
@ -734,7 +732,9 @@ class posixAccount extends baseModule implements passwordService {
elseif (!in_array($temp[0], $this->lamdaemonServers)) {
continue;
}
$result = lamdaemon(
$remote = new \LAM\REMOTE\Remote();
$remote->connect($server);
$result = $remote->execute(
implode(
self::$SPLIT_DELIMITER,
array(
@ -745,11 +745,11 @@ class posixAccount extends baseModule implements passwordService {
"0".$_SESSION['config']->get_scriptRights(),
$this->attributes['uidNumber'][0],
$this->attributes['gidNumber'][0])
),
$server);
));
$remote->disconnect();
// lamdaemon results
if (is_array($result)) {
$singleresult = explode(",", $result[0]);
if (!empty($result)) {
$singleresult = explode(",", $result);
if (($singleresult[0] == 'ERROR') || ($singleresult[0] == 'INFO') || ($singleresult[0] == 'WARN')) {
$messages[] = $singleresult;
}
@ -769,7 +769,9 @@ class posixAccount extends baseModule implements passwordService {
}
$temp = explode(":", $lamdaemonServers[$i]);
$server = $temp[0];
$result = lamdaemon(
$remote = new \LAM\REMOTE\Remote();
$remote->connect($server);
$result = $remote->execute(
implode(
self::$SPLIT_DELIMITER,
array(
@ -779,11 +781,11 @@ class posixAccount extends baseModule implements passwordService {
$this->orig[$homeDirAttr][0],
$this->attributes['uidNumber'][0],
$this->attributes[$homeDirAttr][0])
),
$server);
));
$remote->disconnect();
// lamdaemon results
if (is_array($result)) {
$singleresult = explode(",", $result[0]);
if (!empty($result)) {
$singleresult = explode(",", $result);
if (($singleresult[0] == 'ERROR') || ($singleresult[0] == 'INFO') || ($singleresult[0] == 'WARN')) {
$messages[] = $singleresult;
}
@ -800,7 +802,9 @@ class posixAccount extends baseModule implements passwordService {
}
$temp = explode(":", $lamdaemonServers[$i]);
$server = $temp[0];
$result = lamdaemon(
$remote = new \LAM\REMOTE\Remote();
$remote->connect($server);
$result = $remote->execute(
implode(
self::$SPLIT_DELIMITER,
array(
@ -810,11 +814,11 @@ class posixAccount extends baseModule implements passwordService {
$this->orig[$homeDirAttr][0],
$this->attributes['uidNumber'][0],
$this->attributes['gidNumber'][0])
),
$server);
));
$remote->disconnect();
// lamdaemon results
if (is_array($result)) {
$singleresult = explode(",", $result[0]);
if (!empty($result)) {
$singleresult = explode(",", $result);
if (($singleresult[0] == 'ERROR') || ($singleresult[0] == 'INFO') || ($singleresult[0] == 'WARN')) {
$messages[] = $singleresult;
}
@ -937,7 +941,9 @@ class posixAccount extends baseModule implements passwordService {
}
// try to delete directory on all servers
for ($i = 0; $i < sizeof($lamdaemonServers); $i++) {
$result = lamdaemon(
$remote = new \LAM\REMOTE\Remote();
$remote->connect($lamdaemonServers[$i]);
$result = $remote->execute(
implode(
self::$SPLIT_DELIMITER,
array(
@ -947,16 +953,14 @@ class posixAccount extends baseModule implements passwordService {
$this->attributes[$homeDirAttr][0],
$this->attributes['uidNumber'][0]
)
),
$lamdaemonServers[$i]);
));
$remote->disconnect();
// lamdaemon results
if (is_array($result)) {
foreach ($result as $singleresult) {
$singleresult = explode(",", $singleresult);
if (is_array($singleresult)) {
if (($singleresult[0] == 'ERROR') || ($singleresult[0] == 'WARN') || ($singleresult[0] == 'INFO')) {
$return[] = $singleresult;
}
if (!empty($result)) {
$singleresult = explode(",", $result);
if (is_array($singleresult)) {
if (($singleresult[0] == 'ERROR') || ($singleresult[0] == 'WARN') || ($singleresult[0] == 'INFO')) {
$return[] = $singleresult;
}
}
}
@ -1272,7 +1276,9 @@ class posixAccount extends baseModule implements passwordService {
$temp = explode(":", $lamdaemonServers[$i]);
$server = $temp[0];
if (isset($_POST['form_subpage_' . get_class($this) . '_homedir_create_' . $i])) {
$result = lamdaemon(
$remote = new \LAM\REMOTE\Remote();
$remote->connect($server);
$result = $remote->execute(
implode(
self::$SPLIT_DELIMITER,
array(
@ -1283,22 +1289,22 @@ class posixAccount extends baseModule implements passwordService {
"0".$_SESSION['config']->get_scriptRights(),
$this->attributes['uidNumber'][0],
$this->attributes['gidNumber'][0])
),
$server);
));
$remote->disconnect();
// lamdaemon results
if (is_array($result)) {
foreach ($result as $singleresult) {
$singleresult = explode(",", $singleresult);
if (is_array($singleresult)) {
if (($singleresult[0] == 'ERROR') || ($singleresult[0] == 'WARN') || ($singleresult[0] == 'INFO')) {
$return[] = $singleresult;
}
if (!empty($result)) {
$singleresult = explode(",", $result);
if (is_array($singleresult)) {
if (($singleresult[0] == 'ERROR') || ($singleresult[0] == 'WARN') || ($singleresult[0] == 'INFO')) {
$return[] = $singleresult;
}
}
}
}
elseif (isset($_POST['form_subpage_' . get_class($this) . '_homedir_delete_' . $i])) {
$result = lamdaemon(
$remote = new \LAM\REMOTE\Remote();
$remote->connect($server);
$result = $remote->execute(
implode(
self::$SPLIT_DELIMITER,
array(
@ -1308,16 +1314,14 @@ class posixAccount extends baseModule implements passwordService {
$this->attributes[$homeDirAttr][0],
$this->attributes['uidNumber'][0]
)
),
$server);
));
$remote->disconnect();
// lamdaemon results
if (is_array($result)) {
foreach ($result as $singleresult) {
$singleresult = explode(",", $singleresult);
if (is_array($singleresult)) {
if (($singleresult[0] == 'ERROR') || ($singleresult[0] == 'WARN') || ($singleresult[0] == 'INFO')) {
$return[] = $singleresult;
}
if (!empty($result)) {
$singleresult = explode(",", $result);
if (is_array($singleresult)) {
if (($singleresult[0] == 'ERROR') || ($singleresult[0] == 'WARN') || ($singleresult[0] == 'INFO')) {
$return[] = $singleresult;
}
}
}
@ -1662,7 +1666,9 @@ class posixAccount extends baseModule implements passwordService {
if (isset($temp[1])) {
$label = $temp[1];
}
$result = lamdaemon(
$remote = new \LAM\REMOTE\Remote();
$remote->connect($server);
$result = $remote->execute(
implode(
self::$SPLIT_DELIMITER,
array(
@ -1670,11 +1676,11 @@ class posixAccount extends baseModule implements passwordService {
"home",
"check",
$this->attributes[$homeDirAttr][0])
),
$server);
));
$remote->disconnect();
// lamdaemon results
if (is_array($result)) {
$returnValue = trim($result[0]);
if (!empty($result)) {
$returnValue = trim($result);
if ($returnValue == 'ok') {
$homeServerContainer->addElement(new htmlOutputText($label));
$homeServerContainer->addElement(new htmlSpacer('5px', null));
@ -2533,7 +2539,9 @@ class posixAccount extends baseModule implements passwordService {
// create home directories
elseif ($temp['counter'] < (sizeof($temp['groups']) + sizeof($temp['createHomes']))) {
$pos = $temp['createHomes'][$temp['counter'] - sizeof($temp['groups'])];
$result = lamdaemon(
$remote = new \LAM\REMOTE\Remote();
$remote->connect($data[$pos][$ids['posixAccount_createHomeDir']]);
$result = $remote->execute(
implode(
self::$SPLIT_DELIMITER,
array(
@ -2545,11 +2553,11 @@ class posixAccount extends baseModule implements passwordService {
$accounts[$pos]['uidNumber'],
$accounts[$pos]['gidNumber'],
)
),
$data[$pos][$ids['posixAccount_createHomeDir']]);
));
$remote->disconnect();
$errors = array();
if (($result != false) && (sizeof($result) == 1)) {
$parts = explode(",", $result[0]);
if (!empty($result)) {
$parts = explode(",", $result);
if (in_array($parts[0], array('ERROR', 'WARN'))) {
$errors[] = $parts;
}

View File

@ -186,11 +186,14 @@ class quota extends baseModule {
$temp = explode(":", $lamdaemonServers[$s]);
$server = $temp[0];
// get quotas
$quotas = lamdaemon(implode(quota::$SPLIT_DELIMITER, array($userName, "quota", "get", $this->get_scope())), $server);
$remote = new \LAM\REMOTE\Remote();
$remote->connect($server);
$quotas = $remote->execute(implode(quota::$SPLIT_DELIMITER, array($userName, "quota", "get", $this->get_scope())));
$remote->disconnect();
if (sizeof($quotas) == 0) {
continue;
}
$allQuotas = explode(":", $quotas[0]);
$allQuotas = explode(":", $quotas);
array_pop($allQuotas); // remove empty element at the end
for ($i = 0; $i < sizeof($allQuotas); $i++) {
if (strpos($allQuotas[$i], quota::$QUOTA_PREFIX) !== 0) continue;
@ -280,7 +283,10 @@ class quota extends baseModule {
$quotastring = $quotastring . $this->quota[$server][$i][0] . ',' . $this->quota[$server][$i][2] . ',' . $this->quota[$server][$i][3]
. ',' . $this->quota[$server][$i][6] . ',' . $this->quota[$server][$i][7] . ':';
}
lamdaemon(implode(quota::$SPLIT_DELIMITER, array($id, "quota", "set", $this->get_scope(), "$quotastring\n")), $server);
$remote = new \LAM\REMOTE\Remote();
$remote->connect($server);
$remote->execute(implode(quota::$SPLIT_DELIMITER, array($id, "quota", "set", $this->get_scope(), "$quotastring\n")));
$remote->disconnect();
}
return $messages;
}
@ -319,7 +325,10 @@ class quota extends baseModule {
$quotastring = $quotastring . $this->quota[$server][$i][0] . ',0,0,0,0:';
$i++;
}
lamdaemon(implode(quota::$SPLIT_DELIMITER, array($id, "quota", "set", $this->get_scope(), "$quotastring\n")), $server);
$remote = new \LAM\REMOTE\Remote();
$remote->connect($server);
$remote->execute(implode(quota::$SPLIT_DELIMITER, array($id, "quota", "set", $this->get_scope(), "$quotastring\n")));
$remote->disconnect();
}
return array();
}
@ -483,11 +492,14 @@ class quota extends baseModule {
$description = $temp[1] . ' (' . $temp[0] . ')';
}
// Get quotas
$quotas = lamdaemon(implode(quota::$SPLIT_DELIMITER, array("+", "quota", "get", $this->get_scope())), $server);
if (sizeof($quotas) == 0) {
$remote = new \LAM\REMOTE\Remote();
$remote->connect($server);
$quotas = $remote->execute(implode(quota::$SPLIT_DELIMITER, array("+", "quota", "get", $this->get_scope())));
$remote->disconnect();
if (empty($quotas)) {
continue;
}
$dirs = explode(":", $quotas[0]);
$dirs = explode(":", $quotas);
array_pop($dirs); // remove empty element at the end
for ($i = 0; $i < sizeof($dirs); $i++) {
if (strpos($dirs[$i], quota::$QUOTA_PREFIX) !== 0) {
@ -556,8 +568,11 @@ class quota extends baseModule {
$server = $temp[0];
$id = $this->replaceSpecialChars($server);
// Get quotas
$quotas = lamdaemon(implode(quota::$SPLIT_DELIMITER, array("+", "quota", "get", $this->get_scope())), $server);
$dirs = explode(":", $quotas[0]);
$remote = new \LAM\REMOTE\Remote();
$remote->connect($server);
$quotas = $remote->execute(implode(quota::$SPLIT_DELIMITER, array("+", "quota", "get", $this->get_scope())));
$remote->disconnect();
$dirs = explode(":", $quotas);
array_pop($dirs); // remove empty element at the end
for ($i = 0; $i < sizeof($dirs); $i++) {
if (strpos($dirs[$i], quota::$QUOTA_PREFIX) !== 0) {
@ -669,8 +684,11 @@ class quota extends baseModule {
$temp = explode(":", $lamdaemonServers[$s]);
$server = $temp[0];
// Get quotas
$quotas = lamdaemon(implode(quota::$SPLIT_DELIMITER, array("+", "quota", "get", $this->get_scope())), $server);
$dirs = explode(":", $quotas[0]);
$remote = new \LAM\REMOTE\Remote();
$remote->connect($server);
$quotas = $remote->execute(implode(quota::$SPLIT_DELIMITER, array("+", "quota", "get", $this->get_scope())));
$remote->disconnect();
$dirs = explode(":", $quotas);
array_pop($dirs); // remove empty element at the end
for ($i = 0; $i < sizeof($dirs); $i++) {
if (strpos($dirs[$i], quota::$QUOTA_PREFIX) !== 0) {
@ -786,13 +804,14 @@ class quota extends baseModule {
$dir = $mpParts[1];
$quotaString = implode(quota::$SPLIT_DELIMITER, array($name, "quota", "set", $this->get_scope(), $dir . ',' .
implode(',', $temp['accounts'][$name][$mountPoints[$m]]) . "\n"));
$result = lamdaemon($quotaString, $server);
if (is_array($result)) {
for ($i = 0; $i < sizeof($result); $i++) {
$parts = explode(",", $result);
if ($parts[0] == 'ERROR') {
$errors[] = array('ERROR', $parts[1], $parts[2]);
}
$remote = new \LAM\REMOTE\Remote();
$remote->connect($server);
$result = $remote->execute($quotaString);
$remote->disconnect();
if (!empty($result)) {
$parts = explode(",", $result);
if ($parts[0] == 'ERROR') {
$errors[] = array('ERROR', $parts[1], $parts[2]);
}
}
}

View File

@ -1,4 +1,5 @@
<?php
/*
$Id$
@ -64,7 +65,7 @@ class sambaSamAccount extends baseModule implements passwordService {
private $cachedGroupSIDList = null;
/** cache for domain list */
private $cachedDomainList = null;
/** delimiter for lamdaemon commands */
/** delimiter for remote commands */
private static $SPLIT_DELIMITER = "###x##y##x###";
@ -1541,16 +1542,18 @@ class sambaSamAccount extends baseModule implements passwordService {
$return->addElement(new htmlSpacer(null, '10px'), true);
$homeServerContainer = new htmlTable();
$homeServerContainer->colspan = 5;
// get list of lamdaemon servers
$lamdaemonServers = explode(";", $_SESSION['config']->get_scriptServers());
for ($i = 0; $i < sizeof($lamdaemonServers); $i++) {
$temp = explode(":", $lamdaemonServers[$i]);
// get list of remote servers
$remoteServers = explode(";", $_SESSION['config']->get_scriptServers());
for ($i = 0; $i < sizeof($remoteServers); $i++) {
$temp = explode(":", $remoteServers[$i]);
$server = $temp[0];
$label = $temp[0];
if (isset($temp[1])) {
$label = $temp[1];
}
$result = lamdaemon(
$remote = new \LAM\REMOTE\Remote();
$remote->connect($server);
$result = $remote->execute(
implode(
self::$SPLIT_DELIMITER,
array(
@ -1558,11 +1561,11 @@ class sambaSamAccount extends baseModule implements passwordService {
"home",
"check",
$this->attributes['sambaProfilePath'][0])
),
$server);
// lamdaemon results
if (is_array($result)) {
$returnValue = trim($result[0]);
));
$remote->disconnect();
// remote command results
if (!empty($result)) {
$returnValue = trim($result);
if ($returnValue == 'ok') {
$homeServerContainer->addElement(new htmlOutputText($label));
$homeServerContainer->addElement(new htmlSpacer('5px', null));
@ -1614,13 +1617,15 @@ class sambaSamAccount extends baseModule implements passwordService {
if (empty($uidNumber) || empty($gidNumber)) {
return;
}
// get list of lamdaemon servers
$lamdaemonServers = explode(";", $_SESSION['config']->get_scriptServers());
for ($i = 0; $i < sizeof($lamdaemonServers); $i++) {
$temp = explode(":", $lamdaemonServers[$i]);
// get list of remote servers
$remoteServers = explode(";", $_SESSION['config']->get_scriptServers());
for ($i = 0; $i < sizeof($remoteServers); $i++) {
$temp = explode(":", $remoteServers[$i]);
$server = $temp[0];
if (isset($_POST['form_subpage_' . get_class($this) . '_homedir_create_' . $i])) {
$result = lamdaemon(
$remote = new \LAM\REMOTE\Remote();
$remote->connect($server);
$result = $remote->execute(
implode(
self::$SPLIT_DELIMITER,
array(
@ -1631,22 +1636,22 @@ class sambaSamAccount extends baseModule implements passwordService {
"0".$_SESSION['config']->get_scriptRights(),
$uidNumber,
$gidNumber)
),
$server);
// lamdaemon results
if (is_array($result)) {
foreach ($result as $singleresult) {
$singleresult = explode(",", $singleresult);
if (is_array($singleresult)) {
if (($singleresult[0] == 'ERROR') || ($singleresult[0] == 'WARN') || ($singleresult[0] == 'INFO')) {
$return[] = $singleresult;
}
));
$remote->disconnect();
// remote command results
if (!empty($result)) {
$singleresult = explode(",", $result);
if (is_array($singleresult)) {
if (($singleresult[0] == 'ERROR') || ($singleresult[0] == 'WARN') || ($singleresult[0] == 'INFO')) {
$return[] = $singleresult;
}
}
}
}
elseif (isset($_POST['form_subpage_' . get_class($this) . '_homedir_delete_' . $i])) {
$result = lamdaemon(
$remote = new \LAM\REMOTE\Remote();
$remote->connect($server);
$result = $remote->execute(
implode(
self::$SPLIT_DELIMITER,
array(
@ -1656,16 +1661,14 @@ class sambaSamAccount extends baseModule implements passwordService {
$this->attributes['sambaProfilePath'][0],
$uidNumber
)
),
$server);
// lamdaemon results
if (is_array($result)) {
foreach ($result as $singleresult) {
$singleresult = explode(",", $singleresult);
if (is_array($singleresult)) {
if (($singleresult[0] == 'ERROR') || ($singleresult[0] == 'WARN') || ($singleresult[0] == 'INFO')) {
$return[] = $singleresult;
}
));
$remote->disconnect();
// remote command results
if (!empty($result)) {
$singleresult = explode(",", $result);
if (is_array($singleresult)) {
if (($singleresult[0] == 'ERROR') || ($singleresult[0] == 'WARN') || ($singleresult[0] == 'INFO')) {
$return[] = $singleresult;
}
}
}

164
lam/lib/remote.inc Normal file
View File

@ -0,0 +1,164 @@
<?php
namespace LAM\REMOTE;
use \Exception;
use \phpseclib\Net\SSH2;
use \phpseclib\Crypt\RSA;
/*
$Id$
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2017 Roland Gruber
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* This file includes functions to control LAM remote executions.
*
* @author Roland Gruber
*
* @package modules
*/
/**
* Runs remote commands.
*
* @author Roland Gruber
*/
class Remote {
/** SSH2 server handle */
private $server = null;
/**
* Constructor, include SSH library.
*/
public function __construct() {
$this->includeSshLibrary();
}
/**
* Sends commands to remote script.
*
* @param string $command command to execute
* @return string output of remote script
*/
public function execute($command) {
if ($this->server == null) {
return array();
}
return $this->server->exec("sudo " . $_SESSION['config']->get_scriptPath() . ' ' . escapeshellarg($command));
}
/**
* Connects to the given SSH server.
*
* @param String $server server name (e.g. localhost or localhost,1234)
*/
public function connect($server) {
$serverNameParts = explode(",", $server);
$handle = false;
if (sizeof($serverNameParts) > 1) {
$handle = @new SSH2($serverNameParts[0], $serverNameParts[1]);
}
else {
$handle = @new SSH2($server);
}
if (!$handle) {
throw new Exception(_("Unable to connect to remote server!"));
}
$this->loginSSH($handle);
$this->server = $handle;
}
/**
* Closes the connection.
*/
public function disconnect() {
if ($this->server == null) {
return;
}
$this->server->disconnect();
}
/**
* Performs a login to the provided SSH handle.
*
* @param SSH2 $handle SSH handle
* @throws Exception login failed
*/
private function loginSSH($handle) {
$username = $_SESSION['config']->getScriptUserName();
$credentials = $_SESSION['ldap']->decrypt_login();
if (empty($username)) {
// get user name from current LAM user
$sr = @ldap_read($_SESSION['ldap']->server(), $credentials[0], "objectClass=posixAccount", array('uid'), 0, 0, 0, LDAP_DEREF_NEVER);
if ($sr) {
$entry = @ldap_get_entries($_SESSION['ldap']->server(), $sr);
$username = $entry[0]['uid'][0];
}
if (empty($username)) {
throw new Exception(sprintf(_("Your LAM admin user (%s) must be a valid Unix account to work with lamdaemon!"), getAbstractDN($credentials[0])));
}
}
$password = $credentials[1];
$keyPath = $_SESSION['config']->getScriptSSHKey();
if (!empty($keyPath)) {
// use key authentication
if (!file_exists($keyPath) || !is_readable($keyPath)) {
throw new Exception(sprintf(_("Unable to read %s."), htmlspecialchars($keyPath)));
}
$key = file_get_contents($keyPath);
$rsa = new RSA();
$keyPassword = $_SESSION['config']->getScriptSSHKeyPassword();
if (!empty($keyPassword)) {
$rsa->setPassword($keyPassword);
}
if (!$rsa->loadKey($key)) {
throw new Exception(sprintf(_("Unable to load key %s."), htmlspecialchars($keyPath)));
}
$password = $rsa;
}
$login = @$handle->login($username, $password);
if (!$login) {
throw new Exception(_("Unable to login to remote server!"));
}
}
/**
* Include the SSH files.
*/
private function includeSshLibrary() {
$prefix = dirname(__FILE__) . '/3rdParty/phpseclib/';
require_once($prefix . 'Crypt/Base.php');
require_once($prefix . 'Crypt/Blowfish.php');
require_once($prefix . 'Crypt/Hash.php');
require_once($prefix . 'Crypt/Random.php');
require_once($prefix . 'Crypt/RC4.php');
require_once($prefix . 'Crypt/Rijndael.php');
require_once($prefix . 'Crypt/AES.php');
require_once($prefix . 'Crypt/RSA.php');
require_once($prefix . 'Crypt/DES.php');
require_once($prefix . 'Crypt/TripleDES.php');
require_once($prefix . 'Crypt/Twofish.php');
require_once($prefix . 'Math/BigInteger.php');
require_once($prefix . 'System/SSH/Agent.php');
require_once($prefix . 'Net/SSH2.php');
}
}
?>

2
lam/po/.gitignore vendored
View File

@ -1,2 +1,2 @@
*.po
*.tar.gz
*.tar.gz

View File

@ -85,8 +85,8 @@ if (isset($_GET['DN'])) {
$result = $_SESSION['account']->load_account($DN);
if (sizeof($result) > 0) {
include '../main_header.php';
for ($i=0; $i<sizeof($result); $i++) {
call_user_func_array("StatusMessage", $result[$i]);
foreach ($result as $message) {
call_user_func_array("StatusMessage", $message);
}
include '../main_footer.php';
die();
@ -107,14 +107,6 @@ else if (count($_POST)==0) {
$_SESSION['account']->new_account();
}
// remove double slashes if magic quotes are on
if (get_magic_quotes_gpc() == 1) {
$postKeys = array_keys($_POST);
for ($i = 0; $i < sizeof($postKeys); $i++) {
if (is_string($_POST[$postKeys[$i]])) $_POST[$postKeys[$i]] = stripslashes($_POST[$postKeys[$i]]);
}
}
// show account page
$_SESSION['account']->continue_main();

View File

@ -625,13 +625,6 @@ function checkInput() {
$conf = &$_SESSION['conf_config'];
$types = $conf->get_ActiveTypes();
// remove double slashes if magic quotes are on
if (get_magic_quotes_gpc() == 1) {
$postKeys = array_keys($_POST);
for ($i = 0; $i < sizeof($postKeys); $i++) {
if (is_string($_POST[$postKeys[$i]])) $_POST[$postKeys[$i]] = stripslashes($_POST[$postKeys[$i]]);
}
}
// check new preferences
$errors = array();
if (!$conf->set_ServerURL($_POST['serverurl'])) {

View File

@ -90,13 +90,6 @@ $errors = array();
$messages = array();
// check if submit button was pressed
if (isset($_POST['submitFormData'])) {
// remove double slashes if magic quotes are on
if (get_magic_quotes_gpc() == 1) {
$postKeys = array_keys($_POST);
for ($i = 0; $i < sizeof($postKeys); $i++) {
if (is_string($_POST[$postKeys[$i]])) $_POST[$postKeys[$i]] = stripslashes($_POST[$postKeys[$i]]);
}
}
// set master password
if (isset($_POST['masterpassword']) && ($_POST['masterpassword'] != "")) {
if ($_POST['masterpassword'] && $_POST['masterpassword2'] && ($_POST['masterpassword'] == $_POST['masterpassword2'])) {

View File

@ -42,8 +42,8 @@ include_once('../lib/config.inc');
include_once('../lib/status.inc');
/** LDAP connection */
include_once('../lib/ldap.inc');
/** lamdaemon interface */
include_once('../lib/lamdaemon.inc');
/** remote interface */
include_once('../lib/remote.inc');
/** module interface */
include_once('../lib/modules.inc');
@ -105,7 +105,8 @@ if (isset($_GET['type']) && isset($_SESSION['delete_dn'])) {
echo "<b>" . _("Do you really want to remove the following accounts?") . "</b>";
echo "<br><br>\n";
echo "<table border=0>\n";
for ($i=0; $i<count($users); $i++) {
$userCount = sizeof($users);
for ($i = 0; $i < $userCount; $i++) {
echo "<tr>\n";
echo "<td><b>" . _("Account name:") . "</b> " . htmlspecialchars($users[$i]) . "</td>\n";
echo "<td>&nbsp;&nbsp;<b>" . _('DN') . ":</b> " . htmlspecialchars($_SESSION['delete_dn'][$i]) . "</td>\n";
@ -173,11 +174,11 @@ if (isset($_POST['delete'])) {
// Delete dns
$allOk = true;
$allErrors = array();
for ($m=0; $m<count($_SESSION['delete_dn']); $m++) {
foreach ($_SESSION['delete_dn'] as $deleteDN) {
// Set to true if an real error has happened
$stopprocessing = false;
// First load DN.
$_SESSION['account']->load_account($_SESSION['delete_dn'][$m]);
$_SESSION['account']->load_account($deleteDN);
// get commands and changes of each attribute
$moduleNames = array_keys($_SESSION['account']->getAccountModules());
$modules = $_SESSION['account']->getAccountModules();
@ -188,13 +189,13 @@ if (isset($_POST['delete'])) {
foreach ($moduleNames as $singlemodule) {
$success = true;
$messages = $modules[$singlemodule]->preDeleteActions();
for ($i = 0; $i < sizeof($messages); $i++) {
$errors[] = $messages[$i];
if ($messages[$i][0] == 'ERROR') {
foreach ($messages as $message) {
$errors[] = $message;
if ($message[0] == 'ERROR') {
$success = false;
$allOk = false;
}
elseif ($messages[$i][0] == 'WARN') {
elseif ($message[0] == 'WARN') {
$allOk = false;
}
}
@ -213,20 +214,21 @@ if (isset($_POST['delete'])) {
// merge changes
$DNs = array_keys($temp);
$attributes = array_merge_recursive($temp, $attributes);
for ($i=0; $i<count($DNs); $i++) {
$ops = array_keys($temp[$DNs[$i]]);
for ($j=0; $j<count($ops); $j++) {
$attrs = array_keys($temp[$DNs[$i]][$ops[$j]]);
for ($k=0; $k<count($attrs); $k++)
$attributes[$DNs[$i]][$ops[$j]][$attrs[$k]] = array_unique($attributes[$DNs[$i]][$ops[$j]][$attrs[$k]]);
foreach ($DNs as $dn) {
$ops = array_keys($temp[$dn]);
foreach ($ops as $op) {
$attrs = array_keys($temp[$dn][$op]);
foreach ($attrs as $attribute) {
$attributes[$dn][$op][$attribute] = array_unique($attributes[$dn][$op][$attribute]);
}
}
}
}
}
$DNs = array_keys($attributes);
for ($i=0; $i<count($DNs); $i++) {
if (isset($attributes[$DNs[$i]]['errors'])) {
foreach ($attributes[$DNs[$i]]['errors'] as $singleerror) {
foreach ($DNs as $dn) {
if (isset($attributes[$dn]['errors'])) {
foreach ($attributes[$dn]['errors'] as $singleerror) {
$errors[] = $singleerror;
if ($singleerror[0] == 'ERROR') {
$stopprocessing = true;
@ -236,28 +238,28 @@ if (isset($_POST['delete'])) {
}
if (!$stopprocessing) {
// modify attributes
if (isset($attributes[$DNs[$i]]['modify']) && !$stopprocessing) {
$success = @ldap_mod_replace($_SESSION['ldap']->server(), $DNs[$i], $attributes[$DNs[$i]]['modify']);
if (isset($attributes[$dn]['modify']) && !$stopprocessing) {
$success = @ldap_mod_replace($_SESSION['ldap']->server(), $dn, $attributes[$dn]['modify']);
if (!$success) {
$errors[] = array ('ERROR', sprintf(_('Was unable to modify attributes from DN: %s.'), $DNs[$i]), getDefaultLDAPErrorString($_SESSION['ldap']->server()));
$errors[] = array ('ERROR', sprintf(_('Was unable to modify attributes from DN: %s.'), $dn), getDefaultLDAPErrorString($_SESSION['ldap']->server()));
$stopprocessing = true;
$allOk = false;
}
}
// add attributes
if (isset($attributes[$DNs[$i]]['add']) && !$stopprocessing) {
$success = @ldap_mod_add($_SESSION['ldap']->server(), $DNs[$i], $attributes[$DNs[$i]]['add']);
if (isset($attributes[$dn]['add']) && !$stopprocessing) {
$success = @ldap_mod_add($_SESSION['ldap']->server(), $dn, $attributes[$dn]['add']);
if (!$success) {
$errors[] = array ('ERROR', sprintf(_('Was unable to add attributes to DN: %s.'), $DNs[$i]), getDefaultLDAPErrorString($_SESSION['ldap']->server()));
$errors[] = array ('ERROR', sprintf(_('Was unable to add attributes to DN: %s.'), $dn), getDefaultLDAPErrorString($_SESSION['ldap']->server()));
$stopprocessing = true;
$allOk = false;
}
}
// remove attributes
if (isset($attributes[$DNs[$i]]['remove']) && !$stopprocessing) {
$success = @ldap_mod_del($_SESSION['ldap']->server(), $DNs[$i], $attributes[$DNs[$i]]['remove']);
if (isset($attributes[$dn]['remove']) && !$stopprocessing) {
$success = @ldap_mod_del($_SESSION['ldap']->server(), $dn, $attributes[$dn]['remove']);
if (!$success) {
$errors[] = array ('ERROR', sprintf(_('Was unable to remove attributes from DN: %s.'), $DNs[$i]), getDefaultLDAPErrorString($_SESSION['ldap']->server()));
$errors[] = array ('ERROR', sprintf(_('Was unable to remove attributes from DN: %s.'), $dn), getDefaultLDAPErrorString($_SESSION['ldap']->server()));
$stopprocessing = true;
$allOk = false;
}
@ -267,7 +269,7 @@ if (isset($_POST['delete'])) {
}
if (!$stopprocessing) {
$recursive = !$_SESSION['account']->hasOnlyVirtualChildren();
$messages = deleteDN($_SESSION['delete_dn'][$m], $recursive);
$messages = deleteDN($deleteDN, $recursive);
$errors = array_merge($errors, $messages);
if (sizeof($errors) > 0) {
$stopprocessing = true;
@ -278,16 +280,16 @@ if (isset($_POST['delete'])) {
if (!$stopprocessing) {
foreach ($moduleNames as $singlemodule) {
$messages = $modules[$singlemodule]->postDeleteActions();
for ($i = 0; $i < sizeof($messages); $i++) {
$errors[] = $messages[$i];
if (($messages[$i][0] == 'ERROR') || ($messages[$i][0] == 'WARN')) {
foreach ($messages as $message) {
$errors[] = $message;
if (($message[0] == 'ERROR') || ($message[0] == 'WARN')) {
$allOk = false;
}
}
}
}
if (!$stopprocessing) {
echo sprintf(_('Deleted DN: %s'), $_SESSION['delete_dn'][$m]) . "<br>\n";
echo sprintf(_('Deleted DN: %s'), $deleteDN) . "<br>\n";
foreach ($errors as $error) {
call_user_func_array('StatusMessage', $error);
}
@ -295,7 +297,7 @@ if (isset($_POST['delete'])) {
flush();
}
else {
echo sprintf(_('Error while deleting DN: %s'), $_SESSION['delete_dn'][$m]) . "<br>\n";
echo sprintf(_('Error while deleting DN: %s'), $deleteDN) . "<br>\n";
foreach ($errors as $error) {
call_user_func_array('StatusMessage', $error);
}

View File

@ -54,19 +54,19 @@ if (!empty($_POST)) {
// check if user already pressed button
if (isset($_POST['add_suff']) || isset($_POST['cancel'])) {
if (isset($_POST['add_suff'])) {
$fail = array();
$errors = array();
$new_suff = $_POST['new_suff'];
$new_suff = str_replace("\\", "", $new_suff);
$new_suff = str_replace("'", "", $new_suff);
$new_suff = explode(";", $new_suff);
$failedDNs = array();
$error = array();
$newSuffixes = $_POST['new_suff'];
$newSuffixes = str_replace("\\", "", $newSuffixes);
$newSuffixes = str_replace("'", "", $newSuffixes);
$newSuffixes = explode(";", $newSuffixes);
// add entries
for ($i = 0; $i < sizeof($new_suff); $i++) {
foreach ($newSuffixes as $newSuffix) {
// check if entry is already present
$info = @ldap_read($_SESSION['ldap']->server(), escapeDN($new_suff[$i]), "objectclass=*", array('dn'), 0, 0, 0, LDAP_DEREF_NEVER);
$info = @ldap_read($_SESSION['ldap']->server(), escapeDN($newSuffix), "objectclass=*", array('dn'), 0, 0, 0, LDAP_DEREF_NEVER);
$res = @ldap_get_entries($_SESSION['ldap']->server(), $info);
if ($res) continue;
$suff = $new_suff[$i];
$suff = $newSuffix;
// generate DN and attributes
$tmp = explode(",", $suff);
$name = explode("=", $tmp[0]);
@ -78,7 +78,7 @@ if (isset($_POST['add_suff']) || isset($_POST['cancel'])) {
$attr['objectClass'] = 'organization';
$dn = $suff;
if (!@ldap_add($_SESSION['ldap']->server(), $dn, $attr)) {
$fail[] = $suff;
$failedDNs[] = $suff;
$error[] = ldap_error($_SESSION['ldap']->server());
continue;
}
@ -117,7 +117,7 @@ if (isset($_POST['add_suff']) || isset($_POST['cancel'])) {
$attr['ou'] = $headarray[1];
$dn = $subsuffs[$k];
if (!@ldap_add($_SESSION['ldap']->server(), $dn, $attr)) {
$fail[] = $suff;
$failedDNs[] = $suff;
$error[] = ldap_error($_SESSION['ldap']->server());
break;
}
@ -132,7 +132,7 @@ if (isset($_POST['add_suff']) || isset($_POST['cancel'])) {
}
$dn = $subsuffs[$k];
if (!@ldap_add($_SESSION['ldap']->server(), $dn, $attr)) {
$fail[] = $suff;
$failedDNs[] = $suff;
$error[] = ldap_error($_SESSION['ldap']->server());
break;
}
@ -141,7 +141,7 @@ if (isset($_POST['add_suff']) || isset($_POST['cancel'])) {
}
}
else {
$fail[] = $suff;
$failedDNs[] = $suff;
$error[] = ldap_error($_SESSION['ldap']->server());
}
}
@ -151,10 +151,10 @@ if (isset($_POST['add_suff']) || isset($_POST['cancel'])) {
include 'main_header.php';
// print error/success messages
if (isset($_POST['add_suff'])) {
if (sizeof($fail) > 0) {
if (sizeof($failedDNs) > 0) {
// print error messages
for ($i = 0; $i < sizeof($fail); $i++) {
StatusMessage("ERROR", _("Failed to create entry!") . "<br>" . htmlspecialchars($error[$i]), htmlspecialchars($fail[$i]));
for ($i = 0; $i < sizeof($failedDNs); $i++) {
StatusMessage("ERROR", _("Failed to create entry!") . "<br>" . htmlspecialchars($error[$i]), htmlspecialchars($failedDNs[$i]));
}
include 'main_footer.php';
}
@ -173,10 +173,10 @@ if (isset($_POST['add_suff']) || isset($_POST['cancel'])) {
}
// first show of page
$new_suff = $_GET['suffs'];
$new_suff = str_replace("\\", "", $new_suff);
$new_suff = str_replace("'", "", $new_suff);
$new_suff = explode(";", $new_suff);
$newSuffixes = $_GET['suffs'];
$newSuffixes = str_replace("\\", "", $newSuffixes);
$newSuffixes = str_replace("'", "", $newSuffixes);
$newSuffixes = explode(";", $newSuffixes);
include 'main_header.php';
echo '<div class="user-bright smallPaddingContent">';
@ -186,15 +186,15 @@ include 'main_header.php';
$container->addElement(new htmlOutputText(_("You can setup the LDAP suffixes for all account types in your LAM server profile on tab \"Account types\".")), true);
$container->addElement(new htmlSpacer(null, '10px'), true);
// print missing suffixes
for ($i = 0; $i < sizeof($new_suff); $i++) {
$container->addElement(new htmlOutputText($new_suff[$i]), true);
foreach ($newSuffixes as $newSuffix) {
$container->addElement(new htmlOutputText($newSuffix), true);
}
$container->addElement(new htmlSpacer(null, '10px'), true);
$buttonContainer = new htmlTable();
$buttonContainer->addElement(new htmlButton('add_suff', _("Create")));
$buttonContainer->addElement(new htmlButton('cancel', _("Cancel")));
$buttonContainer->addElement(new htmlHiddenInput('new_suff', implode(";", $new_suff)));
$buttonContainer->addElement(new htmlHiddenInput('new_suff', implode(";", $newSuffixes)));
$container->addElement($buttonContainer);
addSecurityTokenToMetaHTML($container);

View File

@ -61,4 +61,4 @@ if (!isset($_SESSION['list_' . $type->getId()])) {
// show page
$_SESSION['list_' . $type->getId()]->showPage();
?>
?>

View File

@ -177,7 +177,7 @@ $_SESSION['header'] .= "<meta http-equiv=\"pragma\" content=\"no-cache\">\n <me
* @param \LAM\ENV\LAMLicenseValidator $licenseValidator license validator
* @param string $error_message error message to display
*/
function display_LoginPage($config_object, $cfgMain, $licenseValidator, $error_message) {
function display_LoginPage(LAMConfig $config_object, LAMCfgMain $cfgMain, $licenseValidator, $error_message) {
logNewMessage(LOG_DEBUG, "Display login page");
// generate 256 bit key and initialization vector for user/passwd-encryption
if(function_exists('openssl_random_pseudo_bytes') && ($cfgMain->encryptSession == 'true')) {
@ -582,9 +582,6 @@ if(!empty($_POST['checklogin'])) {
display_LoginPage($_SESSION['config'], $_SESSION["cfgMain"], $licenseValidator, $error_message); // Empty password submitted. Return to login page.
exit();
}
if (get_magic_quotes_gpc() == 1) {
$_POST['passwd'] = stripslashes($_POST['passwd']);
}
$username = $_POST['username'];
$password = $_POST['passwd'];
}
@ -594,7 +591,7 @@ if(!empty($_POST['checklogin'])) {
$searchFilter = str_replace('%USER%', $username ,$searchFilter);
$searchDN = '';
$searchPassword = '';
if (($_SESSION['config']->getLoginSearchDN() != null) && ($_SESSION['config']->getLoginSearchDN() != '')) {
if (!empty($_SESSION['config']->getLoginSearchDN())) {
$searchDN = $_SESSION['config']->getLoginSearchDN();
$searchPassword = $_SESSION['config']->getLoginSearchPassword();
}

View File

@ -1,4 +1,5 @@
<?php
namespace LAM\AJAX;
/*
$Id$
@ -47,18 +48,19 @@ if (startSecureSession(false, true) === false) {
setlanguage();
lamAjax::handleRequest();
$ajax = new Ajax();
$ajax->handleRequest();
/**
* Manages all AJAX requests.
*/
class lamAjax {
class Ajax {
/**
* Manages an AJAX request.
*/
public static function handleRequest() {
lamAjax::setHeader();
public function handleRequest() {
$this->setHeader();
// check token
validateSecurityToken(false);
@ -84,16 +86,16 @@ class lamAjax {
$jsonInput = $_POST['jsonInput'];
if ($function == 'passwordStrengthCheck') {
lamAjax::checkPasswordStrength($jsonInput);
$this->checkPasswordStrength($jsonInput);
}
enforceUserIsLoggedIn();
if ($function == 'passwordChange') {
lamAjax::managePasswordChange($jsonInput);
$this->managePasswordChange($jsonInput);
}
elseif ($function == 'upload') {
include_once('../../lib/upload.inc');
$typeManager = new \LAM\TYPES\TypeManager();
$uploader = new LAM\UPLOAD\Uploader($typeManager->getConfiguredType($_GET['typeId']));
$uploader = new \LAM\UPLOAD\Uploader($typeManager->getConfiguredType($_GET['typeId']));
ob_start();
$jsonOut = $uploader->doUpload();
ob_end_clean();
@ -115,7 +117,7 @@ class lamAjax {
*
* @param array $input input parameters
*/
public static function managePasswordChange($input) {
private static function managePasswordChange($input) {
$return = $_SESSION['account']->setNewPassword($input);
echo json_encode($return);
}
@ -125,7 +127,7 @@ class lamAjax {
*
* @param array $input input parameters
*/
public static function checkPasswordStrength($input) {
private function checkPasswordStrength($input) {
$password = $input['password'];
$result = checkPasswordStrength($password, null, null);
echo json_encode(array("result" => $result));

View File

@ -81,7 +81,7 @@ if (isset($_POST['createOU']) || isset($_POST['deleteOU'])) {
// check if ou already exists
$new_dn = "ou=" . $_POST['newOU'] . "," . $_POST['parentOU'];
$found = ldapGetDN($new_dn);
if ($found == null) {
if ($found === null) {
// add new ou
$ou = array();
$ou['objectClass'] = "organizationalunit";

View File

@ -15,6 +15,7 @@ use \htmlInputFileUpload;
use \htmlHelpLink;
use \htmlInputField;
use \htmlHiddenInput;
use \LAM\TYPES\TypeManager;
/*
$Id$
@ -89,7 +90,7 @@ if(isset($_POST['createNewTemplate'])) {
exit();
}
$typeManager = new \LAM\TYPES\TypeManager();
$typeManager = new TypeManager();
$types = $typeManager->getConfiguredTypes();
$sortedTypes = array();
foreach ($types as $type) {
@ -141,7 +142,7 @@ if (!empty($_POST['import'])) {
}
$errMessage = importStructures($_POST['typeId'], $options, $serverProfiles, $typeManager);
}
if ($errMessage != null) {
if ($errMessage !== null) {
$errMessage->colspan = 10;
$container->addElement($errMessage, true);
}
@ -166,7 +167,7 @@ if (!empty($_POST['export'])) {
$name = $_POST['name_' . $typeId];
$errMessage = exportStructures($typeId, $name, $options, $serverProfiles, $typeManager);
}
if ($errMessage != null) {
if ($errMessage !== null) {
$errMessage->colspan = 10;
$container->addElement($errMessage, true);
}
@ -195,23 +196,18 @@ foreach ($sortedTypes as $typeId => $title) {
'scope' => $type->getScope(),
'title' => $title,
'icon' => $type->getIcon(),
'templates' => "");
'templates' => \LAM\PDF\getPDFStructures($type->getId()));
$availableTypes[$title] = $type->getId();
}
// get list of templates for each account type
for ($i = 0; $i < sizeof($templateClasses); $i++) {
$templateClasses[$i]['templates'] = \LAM\PDF\getPDFStructures($templateClasses[$i]['typeId']);
}
// check if a template should be edited
for ($i = 0; $i < sizeof($templateClasses); $i++) {
if (isset($_POST['editTemplate_' . $templateClasses[$i]['typeId']]) || isset($_POST['editTemplate_' . $templateClasses[$i]['typeId'] . '_x'])) {
metaRefresh('pdfpage.php?type=' . htmlspecialchars($templateClasses[$i]['typeId']) . '&edit=' . htmlspecialchars($_POST['template_' . $templateClasses[$i]['typeId']]));
foreach ($templateClasses as $templateClass) {
if (isset($_POST['editTemplate_' . $templateClass['typeId']]) || isset($_POST['editTemplate_' . $templateClass['typeId'] . '_x'])) {
metaRefresh('pdfpage.php?type=' . htmlspecialchars($templateClass['typeId']) . '&edit=' . htmlspecialchars($_POST['template_' . $templateClass['typeId']]));
exit;
}
}
include '../main_header.php';
?>
<div class="user-bright smallPaddingContent">
<form enctype="multipart/form-data" action="pdfmain.php" method="post" name="pdfmainForm" >
@ -246,38 +242,38 @@ include '../main_header.php';
// existing templates
$container->addElement(new htmlSubTitle(_("Manage existing PDF structures")), true);
$existingContainer = new htmlTable();
for ($i = 0; $i < sizeof($templateClasses); $i++) {
foreach ($templateClasses as $templateClass) {
if ($i > 0) {
$existingContainer->addElement(new htmlSpacer(null, '10px'), true);
}
$existingContainer->addElement(new htmlImage('../../graphics/' . $templateClasses[$i]['icon']));
$existingContainer->addElement(new htmlImage('../../graphics/' . $templateClass['icon']));
$existingContainer->addElement(new htmlSpacer('3px', null));
$existingContainer->addElement(new htmlOutputText($templateClasses[$i]['title']));
$existingContainer->addElement(new htmlOutputText($templateClass['title']));
$existingContainer->addElement(new htmlSpacer('3px', null));
$select = new htmlSelect('template_' . $templateClasses[$i]['typeId'], $templateClasses[$i]['templates']);
$select = new htmlSelect('template_' . $templateClass['typeId'], $templateClass['templates']);
$select->setWidth('15em');
$existingContainer->addElement($select);
$existingContainer->addElement(new htmlSpacer('3px', null));
$exEditButton = new htmlButton('editTemplate_' . $templateClasses[$i]['typeId'], 'edit.png', true);
$exEditButton = new htmlButton('editTemplate_' . $templateClass['typeId'], 'edit.png', true);
$exEditButton->setTitle(_('Edit'));
$existingContainer->addElement($exEditButton);
$deleteLink = new htmlLink(null, '#', '../../graphics/delete.png');
$deleteLink->setTitle(_('Delete'));
$deleteLink->setOnClick("profileShowDeleteDialog('" . _('Delete') . "', '" . _('Ok') . "', '" . _('Cancel') . "', '" . $templateClasses[$i]['typeId'] . "', '" . 'template_' . $templateClasses[$i]['typeId'] . "');");
$deleteLink->setOnClick("profileShowDeleteDialog('" . _('Delete') . "', '" . _('Ok') . "', '" . _('Cancel') . "', '" . $templateClass['typeId'] . "', '" . 'template_' . $templateClass['typeId'] . "');");
$existingContainer->addElement($deleteLink);
if (count($configProfiles) > 1) {
$importLink = new htmlLink(null, '#', '../../graphics/import.png');
$importLink->setTitle(_('Import PDF structures'));
$importLink->setOnClick("showDistributionDialog('" . _("Import PDF structures") . "', '" .
_('Ok') . "', '" . _('Cancel') . "', '" . $templateClasses[$i]['typeId'] . "', 'import');");
_('Ok') . "', '" . _('Cancel') . "', '" . $templateClass['typeId'] . "', 'import');");
$existingContainer->addElement($importLink);
}
$exportLink = new htmlLink(null, '#', '../../graphics/export.png');
$exportLink->setTitle(_('Export PDF structure'));
$exportLink->setOnClick("showDistributionDialog('" . _("Export PDF structure") . "', '" .
_('Ok') . "', '" . _('Cancel') . "', '" . $templateClasses[$i]['typeId'] . "', 'export', '" . 'template_' . $templateClasses[$i]['typeId'] . "', '" . $_SESSION['config']->getName() . "');");
_('Ok') . "', '" . _('Cancel') . "', '" . $templateClass['typeId'] . "', 'export', '" . 'template_' . $templateClass['typeId'] . "', '" . $_SESSION['config']->getName() . "');");
$existingContainer->addElement($exportLink);
$existingContainer->addNewLine();
}
@ -314,12 +310,12 @@ include '../main_header.php';
echo "</form>\n";
echo "</div>\n";
for ($i = 0; $i < sizeof($templateClasses); $i++) {
$typeId = $templateClasses[$i]['typeId'];
$scope = $templateClasses[$i]['scope'];
foreach ($templateClasses as $templateClass) {
$typeId = $templateClass['typeId'];
$scope = $templateClass['scope'];
$importOptions = array();
foreach ($configProfiles as $profile) {
$typeManagerImport = new \LAM\TYPES\TypeManager($serverProfiles[$profile]);
$typeManagerImport = new TypeManager($serverProfiles[$profile]);
$typesImport = $typeManagerImport->getConfiguredTypesForScope($scope);
foreach ($typesImport as $typeImport) {
if (($profile != $_SESSION['config']->getName()) || ($typeImport->getId() != $typeId)) {
@ -374,7 +370,7 @@ include '../main_header.php';
$container->addElement(new htmlOutputText(_("Target server profile")), true);
$exportOptions = array();
foreach ($configProfiles as $profile) {
$typeManagerExport = new \LAM\TYPES\TypeManager($serverProfiles[$profile]);
$typeManagerExport = new TypeManager($serverProfiles[$profile]);
$typesExport = $typeManagerExport->getConfiguredTypesForScope($scope);
foreach ($typesExport as $typeExport) {
if (($profile != $_SESSION['config']->getName()) || ($typeExport->getId() != $typeId)) {
@ -430,18 +426,18 @@ include '../main_footer.php';
* @param string $typeId type id
* @param array $options options
* @param \LAMConfig[] $serverProfiles server profiles (name => profile object)
* @param \LAM\TYPES\TypeManager $typeManager type manager
* @param TypeManager $typeManager type manager
* @return \htmlStatusMessage message or null
*/
function importStructures($typeId, $options, &$serverProfiles, &$typeManager) {
function importStructures($typeId, $options, &$serverProfiles, TypeManager &$typeManager) {
foreach ($options as $option) {
$sourceConfName = $option['conf'];
$sourceTypeId = $option['typeId'];
$sourceName = $option['name'];
$sourceTypeManager = new \LAM\TYPES\TypeManager($serverProfiles[$sourceConfName]);
$sourceTypeManager = new TypeManager($serverProfiles[$sourceConfName]);
$sourceType = $sourceTypeManager->getConfiguredType($sourceTypeId);
$targetType = $typeManager->getConfiguredType($typeId);
if (($sourceType != null) && ($targetType != null)) {
if (($sourceType !== null) && ($targetType !== null)) {
try {
\LAM\PDF\copyStructure($sourceType, $sourceName, $targetType);
}
@ -460,12 +456,12 @@ function importStructures($typeId, $options, &$serverProfiles, &$typeManager) {
* @param string $name profile name
* @param array $options options
* @param \LAMConfig[] $serverProfiles server profiles (name => profile object)
* @param \LAM\TYPES\TypeManager $typeManager type manager
* @param TypeManager $typeManager type manager
* @return \htmlStatusMessage message or null
*/
function exportStructures($typeId, $name, $options, &$serverProfiles, &$typeManager) {
function exportStructures($typeId, $name, $options, &$serverProfiles, TypeManager &$typeManager) {
$sourceType = $typeManager->getConfiguredType($typeId);
if ($sourceType == null) {
if ($sourceType === null) {
return null;
}
foreach ($options as $option) {
@ -480,9 +476,9 @@ function exportStructures($typeId, $name, $options, &$serverProfiles, &$typeMana
}
else {
$targetTypeId = $option['typeId'];
$targetTypeManager = new \LAM\TYPES\TypeManager($serverProfiles[$targetConfName]);
$targetTypeManager = new TypeManager($serverProfiles[$targetConfName]);
$targetType = $targetTypeManager->getConfiguredType($targetTypeId);
if ($targetType != null) {
if ($targetType !== null) {
try {
\LAM\PDF\copyStructure($sourceType, $name, $targetType);
}

View File

@ -496,7 +496,7 @@ function translateFieldIDToName($id, $scope, $availablePDFFields) {
*
* @param PDFStructure $structure
*/
function updateBasicSettings(&$structure) {
function updateBasicSettings(PDFStructure &$structure) {
// set headline
if (isset($_POST['headline'])) {
$structure->setTitle(str_replace('<', '', str_replace('>', '', $_POST['headline'])));
@ -516,7 +516,7 @@ function updateBasicSettings(&$structure) {
*
* @param PDFStructure $structure
*/
function updateSectionTitles(&$structure) {
function updateSectionTitles(PDFStructure &$structure) {
$sections = $structure->getSections();
foreach ($_POST as $key => $value) {
if (strpos($key, 'section_') === 0) {
@ -531,7 +531,7 @@ function updateSectionTitles(&$structure) {
*
* @param PDFStructure $structure
*/
function addSection(&$structure) {
function addSection(PDFStructure &$structure) {
$sections = $structure->getSections();
// add a new text field
if(isset($_POST['add_text'])) {
@ -570,7 +570,7 @@ function addSection(&$structure) {
*
* @param PDFStructure $structure
*/
function addSectionEntry(&$structure) {
function addSectionEntry(PDFStructure &$structure) {
if(isset($_POST['add_new_field'])) {
$field = new PDFSectionEntry($_POST['new_field']);
$sections = $structure->getSections();
@ -587,7 +587,7 @@ function addSectionEntry(&$structure) {
*
* @param PDFStructure $structure
*/
function removeItem(&$structure) {
function removeItem(PDFStructure &$structure) {
$sections = $structure->getSections();
foreach ($_POST as $key => $value) {
// remove section
@ -617,7 +617,7 @@ function removeItem(&$structure) {
*
* @param PDFStructure $structure
*/
function moveUp(&$structure) {
function moveUp(PDFStructure &$structure) {
$sections = $structure->getSections();
foreach ($_POST as $key => $value) {
// move section
@ -649,7 +649,7 @@ function moveUp(&$structure) {
*
* @param PDFStructure $structure
*/
function moveDown(&$structure) {
function moveDown(PDFStructure &$structure) {
$sections = $structure->getSections();
foreach ($_POST as $key => $value) {
// move section

View File

@ -14,6 +14,7 @@ use \htmlOutputText;
use \htmlHelpLink;
use \htmlHiddenInput;
use \htmlInputField;
use \LAM\TYPES\TypeManager;
/*
$Id$
@ -67,7 +68,7 @@ if (!empty($_POST)) {
validateSecurityToken();
}
$typeManager = new \LAM\TYPES\TypeManager();
$typeManager = new TypeManager();
$types = $typeManager->getConfiguredTypes();
$profileClasses = array();
$profileClassesTemp = array();
@ -158,7 +159,7 @@ if (!empty($_POST['import'])) {
}
$errMessage = importProfiles($_POST['typeId'], $options, $serverProfiles, $typeManager);
}
if ($errMessage != null) {
if ($errMessage !== null) {
$errMessage->colspan = 10;
$container->addElement($errMessage, true);
}
@ -181,7 +182,7 @@ if (!empty($_POST['export'])) {
$name = $_POST['name_' . $typeId];
$errMessage = exportProfiles($typeId, $name, $options, $serverProfiles, $typeManager);
}
if ($errMessage != null) {
if ($errMessage !== null) {
$errMessage->colspan = 10;
$container->addElement($errMessage, true);
}
@ -274,7 +275,7 @@ for ($i = 0; $i < sizeof($profileClasses); $i++) {
$scope = $profileClasses[$i]['scope'];
$importOptions = array();
foreach ($configProfiles as $profile) {
$typeManagerImport = new \LAM\TYPES\TypeManager($serverProfiles[$profile]);
$typeManagerImport = new TypeManager($serverProfiles[$profile]);
$typesImport = $typeManagerImport->getConfiguredTypesForScope($scope);
foreach ($typesImport as $typeImport) {
if (($profile != $_SESSION['config']->getName()) || ($typeImport->getId() != $typeId)) {
@ -329,7 +330,7 @@ for ($i = 0; $i < sizeof($profileClasses); $i++) {
$container->addElement(new htmlOutputText(_("Target server profile")), true);
$exportOptions = array();
foreach ($configProfiles as $profile) {
$typeManagerExport = new \LAM\TYPES\TypeManager($serverProfiles[$profile]);
$typeManagerExport = new TypeManager($serverProfiles[$profile]);
$typesExport = $typeManagerExport->getConfiguredTypesForScope($scope);
foreach ($typesExport as $typeExport) {
if (($profile != $_SESSION['config']->getName()) || ($typeExport->getId() != $typeId)) {
@ -385,18 +386,18 @@ include '../main_footer.php';
* @param string $typeId type id
* @param array $options options
* @param \LAMConfig[] $serverProfiles server profiles (name => profile object)
* @param \LAM\TYPES\TypeManager $typeManager type manager
* @param TypeManager $typeManager type manager
* @return \htmlStatusMessage message or null
*/
function importProfiles($typeId, $options, &$serverProfiles, &$typeManager) {
function importProfiles($typeId, $options, &$serverProfiles, TypeManager &$typeManager) {
foreach ($options as $option) {
$sourceConfName = $option['conf'];
$sourceTypeId = $option['typeId'];
$sourceName = $option['name'];
$sourceTypeManager = new \LAM\TYPES\TypeManager($serverProfiles[$sourceConfName]);
$sourceTypeManager = new TypeManager($serverProfiles[$sourceConfName]);
$sourceType = $sourceTypeManager->getConfiguredType($sourceTypeId);
$targetType = $typeManager->getConfiguredType($typeId);
if (($sourceType != null) && ($targetType != null)) {
if (($sourceType !== null) && ($targetType !== null)) {
try {
\LAM\PROFILES\copyAccountProfile($sourceType, $sourceName, $targetType);
}
@ -415,12 +416,12 @@ function importProfiles($typeId, $options, &$serverProfiles, &$typeManager) {
* @param string $name profile name
* @param array $options options
* @param \LAMConfig[] $serverProfiles server profiles (name => profile object)
* @param \LAM\TYPES\TypeManager $typeManager type manager
* @param TypeManager $typeManager type manager
* @return \htmlStatusMessage message or null
*/
function exportProfiles($typeId, $name, $options, &$serverProfiles, &$typeManager) {
function exportProfiles($typeId, $name, $options, &$serverProfiles, TypeManager &$typeManager) {
$sourceType = $typeManager->getConfiguredType($typeId);
if ($sourceType == null) {
if ($sourceType === null) {
return null;
}
foreach ($options as $option) {
@ -435,9 +436,9 @@ function exportProfiles($typeId, $name, $options, &$serverProfiles, &$typeManage
}
else {
$targetTypeId = $option['typeId'];
$targetTypeManager = new \LAM\TYPES\TypeManager($serverProfiles[$targetConfName]);
$targetTypeManager = new TypeManager($serverProfiles[$targetConfName]);
$targetType = $targetTypeManager->getConfiguredType($targetTypeId);
if ($targetType != null) {
if ($targetType !== null) {
try {
\LAM\PROFILES\copyAccountProfile($sourceType, $name, $targetType);
}

View File

@ -125,13 +125,6 @@ if (isset($_POST['save'])) {
}
}
// remove double slashes if magic quotes are on
if (get_magic_quotes_gpc() == 1) {
foreach ($opt_keys as $element) {
if (isset($options[$element][0]) && is_string($options[$element][0])) $options[$element][0] = stripslashes($options[$element][0]);
}
}
// check options
$errors = checkProfileOptions($_POST['accounttype'], $options);
if (sizeof($errors) == 0) { // input data is valid, save profile
@ -169,12 +162,7 @@ if (isset($_POST['save'])) {
$postKeys = array_keys($_POST);
for ($i = 0; $i < sizeof($postKeys); $i++) {
if (!is_array($_POST[$postKeys[$i]])) {
if (get_magic_quotes_gpc() == 1) {
$old_options[$postKeys[$i]] = array(stripslashes($_POST[$postKeys[$i]]));
}
else {
$old_options[$postKeys[$i]] = array($_POST[$postKeys[$i]]);
}
$old_options[$postKeys[$i]] = array($_POST[$postKeys[$i]]);
}
else {
$old_options[$postKeys[$i]] = $_POST[$postKeys[$i]];
@ -241,7 +229,7 @@ for ($m = 0; $m < sizeof($modules); $m++) {
if (sizeof($options[$modules[$m]]) < 1) continue;
$module = new $modules[$m]($type->getScope());
$icon = $module->getIcon();
if (($icon != null) && !(strpos($icon, 'http') === 0) && !(strpos($icon, '/') === 0)) {
if (!empty($icon) && !(strpos($icon, 'http') === 0) && !(strpos($icon, '/') === 0)) {
$icon = '../../graphics/' . $icon;
}
$container = new htmlTable();

View File

@ -1,4 +1,18 @@
<?php
namespace LAM\TOOLS\TESTS;
use \LAM\REMOTE\Remote;
use \htmlTable;
use \htmlTitle;
use \htmlOutputText;
use \htmlSelect;
use \htmlInputCheckbox;
use \htmlSpacer;
use \htmlButton;
use \htmlStatusMessage;
use \htmlImage;
use \htmlSubTitle;
use \Exception;
/*
$Id$
@ -22,7 +36,7 @@ $Id$
*/
/**
* Tests the lamdaemon script.
* Tests the remote script.
*
* @author Roland Gruber
* @author Thomas Manninger
@ -67,7 +81,7 @@ for ($i = 0; $i < sizeof($servers); $i++) {
}
if (isset($_POST['runTest'])) {
lamRunLamdaemonTestSuite($_POST['server'], $serverTitles[$_POST['server']] , isset($_POST['checkQuotas']), $container);
lamRunTestSuite($_POST['server'], $serverTitles[$_POST['server']] , isset($_POST['checkQuotas']), $container);
}
else if ((sizeof($servers) > 0) && isset($servers[0]) && ($servers[0] != '')) {
$container->addElement(new htmlOutputText(_("Server")));
@ -111,22 +125,22 @@ include '../main_footer.php';
*
* @param string $command test command
* @param boolean $stopTest specifies if test should be run
* @param connection $handle SSH connection
* @param Remote $remote SSH connection
* @param string $testText describing text
* @param htmlTable $container container for HTML output
* @return boolean true, if errors occured
*/
function lamTestLamdaemon($command, $stopTest, $handle, $testText, $container) {
function testRemoteCommand($command, $stopTest, $remote, $testText, $container) {
$okImage = "../../graphics/pass.png";
$failImage = "../../graphics/fail.png";
$spacer = new htmlSpacer('10px', null);
// run lamdaemon and get user quotas
// run remote command
if (!$stopTest) {
$container->addElement(new htmlOutputText($testText));
$container->addElement($spacer);
flush();
$lamdaemonOk = false;
$output = $handle->exec("sudo " . $_SESSION['config']->get_scriptPath() . ' ' . escapeshellarg($command));
$output = $remote->execute($command);
if ((stripos(strtolower($output), "error") === false) && ((strpos($output, 'INFO,') === 0) || (strpos($output, 'QUOTA_ENTRY') === 0))) {
$lamdaemonOk = true;
}
@ -170,7 +184,7 @@ function lamTestLamdaemon($command, $stopTest, $handle, $testText, $container) {
* @param boolean $testQuota true, if Quotas should be checked
* @param htmlTable $container container for HTML output
*/
function lamRunLamdaemonTestSuite($serverName, $serverTitle, $testQuota, $container) {
function lamRunTestSuite($serverName, $serverTitle, $testQuota, $container) {
$SPLIT_DELIMITER = "###x##y##x###";
$LAMDAEMON_PROTOCOL_VERSION = '5';
$okImage = "../../graphics/pass.png";
@ -246,13 +260,14 @@ function lamRunLamdaemonTestSuite($serverName, $serverTitle, $testQuota, $contai
flush();
// check SSH login
$remote = new Remote();
if (!$stopTest) {
$container->addElement(new htmlOutputText(_("SSH connection")));
$container->addElement($spacer);
flush();
$sshOk = false;
try {
$handle = lamConnectSSH($serverName);
$remote->connect($serverName);
$container->addElement(new htmlImage($okImage));
$container->addElement($spacer);
$container->addElement(new htmlOutputText(_("SSH connection established.")), true);
@ -268,23 +283,21 @@ function lamRunLamdaemonTestSuite($serverName, $serverTitle, $testQuota, $contai
flush();
if (!$stopTest) {
$stopTest = lamTestLamdaemon("+" . $SPLIT_DELIMITER . "test" . $SPLIT_DELIMITER . "basic", $stopTest, $handle, _("Execute lamdaemon"), $container);
$stopTest = testRemoteCommand("+" . $SPLIT_DELIMITER . "test" . $SPLIT_DELIMITER . "basic", $stopTest, $remote, _("Execute lamdaemon"), $container);
}
if (!$stopTest) {
$stopTest = lamTestLamdaemon("+" . $SPLIT_DELIMITER . "test" . $SPLIT_DELIMITER . "version" . $SPLIT_DELIMITER . $LAMDAEMON_PROTOCOL_VERSION, $stopTest, $handle, _("Lamdaemon version"), $container);
$stopTest = testRemoteCommand("+" . $SPLIT_DELIMITER . "test" . $SPLIT_DELIMITER . "version" . $SPLIT_DELIMITER . $LAMDAEMON_PROTOCOL_VERSION, $stopTest, $remote, _("Lamdaemon version"), $container);
}
if (!$stopTest) {
$handle = lamConnectSSH($serverName);
$stopTest = lamTestLamdaemon("+" . $SPLIT_DELIMITER . "test" . $SPLIT_DELIMITER . "nss" . $SPLIT_DELIMITER . "$userName", $stopTest, $handle, _("Lamdaemon: check NSS LDAP"), $container);
$stopTest = testRemoteCommand("+" . $SPLIT_DELIMITER . "test" . $SPLIT_DELIMITER . "nss" . $SPLIT_DELIMITER . "$userName", $stopTest, $remote, _("Lamdaemon: check NSS LDAP"), $container);
if (!$stopTest && $testQuota) {
$handle = lamConnectSSH($serverName);
$stopTest = lamTestLamdaemon("+" . $SPLIT_DELIMITER . "test" . $SPLIT_DELIMITER . "quota", $stopTest, $handle, _("Lamdaemon: Quota module installed"), $container);
$handle = lamConnectSSH($serverName);
$stopTest = lamTestLamdaemon("+" . $SPLIT_DELIMITER . "quota" . $SPLIT_DELIMITER . "get" . $SPLIT_DELIMITER . "user", $stopTest, $handle, _("Lamdaemon: read quotas"), $container);
$stopTest = testRemoteCommand("+" . $SPLIT_DELIMITER . "test" . $SPLIT_DELIMITER . "quota", $stopTest, $remote, _("Lamdaemon: Quota module installed"), $container);
$stopTest = testRemoteCommand("+" . $SPLIT_DELIMITER . "quota" . $SPLIT_DELIMITER . "get" . $SPLIT_DELIMITER . "user", $stopTest, $remote, _("Lamdaemon: read quotas"), $container);
}
}
$remote->disconnect();
$container->addElement(new htmlSpacer(null, '10px'), true);
$endMessage = new htmlOutputText(_("Lamdaemon test finished."));

View File

@ -140,7 +140,7 @@ if ($_FILES['inputfile'] && ($_FILES['inputfile']['size'] > 0)) {
$checkcolumns = array();
$columns = call_user_func_array('array_merge', $columns);
for ($i = 0; $i < sizeof($columns); $i++) {
if (isset($columns[$i]['required']) && ($columns[$i]['required'] == true)) {
if (isset($columns[$i]['required']) && ($columns[$i]['required'] === true)) {
if (isset($ids[$columns[$i]['name']])) $checkcolumns[] = $ids[$columns[$i]['name']];
else $errors[] = array(_("A required column is missing in your CSV file."), $columns[$i]['name']);
}
@ -201,7 +201,7 @@ if ($_FILES['inputfile'] && ($_FILES['inputfile']['size'] > 0)) {
// let modules build accounts
else {
$accounts = buildUploadAccounts($type, $data, $ids, $selectedModules);
if ($accounts != false) {
if ($accounts !== false) {
$rdnList = getRDNAttributes($type->getId(), $selectedModules);
$suffix = $type->getSuffix();
// set DN
@ -282,7 +282,7 @@ include '../main_footer.php';
* @param array $selectedModules selected modules for upload
* @param htmlTable $container table container
*/
function massPrintBackButton($typeId, $selectedModules, &$container) {
function massPrintBackButton($typeId, $selectedModules, htmlTable &$container) {
$backButton = new htmlButton('submit', _('Back'));
$backButton->setIconClass('backButton');
$container->addElement($backButton);
@ -298,4 +298,4 @@ function massPrintBackButton($typeId, $selectedModules, &$container) {
}
}
?>
?>

View File

@ -256,7 +256,7 @@ include '../main_footer.php';
* @param \LAM\TYPES\ConfiguredType $type account type
* @param array $selectedModules list of selected account modules
*/
function showMainPage($type, $selectedModules) {
function showMainPage(\LAM\TYPES\ConfiguredType $type, $selectedModules) {
$scope = $type->getScope();
echo '<div class="' . $scope . '-bright smallPaddingContent">';
// get input fields from modules
@ -382,7 +382,7 @@ function showMainPage($type, $selectedModules) {
$columnContainer->addElement(new htmlSpacer(null, '10px'), true);
$module = moduleCache::getModule($modules[$m], $scope);
$icon = $module->getIcon();
if (($icon != null) && !(strpos($icon, 'http') === 0) && !(strpos($icon, '/') === 0)) {
if (!empty($icon) && !(strpos($icon, 'http') === 0) && !(strpos($icon, '/') === 0)) {
$icon = '../../graphics/' . $icon;
}
$moduleTitle = new htmlSubTitle(getModuleAlias($modules[$m], $scope), $icon);
@ -413,7 +413,7 @@ function showMainPage($type, $selectedModules) {
$odd = true;
for ($i = 0; $i < sizeof($columns[$modules[$m]]); $i++) {
$required = false;
if (isset($columns[$modules[$m]][$i]['required']) && ($columns[$modules[$m]][$i]['required'] == true)) {
if (isset($columns[$modules[$m]][$i]['required']) && ($columns[$modules[$m]][$i]['required'] === true)) {
$required = true;
}
$rowCells = array();