Feature #22685 » form-protection-v1.diff
t3lib/class.t3lib_beuserauth.php (working copy) | ||
---|---|---|
* This class contains the configuration of the database fields used plus some functions for the authentication process of backend users.
|
||
*
|
||
* @author Kasper Skaarhoj <kasperYYYY@typo3.com>
|
||
* @author Oliver Klee <typo3-coding@oliverklee.de>
|
||
*
|
||
* @package TYPO3
|
||
* @subpackage t3lib
|
||
*/
|
||
... | ... | |
'resizeTextareas_Flexible' => 1,
|
||
);
|
||
/**
|
||
* an instance of the form protection for BE forms
|
||
*
|
||
* @var unknown_type
|
||
*/
|
||
protected $formProtection = null;
|
||
/**
|
||
* The destructor. Frees as much memory used by this object as possible.
|
||
*/
|
||
public function __destruct() {
|
||
if ($this->formProtection !== null) {
|
||
$this->formProtection->__destruct();
|
||
$this->formProtection = null;
|
||
}
|
||
}
|
||
/**
|
||
* Sets the security level for the Backend login
|
||
... | ... | |
* + backend user is a regular user and adminOnly is not defined
|
||
* + backend user is an admin user
|
||
* + backend user is used in CLI context and adminOnly is explicitely set to "2"
|
||
*
|
||
*
|
||
* @return boolean Whether a backend user is allowed to access the backend
|
||
*/
|
||
protected function isUserAllowedToLogin() {
|
||
... | ... | |
return $isUserAllowedToLogin;
|
||
}
|
||
}
|
||
/**
|
||
* Returns the BE form protection instance.
|
||
*
|
||
* @return t3lib_formProtection_backend the BE form protection instance.
|
||
*/
|
||
public function getFormProtection() {
|
||
if ($this->formProtection == null) {
|
||
$this->formProtection = t3lib_div::makeInstance(
|
||
't3lib_formProtection_backend'
|
||
);
|
||
}
|
||
return $this->formProtection;
|
||
}
|
||
/**
|
||
* Logs out the current user and clears the form protection tokens.
|
||
*/
|
||
public function logoff() {
|
||
$this->getFormProtection()->clean();
|
||
parent::logoff();
|
||
}
|
||
}
|
||
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_beuserauth.php']) {
|
||
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_beuserauth.php']);
|
||
}
|
||
?>
|
t3lib/core_autoload.php (working copy) | ||
---|---|---|
't3lib_error_errorhandlerinterface' => PATH_t3lib . 'error/interface.t3lib_error_errorhandlerinterface.php',
|
||
't3lib_error_exceptionhandlerinterface' => PATH_t3lib . 'error/interface.t3lib_error_exceptionhandlerinterface.php',
|
||
't3lib_browselinkshook' => PATH_t3lib . 'interfaces/interface.t3lib_browselinkshook.php',
|
||
't3lib_formprotection_abstract' => PATH_t3lib . 'formprotection/class.t3lib_formprotection_abstract.php',
|
||
't3lib_formprotection_backend' => PATH_t3lib . 'formprotection/class.t3lib_formprotection_backend.php',
|
||
't3lib_localrecordlistgettablehook' => PATH_t3lib . 'interfaces/interface.t3lib_localrecordlistgettablehook.php',
|
||
't3lib_pageselect_getpagehook' => PATH_t3lib . 'interfaces/interface.t3lib_pageselect_getpagehook.php',
|
||
't3lib_pageselect_getrecordoverlayhook' => PATH_t3lib . 'interfaces/interface.t3lib_pageselect_getrecordoverlayhook.php',
|
t3lib/formprotection/class.t3lib_formprotection_backend.php (revision 0) | ||
---|---|---|
<?php
|
||
/***************************************************************
|
||
* Copyright notice
|
||
*
|
||
* (c) 2010 Oliver Klee <typo3-coding@oliverklee.de>
|
||
* All rights reserved
|
||
*
|
||
* This script is part of the TYPO3 project. The TYPO3 project 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.
|
||
*
|
||
* The GNU General Public License can be found at
|
||
* http://www.gnu.org/copyleft/gpl.html.
|
||
*
|
||
* This script 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.
|
||
*
|
||
* This copyright notice MUST APPEAR in all copies of the script!
|
||
***************************************************************/
|
||
/**
|
||
* Class t3lib_formProtection_backend.
|
||
*
|
||
* This class provides protection against cross-site request forgery (XSRF)
|
||
* for forms in the BE.
|
||
*
|
||
* @package TYPO3
|
||
* @subpackage t3lib
|
||
*
|
||
* @author Oliver Klee <typo3-coding@oliverklee.de>
|
||
*/
|
||
class t3lib_formProtection_backend extends t3lib_formProtection_abstract {
|
||
/**
|
||
* the maximum number of tokens that can exist at the same time
|
||
*
|
||
* @var integer
|
||
*/
|
||
protected $maximumNumberOfTokens = 20000;
|
||
/**
|
||
* Retrieves all saved tokens.
|
||
*
|
||
* @return array the saved tokens as a two-dimensional array, will be empty
|
||
* if no tokens have been saved
|
||
*/
|
||
protected function retrieveTokens() {
|
||
$tokens = $GLOBALS['BE_USER']->getSessionData('formTokens');
|
||
if (!is_array($tokens)) {
|
||
$tokens = array();
|
||
}
|
||
$this->tokens = $tokens;
|
||
}
|
||
/**
|
||
* Saves the tokens so that they can be used by a later incarnation of this
|
||
* class.
|
||
*/
|
||
public function persistTokens() {
|
||
$GLOBALS['BE_USER']->setAndSaveSessionData('formTokens', $this->tokens);
|
||
}
|
||
}
|
||
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/formprotection/class.t3lib_formprotection_backend.php']) {
|
||
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/formprotection/class.t3lib_formprotection_backend.php']);
|
||
}
|
||
?>
|
t3lib/formprotection/class.t3lib_formprotection_abstract.php (revision 0) | ||
---|---|---|
<?php
|
||
/***************************************************************
|
||
* Copyright notice
|
||
*
|
||
* (c) 2010 Oliver Klee <typo3-coding@oliverklee.de>
|
||
* All rights reserved
|
||
*
|
||
* This script is part of the TYPO3 project. The TYPO3 project 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.
|
||
*
|
||
* The GNU General Public License can be found at
|
||
* http://www.gnu.org/copyleft/gpl.html.
|
||
*
|
||
* This script 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.
|
||
*
|
||
* This copyright notice MUST APPEAR in all copies of the script!
|
||
***************************************************************/
|
||
/**
|
||
* Class t3lib_formProtection_abstract
|
||
*
|
||
* This class provides protection against cross-site request forgery (XSRF)
|
||
* for forms.
|
||
*
|
||
* @package TYPO3
|
||
* @subpackage t3lib
|
||
*
|
||
* @author Oliver Klee <typo3-coding@oliverklee.de>
|
||
*/
|
||
abstract class t3lib_formProtection_abstract {
|
||
/**
|
||
* the maximum number of tokens that can exist at the same time
|
||
*
|
||
* @var integer
|
||
*/
|
||
protected $maximumNumberOfTokens = 0;
|
||
/**
|
||
* Valid tokens sorted from oldest to newest.
|
||
*
|
||
* [tokenId] => array(formName, formInstanceName)
|
||
*
|
||
* @var array
|
||
*/
|
||
protected $tokens = array();
|
||
/**
|
||
* Constructor. Makes sure existing tokens are read and available for
|
||
* checking.
|
||
*/
|
||
public function __construct() {
|
||
$this->retrieveTokens();
|
||
}
|
||
/**
|
||
* Frees as much memory as possible.
|
||
*/
|
||
public function __destruct() {
|
||
$this->tokens = array();
|
||
}
|
||
/**
|
||
* Deletes all existing tokens and persists the (empty) token table.
|
||
*
|
||
* This function is intended to be called when a user logs on or off.
|
||
*/
|
||
public function clean() {
|
||
$this->tokens = array();
|
||
$this->persistTokens();
|
||
}
|
||
/**
|
||
* Generates and stores a token for a form.
|
||
*
|
||
* Calling this function two times with the same parameters will create
|
||
* two valid, different tokens.
|
||
*
|
||
* Generating more tokens than $maximumNumberOfEntries will cause the oldest
|
||
* tokens to get dropped.
|
||
*
|
||
* Note: This function does not persist the tokens.
|
||
*
|
||
* @param string $formName
|
||
* the name of the form, for example a table name like "tt_content",
|
||
* or some other identifier like "install_tool_password", must not be
|
||
* empty
|
||
* @param string $formInstanceName
|
||
* a string used to differentiate two instances of the same form,
|
||
* form example a record UID or a comma-separated list of UIDs,
|
||
* may also be empty
|
||
*
|
||
* @return string the 32-character hex ID of the generated token
|
||
*/
|
||
public function generateToken($formName, $formInstanceName = '') {
|
||
if ($formName == '') {
|
||
throw new InvalidArgumentException('$formName must not be empty.');
|
||
}
|
||
do {
|
||
$tokenId = bin2hex(t3lib_div::generateRandomBytes(16));
|
||
} while (isset($this->tokens[$tokenId]));
|
||
$this->tokens[$tokenId] = array(
|
||
'formName' => $formName,
|
||
'formInstanceName' => $formInstanceName,
|
||
);
|
||
$this->preventOverflow();
|
||
return $tokenId;
|
||
}
|
||
/**
|
||
* Checks whether the token $tokenId is valid in the form $formName with
|
||
* $formInstanceName.
|
||
*
|
||
* A token is valid if $tokenId, $formName and $formInstanceName match and
|
||
* the token has not been used yet.
|
||
*
|
||
* Calling this function will mark the token $tokenId as invalud (if it
|
||
* exists).
|
||
*
|
||
* So calling this function with the same parameters two times will return
|
||
* FALSE the second time.
|
||
*
|
||
* The caller is expected to silently ignore the form data if a token is
|
||
* invalid in order to provide as little feedback as possible to brute-force
|
||
* attacks.
|
||
*
|
||
* @param string $tokenId
|
||
* a form token to check, may also be empty or utterly misformed
|
||
* @param string $formName
|
||
* the name of the form to check, for example "tt_content",
|
||
* may also be empty or utterly misformed
|
||
* @param string $formInstanceName
|
||
* the instance name of the form to check, for example "42",
|
||
* may also be empty or utterly misformed
|
||
*
|
||
* @return boolean TRUE $tokenId, $formName, $formInstanceName match and
|
||
* the token has not been used yet, FALSE otherwise
|
||
*/
|
||
public function validateToken($tokenId, $formName, $formInstanceName = '') {
|
||
if (isset($this->tokens[$tokenId])) {
|
||
$token = $this->tokens[$tokenId];
|
||
$isValid = ($token['formName'] == $formName)
|
||
&& ($token['formInstanceName'] == $formInstanceName);
|
||
$this->dropToken($tokenId);
|
||
} else {
|
||
$isValid = FALSE;
|
||
}
|
||
return $isValid;
|
||
}
|
||
/**
|
||
* Retrieves all saved tokens.
|
||
*
|
||
* @return array the saved tokens as a two-dimensional array, will be empty
|
||
* if no tokens have been saved
|
||
*/
|
||
abstract protected function retrieveTokens();
|
||
/**
|
||
* Saves the tokens so that they can be used by a later incarnation of this
|
||
* class.
|
||
*/
|
||
abstract public function persistTokens();
|
||
/**
|
||
* Drops the token with the ID $tokenId.
|
||
*
|
||
* If there is no token with that ID, this function is a no-op.
|
||
*
|
||
* Note: This function does not persist the tokens.
|
||
*
|
||
* @param string $tokenId
|
||
* the 32-character ID of an existing token, must not be empty
|
||
*/
|
||
protected function dropToken($tokenId) {
|
||
if (isset($this->tokens[$tokenId])) {
|
||
unset($this->tokens[$tokenId]);
|
||
}
|
||
}
|
||
/**
|
||
* Checks whether the number of current tokens still is at most
|
||
* $this->maximumNumberOfTokens.
|
||
*
|
||
* If there are more tokens, the oldest tokens are removed until the number
|
||
* of tokens is low enough.
|
||
*
|
||
* Note: This function does not persist the tokens.
|
||
*/
|
||
protected function preventOverflow() {
|
||
if (empty($this->tokens)) {
|
||
return;
|
||
}
|
||
while (count($this->tokens) > $this->maximumNumberOfTokens) {
|
||
reset($this->tokens);
|
||
$this->dropToken(key($this->tokens));
|
||
}
|
||
}
|
||
}
|
||
?>
|
typo3/sysext/setup/mod/index.php (working copy) | ||
---|---|---|
/**
|
||
* If settings are submitted to _POST[DATA], store them
|
||
* NOTICE: This method is called before the template.php is included. See buttom of document
|
||
*
|
||
* @return void
|
||
* NOTICE: This method is called before the template.php is included. See
|
||
* bottom of document.
|
||
*/
|
||
function storeIncomingData() {
|
||
public function storeIncomingData() {
|
||
/* @var $BE_USER t3lib_beUserAuth */
|
||
global $BE_USER;
|
||
... | ... | |
$storeRec = array();
|
||
$fieldList = $this->getFieldsFromShowItem();
|
||
if (is_array($d)) {
|
||
if (is_array($d) && $BE_USER->getFormProtection()->validateToken(
|
||
(string) t3lib_div::_POST('formToken'),
|
||
'BE user setup', $BE__USER->user['uid']
|
||
)
|
||
) {
|
||
// UC hashed before applying changes
|
||
$save_before = md5(serialize($BE_USER->uc));
|
||
... | ... | |
$this->content .= $this->doc->spacer(20) . $this->doc->getDynTabMenu($menuItems, 'user-setup', false, false, 100, 1, false, 1, $this->dividers2tabs);
|
||
$formToken = $BE_USER->getFormProtection()->generateToken(
|
||
'BE user setup', $BE__USER->user['uid']
|
||
);
|
||
// Submit and reset buttons
|
||
$this->content .= $this->doc->spacer(20);
|
||
$this->content .= $this->doc->section('',
|
||
t3lib_BEfunc::cshItem('_MOD_user_setup', 'reset', $BACK_PATH) . '
|
||
<input type="hidden" name="simUser" value="'.$this->simUser.'" />
|
||
<input type="hidden" name="formToken" value="' . $formToken . '" />
|
||
<input type="submit" name="data[save]" value="'.$LANG->getLL('save').'" />
|
||
<input type="submit" name="data[setValuesToDefault]" value="'.$LANG->getLL('resetConfiguration').'" onclick="return confirm(\''.$LANG->getLL('setToStandardQuestion').'\');" />
|
||
<input type="submit" name="data[clearSessionVars]" value="' . $LANG->getLL('clearSessionVars') . '" onclick="return confirm(\'' . $LANG->getLL('clearSessionVarsQuestion') . '\');" />'
|
||
);
|
||
// Notice
|
||
$this->content .= $this->doc->spacer(30);
|
||
$flashMessage = t3lib_div::makeInstance(
|
||
... | ... | |
}
|
||
return t3lib_BEfunc::cshItem('_MOD_user_setup', $str, $this->doc->backPath, '|', false, 'margin-bottom:0px;');
|
||
}
|
||
|
||
/**
|
||
* Returns array with fields defined in $GLOBALS['TYPO3_USER_SETTINGS']['showitem']
|
||
*
|
||
*
|
||
* @param void
|
||
* @return array array with fieldnames visible in form
|
||
*/
|
||
... | ... | |
$SOBE->init();
|
||
$SOBE->main();
|
||
$SOBE->printContent();
|
||
$GLOBALS['BE_USER']->getFormProtection()->persistTokens();
|
||
?>
|
tests/t3lib/t3lib_beuserauthTest.php (revision 0) | ||
---|---|---|
<?php
|
||
/***************************************************************
|
||
* Copyright notice
|
||
*
|
||
* (c) 2010 Oliver Klee (typo3-coding@oliverklee.de)
|
||
* All rights reserved
|
||
*
|
||
* This script is part of the TYPO3 project. The TYPO3 project 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.
|
||
*
|
||
* The GNU General Public License can be found at
|
||
* http://www.gnu.org/copyleft/gpl.html.
|
||
*
|
||
* This script 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.
|
||
*
|
||
* This copyright notice MUST APPEAR in all copies of the script!
|
||
***************************************************************/
|
||
/**
|
||
* Testcase for the t3lib_beUserAuth class in the TYPO3 Core extension.
|
||
*
|
||
* @package TYPO3
|
||
* @subpackage t3lib
|
||
*
|
||
* @author Oliver Klee <typo3-coding@oliverklee.de>
|
||
*/
|
||
class t3lib_beUserAuthTest extends tx_phpunit_testcase {
|
||
/**
|
||
* @var t3lib_beUserAuth
|
||
*/
|
||
private $fixture;
|
||
public function setUp() {
|
||
$this->fixture = new t3lib_beUserAuth();
|
||
}
|
||
public function tearDown() {
|
||
$this->fixture->__destruct();
|
||
unset($this->fixture);
|
||
}
|
||
/////////////////////////////////////////
|
||
// Tests concerning the form protection
|
||
/////////////////////////////////////////
|
||
/**
|
||
* @test
|
||
*/
|
||
public function getFormProtectectionReturnsBackEndFormProtectionInstance() {
|
||
$this->assertTrue(
|
||
$this->fixture->getFormProtection()
|
||
instanceof t3lib_formProtection_backend
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function getFormProtectectionCalledTwoTimesReturnsSameInstance() {
|
||
$this->assertSame(
|
||
$this->fixture->getFormProtection(),
|
||
$this->fixture->getFormProtection()
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function logoffCleansFormProtection() {
|
||
$className = uniqid('t3lib_beUserAuth');
|
||
eval(
|
||
'class ' . $className . ' extends t3lib_beUserAuth {' .
|
||
'public function setFormProtection(t3lib_formProtection_backend $formProtection) {' .
|
||
'$this->formProtection = $formProtection;' .
|
||
'}' .
|
||
'}'
|
||
);
|
||
$formProtection = $this->getMock(
|
||
't3lib_formProtection_backend', array('clean')
|
||
);
|
||
$formProtection->expects($this->atLeastOnce())->method('clean');
|
||
$fixture = new $className();
|
||
$fixture->setFormProtection($formProtection);
|
||
$fixture->logoff();
|
||
$fixture->__destruct();
|
||
}
|
||
}
|
||
?>
|
tests/t3lib/formprotection/fixtures/class.t3lib_formprotection_testing.php (revision 0) | ||
---|---|---|
<?php
|
||
/***************************************************************
|
||
* Copyright notice
|
||
*
|
||
* (c) 2010 Oliver Klee <typo3-coding@oliverklee.de>
|
||
* All rights reserved
|
||
*
|
||
* This script is part of the TYPO3 project. The TYPO3 project 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.
|
||
*
|
||
* The GNU General Public License can be found at
|
||
* http://www.gnu.org/copyleft/gpl.html.
|
||
*
|
||
* This script 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.
|
||
*
|
||
* This copyright notice MUST APPEAR in all copies of the script!
|
||
***************************************************************/
|
||
/**
|
||
* Class t3lib_formProtection_testing.
|
||
*
|
||
* This class provides protection against cross-site request forgery (XSRF)
|
||
* for forms in the BE.
|
||
*
|
||
* @package TYPO3
|
||
* @subpackage t3lib
|
||
*
|
||
* @author Oliver Klee <typo3-coding@oliverklee.de>
|
||
*/
|
||
class t3lib_formProtection_testing extends t3lib_formProtection_abstract {
|
||
/**
|
||
* the maximum number of tokens that can exist at the same time
|
||
*
|
||
* @var integer
|
||
*/
|
||
protected $maximumNumberOfTokens = 100;
|
||
/**
|
||
* Sets the maximum number of tokens that can exist at the same time.
|
||
*
|
||
* @param integer $number maximum number of tokens, must be > 0
|
||
*/
|
||
public function setMaximumNumberOfTokens($number) {
|
||
$this->maximumNumberOfTokens = $number;
|
||
}
|
||
/**
|
||
* Retrieves all saved tokens.
|
||
*
|
||
* @return array the saved tokens as a two-dimensional array, will be empty
|
||
* if no tokens have been saved
|
||
*/
|
||
protected function retrieveTokens() {}
|
||
/**
|
||
* Saves the tokens so that they can be used by a later incarnation of this
|
||
* class.
|
||
*/
|
||
public function persistTokens() {}
|
||
/**
|
||
* Drops the token with the ID $tokenId and persists all tokens.
|
||
*
|
||
* If there is no token with that ID, this function is a no-op.
|
||
*
|
||
* @param string $tokenId
|
||
* the 32-character ID of an existing token, must not be empty
|
||
*/
|
||
public function dropToken($tokenId) {
|
||
parent::dropToken($tokenId);
|
||
}
|
||
}
|
||
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/formprotection/class.t3lib_formprotection_testing.php']) {
|
||
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/formprotection/class.t3lib_formprotection_testing.php']);
|
||
}
|
||
?>
|
tests/t3lib/formprotection/t3lib_formprotectionTest.php (revision 0) | ||
---|---|---|
<?php
|
||
/***************************************************************
|
||
* Copyright notice
|
||
*
|
||
* (c) 2010 Oliver Klee (typo3-coding@oliverklee.de)
|
||
* All rights reserved
|
||
*
|
||
* This script is part of the TYPO3 project. The TYPO3 project 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.
|
||
*
|
||
* The GNU General Public License can be found at
|
||
* http://www.gnu.org/copyleft/gpl.html.
|
||
*
|
||
* This script 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.
|
||
*
|
||
* This copyright notice MUST APPEAR in all copies of the script!
|
||
***************************************************************/
|
||
require_once('fixtures/class.t3lib_formprotection_testing.php');
|
||
/**
|
||
* Testcase for the t3lib_formProtection_abstract class.
|
||
*
|
||
* @package TYPO3
|
||
* @subpackage t3lib
|
||
*
|
||
* @author Oliver Klee <typo3-coding@oliverklee.de>
|
||
*/
|
||
class t3lib_formProtectionTest extends tx_phpunit_testcase {
|
||
/**
|
||
* @var t3lib_formProtection_testing
|
||
*/
|
||
private $fixture;
|
||
public function setUp() {
|
||
$this->fixture = new t3lib_formProtection_testing();
|
||
}
|
||
public function tearDown() {
|
||
$this->fixture->__destruct();
|
||
unset($this->fixture);
|
||
}
|
||
/////////////////////////////////////////
|
||
// Tests concerning the basic functions
|
||
/////////////////////////////////////////
|
||
/**
|
||
* @test
|
||
*/
|
||
public function constructionRetrievesTokens() {
|
||
$className = uniqid('t3lib_formProtection');
|
||
eval(
|
||
'class ' . $className . ' extends t3lib_formProtection_testing {' .
|
||
'public $tokensHaveBeenRetrieved = FALSE; ' .
|
||
'protected function retrieveTokens() {' .
|
||
'$this->tokensHaveBeenRetrieved = TRUE;' .
|
||
'}' .
|
||
'}'
|
||
);
|
||
$fixture = new $className();
|
||
$this->assertTrue(
|
||
$fixture->tokensHaveBeenRetrieved
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function cleanMakesTokenInvalid() {
|
||
$formName = 'foo';
|
||
$tokenId = $this->fixture->generateToken($formName);
|
||
$this->fixture->clean();
|
||
$this->assertFalse(
|
||
$this->fixture->validateToken($tokenId, $formName)
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function cleanPersistsTokens() {
|
||
$fixture = $this->getMock(
|
||
't3lib_formProtection_testing', array('persistTokens')
|
||
);
|
||
$fixture->expects($this->once())->method('persistTokens');
|
||
$fixture->clean();
|
||
}
|
||
///////////////////////////////////
|
||
// Tests concerning generateToken
|
||
///////////////////////////////////
|
||
/**
|
||
* @test
|
||
*/
|
||
public function generateTokenFormForEmptyFormNameThrowsException() {
|
||
$this->setExpectedException(
|
||
'InvalidArgumentException', '$formName must not be empty.'
|
||
);
|
||
$this->fixture->generateToken('', 'bar');
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function generateTokenFormForEmptyFormInstanceNameNotThrowsException() {
|
||
$this->fixture->generateToken('foo', '');
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function generateTokenFormForOmittedFormInstanceNameNotThrowsException() {
|
||
$this->fixture->generateToken('foo');
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function generateTokenReturns32CharacterHexToken() {
|
||
$this->assertRegexp(
|
||
'/^[0-9a-f]{32}$/',
|
||
$this->fixture->generateToken('foo')
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function generateTokenCalledTwoTimesWithSameParametersReturnsDifferentTokens() {
|
||
$this->assertNotEquals(
|
||
$this->fixture->generateToken('foo', 'bar'),
|
||
$this->fixture->generateToken('foo', 'bar')
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function generatingTooManyTokensInvalidatesOldestToken() {
|
||
$this->fixture->setMaximumNumberOfTokens(2);
|
||
$formName = 'foo';
|
||
$formInstanceName = 'bar';
|
||
$token1 = $this->fixture->generateToken($formName, $formInstanceName);
|
||
$token2 = $this->fixture->generateToken($formName, $formInstanceName);
|
||
$token3 = $this->fixture->generateToken($formName, $formInstanceName);
|
||
$this->assertFalse(
|
||
$this->fixture->validateToken($token1, $formName, $formInstanceName)
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function generatingTooManyTokensNotInvalidatesNewestToken() {
|
||
$this->fixture->setMaximumNumberOfTokens(2);
|
||
$formName = 'foo';
|
||
$formInstanceName = 'bar';
|
||
$token1 = $this->fixture->generateToken($formName, $formInstanceName);
|
||
$token2 = $this->fixture->generateToken($formName, $formInstanceName);
|
||
$token3 = $this->fixture->generateToken($formName, $formInstanceName);
|
||
$this->assertTrue(
|
||
$this->fixture->validateToken($token3, $formName, $formInstanceName)
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function generatingTooManyTokensNotInvalidatesTokenInTheMiddle() {
|
||
$this->fixture->setMaximumNumberOfTokens(2);
|
||
$formName = 'foo';
|
||
$formInstanceName = 'bar';
|
||
$token1 = $this->fixture->generateToken($formName, $formInstanceName);
|
||
$token2 = $this->fixture->generateToken($formName, $formInstanceName);
|
||
$token3 = $this->fixture->generateToken($formName, $formInstanceName);
|
||
$this->assertTrue(
|
||
$this->fixture->validateToken($token2, $formName, $formInstanceName)
|
||
);
|
||
}
|
||
///////////////////////////////////
|
||
// Tests concerning validateToken
|
||
///////////////////////////////////
|
||
/**
|
||
* @test
|
||
*/
|
||
public function validateTokenWithThreeEmptyParametersNotThrowsException() {
|
||
$this->fixture->validateToken('', '', '');
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function validateTokenWithTwoEmptyAndOneMissingParametersNotThrowsException() {
|
||
$this->fixture->validateToken('', '');
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function validateTokenWithDataFromGenerateTokenWithFormInstanceNameReturnsTrue() {
|
||
$formName = 'foo';
|
||
$formInstanceName = 'bar';
|
||
$this->assertTrue(
|
||
$this->fixture->validateToken(
|
||
$this->fixture->generateToken($formName, $formInstanceName),
|
||
$formName,
|
||
$formInstanceName
|
||
)
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function validateTokenWithDataFromGenerateTokenWithMissingFormInstanceNameReturnsTrue() {
|
||
$formName = 'foo';
|
||
$this->assertTrue(
|
||
$this->fixture->validateToken(
|
||
$this->fixture->generateToken($formName), $formName
|
||
)
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function validateTokenWithValidDataDropsToken() {
|
||
$formName = 'foo';
|
||
$fixture = $this->getMock(
|
||
't3lib_formProtection_testing', array('dropToken')
|
||
);
|
||
$tokenId = $fixture->generateToken($formName);
|
||
$fixture->expects($this->once())->method('dropToken')
|
||
->with($tokenId);
|
||
$fixture->validateToken($tokenId, $formName);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function validateTokenWithValidDataCalledTwoTimesReturnsFalseOnSecondCall() {
|
||
$formName = 'foo';
|
||
$formInstanceName = 'bar';
|
||
$tokenId = $this->fixture->generateToken($formName, $formInstanceName);
|
||
$this->fixture->validateToken($tokenId, $formName, $formInstanceName);
|
||
$this->assertFalse(
|
||
$this->fixture->validateToken($tokenId, $formName, $formInstanceName)
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function validateTokenWithMismatchingTokenIdReturnsFalse() {
|
||
$formName = 'foo';
|
||
$formInstanceName = 'bar';
|
||
$this->fixture->generateToken($formName, $formInstanceName);
|
||
$this->assertFalse(
|
||
$this->fixture->validateToken(
|
||
'Hello world!', $formName, $formInstanceName
|
||
)
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function validateTokenWithMismatchingFormNameReturnsFalse() {
|
||
$formName = 'foo';
|
||
$formInstanceName = 'bar';
|
||
$tokenId = $this->fixture->generateToken($formName, $formInstanceName);
|
||
$this->assertFalse(
|
||
$this->fixture->validateToken(
|
||
$tokenId, 'espresso', $formInstanceName
|
||
)
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function validateTokenWithMismatchingFormInstanceNameReturnsFalse() {
|
||
$formName = 'foo';
|
||
$formInstanceName = 'bar';
|
||
$tokenId = $this->fixture->generateToken($formName, $formInstanceName);
|
||
$this->assertFalse(
|
||
$this->fixture->validateToken(
|
||
$tokenId, $formName, 'beer'
|
||
)
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function validateTokenWithTwoTokensForSameFormNameAndFormInstanceNameReturnsTrueForBoth() {
|
||
$formName = 'foo';
|
||
$formInstanceName = 'bar';
|
||
$tokenId1 = $this->fixture->generateToken($formName, $formInstanceName);
|
||
$tokenId2 = $this->fixture->generateToken($formName, $formInstanceName);
|
||
$this->assertTrue(
|
||
$this->fixture->validateToken(
|
||
$tokenId1, $formName, $formInstanceName
|
||
)
|
||
);
|
||
$this->assertTrue(
|
||
$this->fixture->validateToken(
|
||
$tokenId2, $formName, $formInstanceName
|
||
)
|
||
);
|
||
}
|
||
}
|
||
?>
|
tests/t3lib/formprotection/t3lib_formprotection_backendTest.php (revision 0) | ||
---|---|---|
<?php
|
||
/***************************************************************
|
||
* Copyright notice
|
||
*
|
||
* (c) 2010 Oliver Klee (typo3-coding@oliverklee.de)
|
||
* All rights reserved
|
||
*
|
||
* This script is part of the TYPO3 project. The TYPO3 project 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.
|
||
*
|
||
* The GNU General Public License can be found at
|
||
* http://www.gnu.org/copyleft/gpl.html.
|
||
*
|
||
* This script 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.
|
||
*
|
||
* This copyright notice MUST APPEAR in all copies of the script!
|
||
***************************************************************/
|
||
/**
|
||
* Testcase for the t3lib_formProtection_backend class.
|
||
*
|
||
* @package TYPO3
|
||
* @subpackage t3lib
|
||
*
|
||
* @author Oliver Klee <typo3-coding@oliverklee.de>
|
||
*/
|
||
class t3lib_formProtection_backendTest extends tx_phpunit_testcase {
|
||
/**
|
||
* a backup of the current BE user
|
||
*
|
||
* @var t3lib_beUserAuth
|
||
*/
|
||
private $backEndUserBackup = null;
|
||
/**
|
||
* @var t3lib_formProtection_backend
|
||
*/
|
||
private $fixture;
|
||
public function setUp() {
|
||
$this->backEndUserBackup = $GLOBALS['BE_USER'];
|
||
$GLOBALS['BE_USER'] = $this->getMock(
|
||
't3lib_beUserAuth',
|
||
array('getSessionData', 'setAndSaveSessionData')
|
||
);
|
||
$className = $this->createAccessibleProxyClass();
|
||
$this->fixture = new $className;
|
||
}
|
||
public function tearDown() {
|
||
$this->fixture->__destruct();
|
||
unset($this->fixture);
|
||
$GLOBALS['BE_USER'] = $this->backEndUserBackup;
|
||
}
|
||
//////////////////////
|
||
// Utility functions
|
||
//////////////////////
|
||
/**
|
||
* Creates a subclass t3lib_formProtection_backend with retrieveTokens made
|
||
* public.
|
||
*
|
||
* @return string the name of the created class, will not be empty
|
||
*/
|
||
private function createAccessibleProxyClass() {
|
||
$className = 't3lib_formProtection_backendAccessibleProxy';
|
||
if (!class_exists($className)) {
|
||
eval(
|
||
'class ' . $className . ' extends t3lib_formProtection_backend {' .
|
||
'public function retrieveTokens() {' .
|
||
'return parent::retrieveTokens();' .
|
||
'}' .
|
||
'}'
|
||
);
|
||
}
|
||
return $className;
|
||
}
|
||
////////////////////////////////////
|
||
// Tests for the utility functions
|
||
////////////////////////////////////
|
||
/**
|
||
* @test
|
||
*/
|
||
public function createAccessibleProxyCreatesBackendFormProtectionSubclass() {
|
||
$className = $this->createAccessibleProxyClass();
|
||
$this->assertTrue(
|
||
(new $className()) instanceof t3lib_formProtection_backend
|
||
);
|
||
}
|
||
//////////////////////////////////////////////////////////
|
||
// Tests concerning the reading and saving of the tokens
|
||
//////////////////////////////////////////////////////////
|
||
/**
|
||
* @test
|
||
*/
|
||
public function retrieveTokensReadsTokensFromSessionData() {
|
||
$GLOBALS['BE_USER']->expects($this->once())->method('getSessionData')
|
||
->with('formTokens')->will($this->returnValue(array()));
|
||
$this->fixture->retrieveTokens();
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function tokensFromSessionDataAreAvailableForValidateToken() {
|
||
$tokenId = '51a655b55c54d54e5454c5f521f6552a';
|
||
$formName = 'foo';
|
||
$formInstanceName = '42';
|
||
$GLOBALS['BE_USER']->expects($this->once())->method('getSessionData')
|
||
->with('formTokens')->will($this->returnValue(array(
|
||
$tokenId => array(
|
||
'formName' => $formName,
|
||
'formInstanceName' => $formInstanceName,
|
||
),
|
||
)));
|
||
$this->fixture->retrieveTokens();
|
||
$this->assertTrue(
|
||
$this->fixture->validateToken($tokenId, $formName, $formInstanceName)
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function persistTokensWritesTokensToSession() {
|
||
$formName = 'foo';
|
||
$formInstanceName = '42';
|
||
$tokenId = $this->fixture->generateToken($formName, $formInstanceName);
|
||
$allTokens = array(
|
||
$tokenId => array(
|
||
'formName' => $formName,
|
||
'formInstanceName' => $formInstanceName,
|
||
),
|
||
);
|
||
$GLOBALS['BE_USER']->expects($this->once())
|
||
->method('setAndSaveSessionData')->with('formTokens', $allTokens);
|
||
$this->fixture->persistTokens();
|
||
}
|
||
}
|
||
?>
|