diff --git a/t3lib/class.t3lib_befunc.php b/t3lib/class.t3lib_befunc.php index 135211a08ac4c61713c786385fea1f5d64600b5a..09ba414c8686fcec9cffd2d70727ac91e1a1d676 100644 --- a/t3lib/class.t3lib_befunc.php +++ b/t3lib/class.t3lib_befunc.php @@ -3159,7 +3159,7 @@ final class t3lib_BEfunc { */ public static function getUrlToken($formName = 'securityToken', $tokenName = 'formToken') { $formprotection = t3lib_formprotection_Factory::get(); - return '&' . $tokenName . '=' . $formprotection->generateToken($formName) . '-' . $formName; + return '&' . $tokenName . '=' . $formprotection->generateToken($formName); } /******************************************* diff --git a/t3lib/class.t3lib_pagerenderer.php b/t3lib/class.t3lib_pagerenderer.php index 19188397dbc0bd14e1b7837ca1cec0966d03ba85..fc287a9aa63ca5ffed89a1b70763f1606c937ba7 100644 --- a/t3lib/class.t3lib_pagerenderer.php +++ b/t3lib/class.t3lib_pagerenderer.php @@ -985,7 +985,7 @@ class t3lib_PageRenderer implements t3lib_Singleton { // does this only with multiple arguments $this->addExtOnReadyCode(' (function() { - TYPO3.ExtDirectToken = "' . $token . '-extDirect"; + TYPO3.ExtDirectToken = "' . $token . '"; for (var api in Ext.app.ExtDirectAPI) { var provider = Ext.Direct.addProvider(Ext.app.ExtDirectAPI[api]); provider.on("beforecall", function(provider, transaction, meta) { diff --git a/t3lib/class.t3lib_tceforms.php b/t3lib/class.t3lib_tceforms.php index 86aee82a31b1e9ecda6745b484b30a8f8a044469..ba7ae5c0abb38ffc369612d80c8dc3dcb069d8b5 100644 --- a/t3lib/class.t3lib_tceforms.php +++ b/t3lib/class.t3lib_tceforms.php @@ -4984,7 +4984,7 @@ class t3lib_TCEforms { */ public static function getHiddenTokenField($formName = 'securityToken', $tokenName = 'formToken') { $formprotection = t3lib_formprotection_Factory::get(); - return '<input type="hidden" name="' .$tokenName . '" value="' . $formprotection->generateToken($formName) . '-' . $formName . '" />'; + return '<input type="hidden" name="' .$tokenName . '" value="' . $formprotection->generateToken($formName) . '" />'; } /** diff --git a/t3lib/formprotection/class.t3lib_formprotection_abstract.php b/t3lib/formprotection/class.t3lib_formprotection_abstract.php index ba2dddb1e969f73aa9cbe9737a8e4df4b40c044e..313bc1cc452dc64a3cc512af04d76fd686ef67ba 100644 --- a/t3lib/formprotection/class.t3lib_formprotection_abstract.php +++ b/t3lib/formprotection/class.t3lib_formprotection_abstract.php @@ -35,75 +35,49 @@ * @subpackage t3lib * * @author Oliver Klee <typo3-coding@oliverklee.de> + * @author Helmut Hummel <helmut.hummel@typo3.org> */ abstract class t3lib_formprotection_Abstract { /** - * the maximum number of tokens that can exist at the same time + * The session token which is used to be hashed during token generation. * - * @var integer + * @var string */ - protected $maximumNumberOfTokens = 0; + protected $sessionToken; /** - * Valid tokens sorted from oldest to newest. - * - * [tokenId] => array(formName, formInstanceName) - * - * @var array<array> - */ - protected $tokens = array(); - - /** - * Tokens that have been added during this request. - * - * @var array<array> - */ - protected $addedTokens = array(); - - /** - * Token ids of tokens that have been dropped during this request. - * - * @var array - */ - protected $droppedTokenIds = array(); - - /** - * Constructor. Makes sure existing tokens are read and available for - * checking. + * Constructor. Makes sure the session token is read and + * available for checking. */ public function __construct() { - $this->tokens = $this->retrieveTokens(); + $this->retrieveSessionToken(); } /** * Frees as much memory as possible. */ public function __destruct() { - $this->tokens = array(); + unset($this->sessionToken); } /** - * Deletes all existing tokens and persists the (empty) token table. + * Deletes the session token and persists the (empty) token. * * This function is intended to be called when a user logs on or off. * * @return void */ public function clean() { - $this->tokens = array(); - $this->persistTokens(); + unset($this->sessionToken); + $this->persistSessionToken(); } /** - * Generates and stores a token for a form. + * Generates a token for a form by hashing the given parameters + * with the secret session token. * * 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. + * the same valid token during one user session. * * @param string $formName * the name of the form, for example a table name like "tt_content", @@ -126,17 +100,12 @@ abstract class t3lib_formprotection_Abstract { throw new InvalidArgumentException('$formName must not be empty.', 1294586643); } - do { - $tokenId = bin2hex(t3lib_div::generateRandomBytes(16)); - } while (isset($this->tokens[$tokenId])); - - $this->tokens[$tokenId] = array( - 'formName' => $formName, - 'action' => $action, - 'formInstanceName' => $formInstanceName, + $tokenId = t3lib_div::hmac( + $formName . + $action . + $formInstanceName . + $this->sessionToken ); - $this->addedTokens[$tokenId] = $this->tokens[$tokenId]; - $this->preventOverflow(); return $tokenId; } @@ -145,40 +114,33 @@ abstract class t3lib_formprotection_Abstract { * 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. - * * @param string $tokenId - * a form token to check, may also be empty or utterly misformed + * a form token to check, may also be empty or utterly malformed * @param string $formName * the name of the form to check, for example "tt_content", - * may also be empty or utterly misformed + * may also be empty or utterly malformed * @param string $action * the action of the form to check, for example "edit", - * may also be empty or utterly misformed + * may also be empty or utterly malformed * @param string $formInstanceName * the instance name of the form to check, for example "42" or "foo" - * or "31,42", may also be empty or utterly misformed + * or "31,42", may also be empty or utterly malformed * * @return boolean * TRUE if $tokenId, $formName, $action and $formInstanceName match - * and the token has not been used yet, FALSE otherwise */ public function validateToken( $tokenId, $formName, $action = '', $formInstanceName = '' ) { - if (isset($this->tokens[$tokenId])) { - $token = $this->tokens[$tokenId]; - $isValid = ($token['formName'] == $formName) - && ($token['action'] == $action) - && ($token['formInstanceName'] == $formInstanceName); - $this->dropToken($tokenId); + $validTokenId = t3lib_div::hmac( + (string)$formName . + (string)$action . + (string)$formInstanceName . + $this->sessionToken + ); + + if ((string)$tokenId === $validTokenId) { + $isValid = TRUE; } else { $isValid = FALSE; } @@ -191,92 +153,41 @@ abstract class t3lib_formprotection_Abstract { } /** - * Creates or displayes an error message telling the user that the submitted - * form token is invalid. - * - * This function may also be empty if the validation error should be handled - * silently. - * - * @return void - */ - abstract protected function createValidationErrorMessage(); - - /** - * Retrieves all saved tokens. - * - * @return array<arrray> - * the saved tokens, 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. + * Generates the random token which is used in the hash for the form tokens. * - * @return void + * @return string */ - abstract public function persistTokens(); + protected function generateSessionToken() { + return bin2hex(t3lib_div::generateRandomBytes(32)); + } /** - * 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. + * Creates or displays an error message telling the user that the submitted + * form token is invalid. * - * @param string $tokenId - * the 32-character ID of an existing token, must not be empty + * This function may also be empty if the validation error should be handled + * silently. * * @return void */ - protected function dropToken($tokenId) { - if (isset($this->tokens[$tokenId])) { - unset($this->tokens[$tokenId]); - $this->droppedTokenIds[] = $tokenId; - } - } - - /** - * Persisting of tokens is only required, if tokens are - * deleted or added during this request. - * - * @return boolean - */ - protected function isPersistingRequired() { - return !empty($this->droppedTokenIds) || !empty($this->addedTokens); - } + abstract protected function createValidationErrorMessage(); /** - * Reset the arrays of added or deleted tokens. + * Retrieves the session token. * - * @return void + * @return string + * the saved session token, will be empty if no token has been saved */ - protected function resetPersistingRequiredStatus() { - $this->droppedTokenIds = array(); - $this->addedTokens = array(); - } + abstract protected function retrieveSessionToken(); /** - * 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. + * Saves the session token so that it can be used by a later incarnation + * of this class. * + * @access private * @return void */ - protected function preventOverflow() { - if (empty($this->tokens)) { - return; - } - - while (count($this->tokens) > $this->maximumNumberOfTokens) { - reset($this->tokens); - $this->dropToken(key($this->tokens)); - } - } + abstract public function persistSessionToken(); } ?> \ No newline at end of file diff --git a/t3lib/formprotection/class.t3lib_formprotection_backendformprotection.php b/t3lib/formprotection/class.t3lib_formprotection_backendformprotection.php index 06ad1147b0a01de410994ca62b430d88d0e258d5..045a043356253a714acf50fa64bfa143449dcdc9 100644 --- a/t3lib/formprotection/class.t3lib_formprotection_backendformprotection.php +++ b/t3lib/formprotection/class.t3lib_formprotection_backendformprotection.php @@ -3,6 +3,7 @@ * Copyright notice * * (c) 2010-2011 Oliver Klee <typo3-coding@oliverklee.de> + * (c) 2010-2011 Helmut Hummel <helmut.hummel@typo3.org> * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is @@ -35,9 +36,8 @@ * matter; you only need it to get the form token for verifying it. * * <pre> - * $formToken = t3lib_formprotection_Factory::get( - * t3lib_formprotection_Factory::TYPE_BACK_END - * )->generateToken( + * $formToken = t3lib_formprotection_Factory::get() + * ->generateToken( * 'BE user setup', 'edit' * ); * $this->content .= '<input type="hidden" name="formToken" value="' . @@ -53,35 +53,20 @@ * For editing a tt_content record, the call could look like this: * * <pre> - * $formToken = t3lib_formprotection_Factory::get( - * t3lib_formprotection_Factory::TYPE_BACK_END - * )->getFormProtection()->generateToken( + * $formToken = t3lib_formprotection_Factory::get() + * ->getFormProtection()->generateToken( * 'tt_content', 'edit', $uid * ); * </pre> * - * At the end of the form, you need to persist the tokens. This makes sure that - * generated tokens get saved, and also that removed tokens stay removed: - * - * <pre> - * t3lib_formprotection_Factory::get( - * t3lib_formprotection_Factory::TYPE_BACK_END - * )->persistTokens(); - * </pre> - * - * In BE lists, it might be necessary to generate hundreds of tokens. So the - * tokens do not get automatically persisted after creation for performance - * reasons. - * * * When processing the data that has been submitted by the form, you can check * that the form token is valid like this: * * <pre> - * if ($dataHasBeenSubmitted && t3lib_formprotection_Factory::get( - * t3lib_formprotection_Factory::TYPE_BACK_END - * )->validateToken( - * (string) t3lib_div::_POST('formToken'), + * if ($dataHasBeenSubmitted && t3lib_formprotection_Factory::get() + * ->validateToken( + * t3lib_div::_POST('formToken'), * 'BE user setup', 'edit * ) * ) { @@ -92,27 +77,14 @@ * } * </pre> * - * Note that validateToken invalidates the token with the token ID. So calling - * validate with the same parameters two times in a row will always return FALSE - * for the second call. - * - * It is important that the tokens get validated <em>before</em> the tokens are - * persisted. This makes sure that the tokens that get invalidated by - * validateToken cannot be used again. * * @package TYPO3 * @subpackage t3lib * * @author Oliver Klee <typo3-coding@oliverklee.de> + * @author Helmut Hummel <helmut.hummel@typo3.org> */ class t3lib_formprotection_BackendFormProtection extends t3lib_formprotection_Abstract { - /** - * the maximum number of tokens that can exist at the same time - * - * @var integer - */ - protected $maximumNumberOfTokens = 20000; - /** * Keeps the instance of the user which existed during creation * of the object. @@ -121,6 +93,14 @@ class t3lib_formprotection_BackendFormProtection extends t3lib_formprotection_Ab */ protected $backendUser; + /** + * Instance of the registry, which is used to permanently persist + * the session token so that it can be restored during re-login. + * + * @var t3lib_Registry + */ + protected $registry; + /** * Only allow construction if we have a backend session */ @@ -137,34 +117,7 @@ class t3lib_formprotection_BackendFormProtection extends t3lib_formprotection_Ab } /** - * Overrule the method in the absract class, because we can drop the - * whole locking procedure, which is done in persistTokens, if we - * simply want to delete all tokens. - * - * @see t3lib/formprotection/t3lib_formprotection_Abstract::clean() - */ - public function clean() { - $this->tokens = array(); - $this->backendUser->setAndSaveSessionData('formTokens', $this->tokens); - $this->resetPersistingRequiredStatus(); - } - - /** - * Override the abstract class to be able to strip out - * the token id from the POST variable. - * - * @see t3lib/formprotection/t3lib_formprotection_Abstract::validateToken() - */ - public function validateToken( - $token, $formName, $action = '', $formInstanceName = '' - ) { - list($tokenId, $_) = explode('-', (string)$token); - - return parent::validateToken($tokenId, $formName, $action, $formInstanceName); - } - - /** - * Creates or displayes an error message telling the user that the submitted + * Creates or displays an error message telling the user that the submitted * form token is invalid. * * @return void @@ -183,90 +136,89 @@ class t3lib_formprotection_BackendFormProtection extends t3lib_formprotection_Ab } /** - * Retrieves all saved tokens. + * Retrieves the saved session token or generates a new one. * * @return array<array> * the saved tokens as, will be empty if no tokens have been saved */ - protected function retrieveTokens() { - $tokens = $this->backendUser->getSessionData('formTokens'); - if (!is_array($tokens)) { - $tokens = array(); + protected function retrieveSessionToken() { + $this->sessionToken = $this->backendUser->getSessionData('formSessionToken'); + if (empty($this->sessionToken)) { + $this->sessionToken = $this->generateSessionToken(); + $this->persistSessionToken(); } + } - return $tokens; + /** + * Saves the tokens so that they can be used by a later incarnation of this + * class. + * + * @return void + */ + public function persistSessionToken() { + $this->backendUser->setAndSaveSessionData('formSessionToken', $this->sessionToken); } /** - * It might be that two (or more) scripts are executed at the same time, - * which would lead to a race condition, where both (all) scripts retrieve - * the same tokens from the session, so the script that is executed - * last will overwrite the tokens generated in the first scripts. - * So before writing all tokens back to the session we need to get the - * current tokens from the session again. + * Sets the session token for the user from the registry + * and returns it additionally. * + * @access private + * @return string */ - protected function updateTokens() { - $this->backendUser->user = $this->backendUser->fetchUserSession(TRUE); - $tokens = $this->retrieveTokens(); - $this->tokens = array_merge($tokens, $this->addedTokens); - foreach ($this->droppedTokenIds as $tokenId) { - unset($this->tokens[$tokenId]); + public function setSessionTokenFromRegistry() { + $this->sessionToken = $this->getRegistry() + ->get('core', 'formSessionToken:' . $this->backendUser->user['uid']); + if (empty($this->sessionToken)) { + throw new UnexpectedValueException('Failed to restore the session token from the registry.', 1301827270); } + return $this->sessionToken; } /** - * Saves the tokens so that they can be used by a later incarnation of this - * class. + * Stores the session token in the registry to have it + * available during re-login of the user. * + * @access private * @return void */ - public function persistTokens() { - if ($this->isPersistingRequired()) { - $lockObject = $this->acquireLock(); - - $this->updateTokens(); - $this->backendUser->setAndSaveSessionData('formTokens', $this->tokens); - $this->resetPersistingRequiredStatus(); - - $this->releaseLock($lockObject); - } + public function storeSessionTokenInRegistry() { + $this->getRegistry() + ->set('core', 'formSessionToken:' . $this->backendUser->user['uid'], $this->sessionToken); } /** - * Tries to acquire a lock to not allow a race condition. + * Removes the session token for the user from the registry. * - * @return t3lib_lock|FALSE The lock object or FALSE + * @access private + * @return string */ - protected function acquireLock() { - $identifier = 'persistTokens' . $this->backendUser->id; - try { - /** @var t3lib_lock $lockObject */ - $lockObject = t3lib_div::makeInstance('t3lib_lock', $identifier, 'simple'); - $lockObject->setEnableLogging(FALSE); - $success = $lockObject->acquire(); - } catch (Exception $e) { - t3lib_div::sysLog('Locking: Failed to acquire lock: '.$e->getMessage(), 't3lib_formprotection_BackendFormProtection', t3lib_div::SYSLOG_SEVERITY_ERROR); - $success = FALSE; // If locking fails, return with false and continue without locking - } - - return $success ? $lockObject : FALSE; + public function removeSessionTokenFromRegistry() { + return $this->getRegistry() + ->remove('core', 'formSessionToken:' . $this->backendUser->user['uid']); } /** - * Releases the lock if it was acquired before. + * Returns the instance of the registry. * - * @return boolean + * @return t3lib_Registry */ - protected function releaseLock(&$lockObject) { - $success = FALSE; - // If lock object is set and was acquired, release it: - if (is_object($lockObject) && $lockObject instanceof t3lib_lock && $lockObject->getLockStatus()) { - $success = $lockObject->release(); - $lockObject = NULL; + protected function getRegistry() { + if (!$this->registry instanceof t3lib_Registry) { + $this->registry = t3lib_div::makeInstance('t3lib_Registry'); } + return $this->registry; + } - return $success; + /** + * Inject the registry. Currently only used in unit tests. + * + * @access private + * @param t3lib_Registry $registry + * @return void + */ + public function injectRegistry(t3lib_Registry $registry) { + $this->registry = $registry; } /** diff --git a/t3lib/formprotection/class.t3lib_formprotection_disabledformprotection.php b/t3lib/formprotection/class.t3lib_formprotection_disabledformprotection.php index 18c878dc173b8056974e5401e97c430dc74a12ec..dff5a89c5cb195d26ed1a3e450cefc025c32cb60 100644 --- a/t3lib/formprotection/class.t3lib_formprotection_disabledformprotection.php +++ b/t3lib/formprotection/class.t3lib_formprotection_disabledformprotection.php @@ -73,14 +73,14 @@ class t3lib_formprotection_DisabledFormProtection extends t3lib_formprotection_A /** * Dummy implementation */ - protected function retrieveTokens() { + protected function retrieveSessionToken() { // Do nothing. } /** * Dummy implementation */ - public function persistTokens() { + public function persistSessionToken() { // Do nothing. } } diff --git a/t3lib/formprotection/class.t3lib_formprotection_factory.php b/t3lib/formprotection/class.t3lib_formprotection_factory.php index c7ad85bdb4db103ce92d9f7ff2eced2e494836d9..062092a05f1c3e46a8bbec3492d433440d1242fa 100644 --- a/t3lib/formprotection/class.t3lib_formprotection_factory.php +++ b/t3lib/formprotection/class.t3lib_formprotection_factory.php @@ -33,17 +33,13 @@ * Usage for the back-end form protection: * * <pre> - * $formProtection = t3lib_formprotection_Factory::get( - * 't3lib_formProtection_BackEnd' - * ); + * $formProtection = t3lib_formprotection_Factory::get(); * </pre> * * Usage for the install tool form protection: * * <pre> - * $formProtection = t3lib_formprotection_Factory::get( - * 'tx_install_formprotection' - * ); + * $formProtection = t3lib_formprotection_Factory::get(); * $formProtection->injectInstallTool($this); * </pre> * @@ -52,6 +48,7 @@ * * @author Oliver Klee <typo3-coding@oliverklee.de> * @author Ernesto Baschny <ernst@cron-it.de> + * @author Helmut Hummel <helmut.hummel@typo3.org> */ final class t3lib_formprotection_Factory { /** @@ -71,7 +68,8 @@ final class t3lib_formprotection_Factory { * Gets a form protection instance for the requested class $className. * * If there already is an existing instance of the requested $className, the - * existing instance will be returned. + * existing instance will be returned. If no $className is provided, the factory + * detects the scope and returns the appropriate form protection object. * * @param string $className * the name of the class for which to return an instance, must be @@ -90,7 +88,7 @@ final class t3lib_formprotection_Factory { } /** - * Returns the classname depending on TYPO3_MODE and + * Returns the class name depending on TYPO3_MODE and * active backend session. * * @return string @@ -128,7 +126,7 @@ final class t3lib_formprotection_Factory { return (isset($GLOBALS['BE_USER']) && $GLOBALS['BE_USER'] instanceof t3lib_beUserAuth && isset($GLOBALS['BE_USER']->user['uid']) && - !(TYPO3_MODE == 'FE') + !(TYPO3_MODE === 'FE') ); } @@ -141,12 +139,12 @@ final class t3lib_formprotection_Factory { return (is_object($GLOBALS['TSFE']) && $GLOBALS['TSFE']->fe_user instanceof tslib_feUserAuth && isset($GLOBALS['TSFE']->fe_user->user['uid']) && - (TYPO3_MODE == 'FE') + (TYPO3_MODE === 'FE') ); } /** - * Creates an instace for the requested class $className + * Creates an instance for the requested class $className * and stores it internally. * * @param string $className @@ -182,6 +180,7 @@ final class t3lib_formprotection_Factory { * * Note: This function is intended for testing purposes only. * + * @access private * @param string $className * the name of the class for which to set an instance, must be * "t3lib_formProtection_BackEnd" or "t3lib_formprotection_InstallToolFormProtection" diff --git a/t3lib/formprotection/class.t3lib_formprotection_installtoolformprotection.php b/t3lib/formprotection/class.t3lib_formprotection_installtoolformprotection.php index d764b086cf3320014d6aedae9e664077e20ef9e6..09216333a3eb18fb66a5f5eeb4b7fe496aa4e78e 100644 --- a/t3lib/formprotection/class.t3lib_formprotection_installtoolformprotection.php +++ b/t3lib/formprotection/class.t3lib_formprotection_installtoolformprotection.php @@ -47,20 +47,12 @@ * possible. For different forms (e.g. the password change and editing a the * configuration), those values should be different. * - * At the end of the form, you need to persist the tokens. This makes sure that - * generated tokens get saved, and also that removed tokens stay removed: - * - * <pre> - * $this->formProtection()->persistTokens(); - * </pre> - * - * * When processing the data that has been submitted by the form, you can check * that the form token is valid like this: * * <pre> * if ($dataHasBeenSubmitted && $this->formProtection()->validateToken( - * (string) $_POST['formToken'], + * $_POST['formToken'], * 'installToolPassword', * 'change' * ) { @@ -71,13 +63,6 @@ * } * </pre> * - * Note that validateToken invalidates the token with the token ID. So calling - * validate with the same parameters two times in a row will always return FALSE - * for the second call. - * - * It is important that the tokens get validated <em>before</em> the tokens are - * persisted. This makes sure that the tokens that get invalidated by - * validateToken cannot be used again. * * @package TYPO3 * @subpackage t3lib @@ -85,13 +70,6 @@ * @author Oliver Klee <typo3-coding@oliverklee.de> */ class t3lib_formprotection_InstallToolFormProtection extends t3lib_formProtection_Abstract { - /** - * the maximum number of tokens that can exist at the same time - * - * @var integer - */ - protected $maximumNumberOfTokens = 100; - /** * an instance of the install tool used for displaying messages * @@ -134,20 +112,19 @@ class t3lib_formprotection_InstallToolFormProtection extends t3lib_formProtectio } /** - * Retrieves all saved tokens. + * Retrieves or generates the session token. * - * @return array<array> - * the saved tokens, will be empty if no tokens have been saved + * @return void */ - protected function retrieveTokens() { - if (isset($_SESSION['installToolFormTokens']) - && is_array($_SESSION['installToolFormTokens']) + protected function retrieveSessionToken() { + if (isset($_SESSION['installToolFormToken']) + && !empty($_SESSION['installToolFormToken']) ) { - $tokens = $_SESSION['installToolFormTokens']; + $this->sessionToken = $_SESSION['installToolFormToken']; } else { - $tokens = array(); + $this->sessionToken = $this->generateSessionToken(); + $this->persistSessionToken(); } - return $tokens; } /** @@ -156,8 +133,8 @@ class t3lib_formprotection_InstallToolFormProtection extends t3lib_formProtectio * * @return void */ - public function persistTokens() { - $_SESSION['installToolFormTokens'] = $this->tokens; + public function persistSessionToken() { + $_SESSION['installToolFormToken'] = $this->sessionToken; } } diff --git a/tests/t3lib/formprotection/class.t3lib_formprotection_AbstractTest.php b/tests/t3lib/formprotection/class.t3lib_formprotection_AbstractTest.php index fc276110bcebbc3560033fc158a5350fbee18c3e..2b3e3581ce3e42743ee5a2688b6820ed3099153d 100644 --- a/tests/t3lib/formprotection/class.t3lib_formprotection_AbstractTest.php +++ b/tests/t3lib/formprotection/class.t3lib_formprotection_AbstractTest.php @@ -55,13 +55,13 @@ class t3lib_formprotection_AbstractTest extends tx_phpunit_testcase { /** * @test */ - public function constructionRetrievesTokens() { + public function constructionRetrievesToken() { $className = uniqid('t3lib_formProtection'); eval( 'class ' . $className . ' extends t3lib_formProtection_Testing {' . - 'public $tokensHaveBeenRetrieved = FALSE; ' . - 'protected function retrieveTokens() {' . - '$this->tokensHaveBeenRetrieved = TRUE;' . + 'public $tokenHasBeenRetrieved = FALSE; ' . + 'protected function retrieveSessionToken() {' . + '$this->tokenHasBeenRetrieved = TRUE;' . '}' . '}' ); @@ -69,7 +69,7 @@ class t3lib_formprotection_AbstractTest extends tx_phpunit_testcase { $fixture = new $className(); $this->assertTrue( - $fixture->tokensHaveBeenRetrieved + $fixture->tokenHasBeenRetrieved ); } @@ -90,11 +90,11 @@ class t3lib_formprotection_AbstractTest extends tx_phpunit_testcase { /** * @test */ - public function cleanPersistsTokens() { + public function cleanPersistsToken() { $fixture = $this->getMock( - 't3lib_formProtection_Testing', array('persistTokens') + 't3lib_formProtection_Testing', array('persistSessionToken') ); - $fixture->expects($this->once())->method('persistTokens'); + $fixture->expects($this->once())->method('persistSessionToken'); $fixture->clean(); } @@ -141,7 +141,7 @@ class t3lib_formprotection_AbstractTest extends tx_phpunit_testcase { */ public function generateTokenReturns32CharacterHexToken() { $this->assertRegexp( - '/^[0-9a-f]{32}$/', + '/^[0-9a-f]{40}$/', $this->fixture->generateToken('foo') ); } @@ -149,66 +149,13 @@ class t3lib_formprotection_AbstractTest extends tx_phpunit_testcase { /** * @test */ - public function generateTokenCalledTwoTimesWithSameParametersReturnsDifferentTokens() { - $this->assertNotEquals( + public function generateTokenCalledTwoTimesWithSameParametersReturnsSameTokens() { + $this->assertEquals( $this->fixture->generateToken('foo', 'edit', 'bar'), $this->fixture->generateToken('foo', 'edit', 'bar') ); } - /** - * @test - */ - public function generatingTooManyTokensInvalidatesOldestToken() { - $this->fixture->setMaximumNumberOfTokens(2); - - $formName = 'foo'; - - $token1 = $this->fixture->generateToken($formName); - $token2 = $this->fixture->generateToken($formName); - $token3 = $this->fixture->generateToken($formName); - - $this->assertFalse( - $this->fixture->validateToken($token1, $formName) - ); - } - - /** - * @test - */ - public function generatingTooManyTokensNotInvalidatesNewestToken() { - $this->fixture->setMaximumNumberOfTokens(2); - - $formName = 'foo'; - $formInstanceName = 'bar'; - - $token1 = $this->fixture->generateToken($formName); - $token2 = $this->fixture->generateToken($formName); - $token3 = $this->fixture->generateToken($formName); - - $this->assertTrue( - $this->fixture->validateToken($token3, $formName) - ); - } - - /** - * @test - */ - public function generatingTooManyTokensNotInvalidatesTokenInTheMiddle() { - $this->fixture->setMaximumNumberOfTokens(2); - - $formName = 'foo'; - $formInstanceName = 'bar'; - - $token1 = $this->fixture->generateToken($formName); - $token2 = $this->fixture->generateToken($formName); - $token3 = $this->fixture->generateToken($formName); - - $this->assertTrue( - $this->fixture->validateToken($token2, $formName) - ); - } - /////////////////////////////////// // Tests concerning validateToken @@ -262,24 +209,7 @@ class t3lib_formprotection_AbstractTest extends tx_phpunit_testcase { /** * @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() { + public function validateTokenWithValidDataCalledTwoTimesReturnsTrueOnSecondCall() { $formName = 'foo'; $action = 'edit'; $formInstanceName = 'bar'; @@ -288,7 +218,7 @@ class t3lib_formprotection_AbstractTest extends tx_phpunit_testcase { $this->fixture->validateToken($tokenId, $formName, $action, $formInstanceName); - $this->assertFalse( + $this->assertTrue( $this->fixture->validateToken($tokenId, $formName, $action, $formInstanceName) ); } @@ -361,52 +291,6 @@ class t3lib_formprotection_AbstractTest extends tx_phpunit_testcase { ); } - /** - * @test - */ - public function validateTokenWithTwoTokensForSameFormNameAndActionAndFormInstanceNameReturnsTrueForBoth() { - $formName = 'foo'; - $action = 'edit'; - $formInstanceName = 'bar'; - - $tokenId1 = $this->fixture->generateToken($formName, $action, $formInstanceName); - $tokenId2 = $this->fixture->generateToken($formName, $action, $formInstanceName); - - $this->assertTrue( - $this->fixture->validateToken( - $tokenId1, $formName, $action, $formInstanceName - ) - ); - $this->assertTrue( - $this->fixture->validateToken( - $tokenId2, $formName, $action, $formInstanceName - ) - ); - } - - /** - * @test - */ - public function validateTokenWithTwoTokensForSameFormNameAndActionAndFormInstanceNameCalledInReverseOrderReturnsTrueForBoth() { - $formName = 'foo'; - $action = 'edit'; - $formInstanceName = 'bar'; - - $tokenId1 = $this->fixture->generateToken($formName, $action, $formInstanceName); - $tokenId2 = $this->fixture->generateToken($formName, $action, $formInstanceName); - - $this->assertTrue( - $this->fixture->validateToken( - $tokenId2, $formName, $action, $formInstanceName - ) - ); - $this->assertTrue( - $this->fixture->validateToken( - $tokenId1, $formName, $action, $formInstanceName - ) - ); - } - /** * @test */ diff --git a/tests/t3lib/formprotection/class.t3lib_formprotection_BackendFormProtectionTest.php b/tests/t3lib/formprotection/class.t3lib_formprotection_BackendFormProtectionTest.php index 38374f464403f5f8ea266b19d960939fe18fed85..7c158be6b07d9207f679c6e0743ceebfb02d63f1 100644 --- a/tests/t3lib/formprotection/class.t3lib_formprotection_BackendFormProtectionTest.php +++ b/tests/t3lib/formprotection/class.t3lib_formprotection_BackendFormProtectionTest.php @@ -83,11 +83,11 @@ class t3lib_formprotection_BackendFormProtectionTest extends tx_phpunit_testcase ' public function createValidationErrorMessage() {' . ' parent::createValidationErrorMessage();' . ' }' . - ' public function updateTokens() {' . - ' return parent::updateTokens();' . + ' public function retrieveSessionToken() {' . + ' return parent::retrieveSessionToken();' . ' }' . - ' public function retrieveTokens() {' . - ' return parent::retrieveTokens();' . + ' public function setSessionToken($sessionToken) {' . + ' $this->sessionToken = $sessionToken;' . ' }' . '}' ); @@ -162,93 +162,57 @@ class t3lib_formprotection_BackendFormProtectionTest extends tx_phpunit_testcase /** * @test */ - public function retrieveTokensReadsTokensFromSessionData() { + public function retrieveTokenReadsTokenFromSessionData() { $GLOBALS['BE_USER']->expects($this->once())->method('getSessionData') - ->with('formTokens')->will($this->returnValue(array())); + ->with('formSessionToken')->will($this->returnValue(array())); - $this->fixture->retrieveTokens(); + $this->fixture->retrieveSessionToken(); } /** * @test */ - public function tokensFromSessionDataAreAvailableForValidateToken() { - $tokenId = '51a655b55c54d54e5454c5f521f6552a'; + public function tokenFromSessionDataIsAvailableForValidateToken() { + $sessionToken = '881ffea2159ac72182557b79dc0c723f5a8d20136f9fab56cdd4f8b3a1dbcfcd'; $formName = 'foo'; $action = 'edit'; $formInstanceName = '42'; + $tokenId = t3lib_div::hmac($formName . $action . $formInstanceName . $sessionToken); + $GLOBALS['BE_USER']->expects($this->atLeastOnce())->method('getSessionData') - ->with('formTokens') - ->will($this->returnValue(array( - $tokenId => array( - 'formName' => $formName, - 'action' => $action, - 'formInstanceName' => $formInstanceName, - ), - ))); + ->with('formSessionToken') + ->will($this->returnValue($sessionToken)); - $this->fixture->updateTokens(); + $this->fixture->retrieveSessionToken(); $this->assertTrue( - $this->fixture->validateToken($tokenId, $formName, $action, $formInstanceName) + $this->fixture->validateToken($tokenId, $formName, $action, $formInstanceName) ); } /** + * @expectedException UnexpectedValueException * @test */ - public function tokensStayDroppedAfterPersistingTokens() { - $tokenId = '51a655b55c54d54e5454c5f521f6552a'; - $formName = 'foo'; - $action = 'edit'; - $formInstanceName = '42'; - - $GLOBALS['BE_USER']->expects($this->atLeastOnce())->method('getSessionData') - ->will($this->returnValue(array( - $tokenId => array( - 'formName' => $formName, - 'action' => $action, - 'formInstanceName' => $formInstanceName, - ), - ))); - - $className = $this->createAccessibleProxyClass(); - - $this->fixture->updateTokens(); - - $this->fixture->validateToken($tokenId, $formName, $action, $formInstanceName); - - $this->fixture->persistTokens(); - - $this->assertFalse( - $this->fixture->validateToken($tokenId, $formName, $action, $formInstanceName) + public function restoreSessionTokenFromRegistryThrowsExceptionIfSessionTokenIsEmpty() { + $this->fixture->injectRegistry( + $this->getMock('t3lib_Registry') ); + $this->fixture->setSessionTokenFromRegistry(); } /** * @test */ - public function persistTokensWritesTokensToSession() { - $formName = 'foo'; - $action = 'edit'; - $formInstanceName = '42'; - - $tokenId = $this->fixture->generateToken( - $formName, $action, $formInstanceName - ); - $allTokens = array( - $tokenId => array( - 'formName' => $formName, - 'action' => $action, - 'formInstanceName' => $formInstanceName, - ), - ); + public function persistSessionTokenWritesTokenToSession() { + $sessionToken = '881ffea2159ac72182557b79dc0c723f5a8d20136f9fab56cdd4f8b3a1dbcfcd'; + $this->fixture->setSessionToken($sessionToken); $GLOBALS['BE_USER']->expects($this->once()) - ->method('setAndSaveSessionData')->with('formTokens', $allTokens); + ->method('setAndSaveSessionData')->with('formSessionToken', $sessionToken); - $this->fixture->persistTokens(); + $this->fixture->persistSessionToken(); } diff --git a/tests/t3lib/formprotection/class.t3lib_formprotection_InstallToolFormProtectionTest.php b/tests/t3lib/formprotection/class.t3lib_formprotection_InstallToolFormProtectionTest.php index f3966790d71e38e1b4275e4cc4f752ea0d017b9a..8dc593d9854473e845fd95b14a5ba1c941daceeb 100644 --- a/tests/t3lib/formprotection/class.t3lib_formprotection_InstallToolFormProtectionTest.php +++ b/tests/t3lib/formprotection/class.t3lib_formprotection_InstallToolFormProtectionTest.php @@ -77,11 +77,12 @@ class t3lib_formprotection_InstallToolFormProtectionTest extends tx_phpunit_test if (!class_exists($className)) { eval( 'class ' . $className . ' extends t3lib_formprotection_InstallToolFormProtection {' . + ' public $sessionToken;' . ' public function createValidationErrorMessage() {' . ' parent::createValidationErrorMessage();' . ' }' . - ' public function retrieveTokens() {' . - ' return $this->tokens = parent::retrieveTokens();' . + ' public function retrieveSessionToken() {' . + ' parent::retrieveSessionToken();' . ' }' . '}' ); @@ -114,52 +115,36 @@ class t3lib_formprotection_InstallToolFormProtectionTest extends tx_phpunit_test /** * @test */ - public function tokensFromSessionDataAreAvailableForValidateToken() { - $tokenId = '51a655b55c54d54e5454c5f521f6552a'; + public function tokenFromSessionDataIsAvailableForValidateToken() { + $sessionToken = '881ffea2159ac72182557b79dc0c723f5a8d20136f9fab56cdd4f8b3a1dbcfcd'; $formName = 'foo'; $action = 'edit'; $formInstanceName = '42'; - $_SESSION['installToolFormTokens'] = array( - $tokenId => array( - 'formName' => $formName, - 'action' => $action, - 'formInstanceName' => $formInstanceName, - ), - ); + $tokenId = t3lib_div::hmac($formName . $action . $formInstanceName . $sessionToken); + + $_SESSION['installToolFormToken'] = $sessionToken; - $this->fixture->retrieveTokens(); + $this->fixture->retrieveSessionToken(); $this->assertTrue( - $this->fixture->validateToken( - $tokenId, $formName, $action, $formInstanceName - ) + $this->fixture->validateToken($tokenId, $formName, $action, $formInstanceName) ); } /** * @test */ - public function persistTokensWritesTokensToSession() { - $formName = 'foo'; - $action = 'edit'; - $formInstanceName = '42'; + public function persistSessionTokenWritesTokensToSession() { + $_SESSION['installToolFormToken'] = 'foo'; - $tokenId = $this->fixture->generateToken( - $formName, $action, $formInstanceName - ); + $this->fixture->sessionToken = '881ffea2159ac72182557b79dc0c723f5a8d20136f9fab56cdd4f8b3a1dbcfcd'; - $this->fixture->persistTokens(); + $this->fixture->persistSessionToken(); $this->assertEquals( - array( - $tokenId => array( - 'formName' => $formName, - 'action' => $action, - 'formInstanceName' => $formInstanceName, - ), - ), - $_SESSION['installToolFormTokens'] + '881ffea2159ac72182557b79dc0c723f5a8d20136f9fab56cdd4f8b3a1dbcfcd', + $_SESSION['installToolFormToken'] ); } diff --git a/tests/t3lib/formprotection/fixtures/class.t3lib_formprotection_testing.php b/tests/t3lib/formprotection/fixtures/class.t3lib_formprotection_testing.php index 0c472c9f8eac7c8ea8642b0e4a6f688a863da1fc..2ce5c85ae2a71c5f5148cbad04a643733f2f3614 100644 --- a/tests/t3lib/formprotection/fixtures/class.t3lib_formprotection_testing.php +++ b/tests/t3lib/formprotection/fixtures/class.t3lib_formprotection_testing.php @@ -34,24 +34,6 @@ * @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 - * - * @return void - */ - public function setMaximumNumberOfTokens($number) { - $this->maximumNumberOfTokens = $number; - } - /** * Creates or displayes an error message telling the user that the submitted * form token is invalid. @@ -66,7 +48,9 @@ class t3lib_formProtection_Testing extends t3lib_formprotection_Abstract { * @return array the saved tokens as a two-dimensional array, will be empty * if no tokens have been saved */ - protected function retrieveTokens() {} + protected function retrieveSessionToken() { + $this->sessionToken = $this->generateSessionToken(); + } /** * Saves the tokens so that they can be used by a later incarnation of this @@ -74,21 +58,7 @@ class t3lib_formProtection_Testing extends t3lib_formprotection_Abstract { * * @return void */ - 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 - * - * @return void - */ - public function dropToken($tokenId) { - parent::dropToken($tokenId); - } + public function persistSessionToken() {} } if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/formprotection/class.t3lib_formprotection_testing.php'])) { diff --git a/typo3/alt_clickmenu.php b/typo3/alt_clickmenu.php index de22429ea222cb004abf6bcd7a27e798a34dcb7f..66556604317bcd7a4837dd9756a1cb3098c9b2fd 100644 --- a/typo3/alt_clickmenu.php +++ b/typo3/alt_clickmenu.php @@ -1763,7 +1763,6 @@ class SC_alt_clickmenu { $this->content = $this->doc->insertStylesAndJS($this->content); echo $this->content; } else { - t3lib_formprotection_Factory::get()->persistTokens(); $this->content = $GLOBALS['LANG']->csConvObj->utf8_encode($this->content,$GLOBALS['LANG']->charSet); t3lib_ajax::outputXMLreply($this->content); } diff --git a/typo3/classes/class.ajaxlogin.php b/typo3/classes/class.ajaxlogin.php index 001fe6b8fd25edcfad5956649936c71ec16c72c7..ec86bdcf38deb861832fdae60f8b2c91455e8c6a 100644 --- a/typo3/classes/class.ajaxlogin.php +++ b/typo3/classes/class.ajaxlogin.php @@ -45,11 +45,10 @@ class AjaxLogin { public function login(array $parameters, TYPO3AJAX $ajaxObj) { if ($this->isAuthorizedBackendSession()) { $json = array('success' => TRUE); - $token = ''; if ($this->hasLoginBeenProcessed()) { - $formprotection = t3lib_formprotection_Factory::get(); - $json['accessToken'] = $formprotection->generateToken('refreshTokens'); - $formprotection->persistTokens(); + $formProtection = t3lib_formprotection_Factory::get(); + $formProtection->setSessionTokenFromRegistry(); + $formProtection->persistSessionToken(); } } else { $json = array('success' => FALSE); @@ -68,7 +67,7 @@ class AjaxLogin { } /** - * Check whether the user was not already authorized + * Check whether the user was already authorized or not * * @return boolean */ @@ -164,43 +163,6 @@ class AjaxLogin { $parent->addContent('challenge', $_SESSION['login_challenge']); $parent->setContentFormat('json'); } - - /** - * Generates new tokens for the ones found in the DOM. - * - * @param array $parameters: Parameters (not used) - * @param TYPO3AJAX $parent: The calling parent AJAX object - */ - public function refreshTokens(array $parameters, TYPO3AJAX $parent) { - $accessToken = (string)t3lib_div::_GP('accessToken'); - $formprotection = t3lib_formprotection_Factory::get(); - - if ($formprotection->validateToken($accessToken, 'refreshTokens')) { - $oldTokens = json_decode((string)t3lib_div::_GP('tokens')); - $regeneratedTokens = new stdClass(); - - foreach ($oldTokens as $oldToken) { - $newToken = $this->generateNewToken($oldToken); - $regeneratedTokens->$oldToken = $newToken; - } - } - $parent->addContent('newTokens', $regeneratedTokens); - $parent->setContentFormat('json'); - - $formprotection->persistTokens(); - } - - /** - * Generate new token. - * - * @param string $oldToken - * @return string regenerated Token - */ - protected function generateNewToken($oldToken) { - list ($tokenId, $formName) = explode('-', $oldToken); - return t3lib_formprotection_Factory::get()->generateToken($formName) . '-' . $formName; - } - } if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/classes/class.ajaxlogin.php'])) { diff --git a/typo3/classes/class.clearcachemenu.php b/typo3/classes/class.clearcachemenu.php index 96b135a650b9c20d2c8e26a117750719ccd44063..3abdb741de3c15949a3d8fbd72baa02ec352f556 100644 --- a/typo3/classes/class.clearcachemenu.php +++ b/typo3/classes/class.clearcachemenu.php @@ -112,8 +112,6 @@ class ClearCacheMenu implements backend_toolbarItem { $hookObject->manipulateCacheActions($this->cacheActions, $this->optionValues); } } - - t3lib_formprotection_Factory::get()->persistTokens(); } /** diff --git a/typo3/index.php b/typo3/index.php index e9891cfffc89138e0910f0ce27c490a9ea291441..2b7fb7bea126f9581261215e539f1b4b5a3fd8ae 100644 --- a/typo3/index.php +++ b/typo3/index.php @@ -392,13 +392,14 @@ class SC_index { break; } + $formProtection = t3lib_formprotection_Factory::get(); // If there is a redirect URL AND if loginRefresh is not set... if (!$this->loginRefresh) { + $formProtection->storeSessionTokenInRegistry(); t3lib_utility_Http::redirect($this->redirectToURL); } else { - $formprotection = t3lib_formprotection_Factory::get(); - $accessToken = $formprotection->generateToken('refreshTokens'); - $formprotection->persistTokens(); + $formProtection->setSessionTokenFromRegistry(); + $formProtection->persistSessionToken(); $TBE_TEMPLATE->JScode.=$TBE_TEMPLATE->wrapScriptTags(' if (parent.opener && (parent.opener.busy || parent.opener.TYPO3.loginRefresh)) { if (parent.opener.TYPO3.loginRefresh) { @@ -406,7 +407,6 @@ class SC_index { } else { parent.opener.busy.loginRefreshed(); } - parent.opener.TYPO3.loginRefresh.refreshTokens("' . $accessToken . '"); parent.close(); } '); diff --git a/typo3/js/clearcachemenu.js b/typo3/js/clearcachemenu.js index 0a7c6534b59d078e04235e0f66de236723e042ac..25b30f9d96068dfe3595b5a5579889da4bfcf737 100644 --- a/typo3/js/clearcachemenu.js +++ b/typo3/js/clearcachemenu.js @@ -96,10 +96,6 @@ var ClearCacheMenu = Class.create({ 'method': 'get', 'onComplete': function(result) { spinner.replace(oldIcon); - // replace used token with new one - if (result.responseText.length > 0) { - link.href = link.href.substr(0, link.href.length - result.responseText.length) + result.responseText - } }.bind(this) }); } diff --git a/typo3/js/loginrefresh.js b/typo3/js/loginrefresh.js index de0871bfdf41241ae1b6e2405e62e6b2e5676020..33ca93ba7f00cac5ba0d2c627e7822d8eab267a2 100644 --- a/typo3/js/loginrefresh.js +++ b/typo3/js/loginrefresh.js @@ -306,7 +306,6 @@ Ext.ux.TYPO3.loginRefresh = Ext.extend(Ext.util.Observable, { // User is logged in Ext.getCmp("loginformWindow").hide(); TYPO3.loginRefresh.startTimer(); - TYPO3.loginRefresh.refreshTokens(result.accessToken); } else { // TODO: add failure to notification system instead of alert Ext.Msg.alert(TYPO3.LLL.core.refresh_login_failed, TYPO3.LLL.core.refresh_login_failed_message); @@ -337,97 +336,6 @@ Ext.ux.TYPO3.loginRefresh = Ext.extend(Ext.util.Observable, { } else { this.submitForm(); } - }, - - getOutdatedTokens: function() { - var tokens = []; - var searchTokenPlaces = [top, top.content.document]; - - if (top.nav instanceof TYPO3.iframePanel) { - searchTokenPlaces.push(top.nav.getIframe()); - } - - Ext.each(searchTokenPlaces, function(searchPlace) { - var links = searchPlace.Ext.query('a[href*=formToken]'); - Ext.each(links, function(linkTag) { - tokens.push(Ext.urlDecode(linkTag.href).formToken); - }); - - var formFields = searchPlace.Ext.query("form input[name=formToken]"); - Ext.each(formFields, function(inputField) { - tokens.push(inputField.value); - }); - - var linksOnclick = searchPlace.Ext.query('a[onclick*=formToken]'); - Ext.each(linksOnclick, function(linkTag) { - tokens.push(linkTag.attributes.onclick.value.match(/&formToken=([^&]*)&/).pop()); - }); - - if (Ext.isString(searchPlace.TYPO3.ExtDirectToken)) { - tokens.push(searchPlace.TYPO3.ExtDirectToken); - } - - }); - - return tokens; - }, - - replaceOutdatedTokens: function(newTokens) { - var searchTokenPlaces = [top, top.content.document]; - - if (top.nav instanceof TYPO3.iframePanel) { - searchTokenPlaces.push(top.nav.getIframe()); - } - - Ext.each(searchTokenPlaces, function(searchPlace) { - var links = searchPlace.Ext.query('a[href*=formToken]'); - Ext.each(links, function(linkTag) { - var url = Ext.urlDecode(linkTag.href); - url.formToken = newTokens[url.formToken]; - linkTag.href = unescape(Ext.urlEncode(url)); - }); - - var formFields = searchPlace.Ext.query("form input[name=formToken]"); - Ext.each(formFields, function(inputField) { - inputField.value = newTokens[inputField.value]; - }); - - var linksOnclick = searchPlace.Ext.query('a[onclick*=formToken]'); - Ext.each(linksOnclick, function(linkTag) { - var token = linkTag.attributes.onclick.value.match(/&formToken=([^&]*)&/).pop(); - linkTag.attributes.onclick.value = linkTag.attributes.onclick.value.replace(new RegExp(token), newTokens[token]); - }); - - if (Ext.isString(searchPlace.TYPO3.ExtDirectToken)) { - searchPlace.TYPO3.ExtDirectToken = newTokens[searchPlace.TYPO3.ExtDirectToken]; - } - }); - }, - - refreshTokens: function(accessToken) { - Ext.Ajax.request({ - url: "ajax.php", - params: { - "ajaxID": "BackendLogin::refreshTokens", - "accessToken": accessToken, - "tokens": Ext.encode(this.getOutdatedTokens()) - }, - method: "POST", - scope: this, - success: function(response, opts) { - var result = Ext.util.JSON.decode(response.responseText); - TYPO3.loginRefresh.replaceOutdatedTokens(result.newTokens); - }, - failure: function(response, opts) { - TYPO3.Flashmessage.display( - TYPO3.Severity.error, - 'Refresh tokens', - 'Refreshing tokens after relogin failed. Please reload the backend.', - 30 - ); - } - - }); } }); diff --git a/typo3/logout.php b/typo3/logout.php index 759b6784759a02b70d361291493c5c781d924fb9..c11ada394aeac3b83900fee80c0cb4c889010d22 100644 --- a/typo3/logout.php +++ b/typo3/logout.php @@ -66,7 +66,8 @@ class SC_logout { */ function logout() { // Logout written to log - $GLOBALS['BE_USER']->writelog(255 ,2, 0, 1, 'User %s logged out from TYPO3 Backend', array($GLOBALS['BE_USER']->user['username'])); + $GLOBALS['BE_USER']->writelog(255, 2, 0, 1, 'User %s logged out from TYPO3 Backend', array($GLOBALS['BE_USER']->user['username'])); + t3lib_formProtection_Factory::get()->removeSessionTokenFromRegistry(); $GLOBALS['BE_USER']->logoff(); $redirect = t3lib_div::sanitizeLocalUrl(t3lib_div::_GP('redirect')); $redirectUrl = $redirect ? $redirect : 'index.php'; diff --git a/typo3/sysext/install/mod/class.tx_install.php b/typo3/sysext/install/mod/class.tx_install.php index 8d239e2653096d4389607db2aabe9486313848ab..0abb71eca85fe011b21b7cbebb751998048d083d 100755 --- a/typo3/sysext/install/mod/class.tx_install.php +++ b/typo3/sysext/install/mod/class.tx_install.php @@ -925,8 +925,6 @@ REMOTE_ADDR was '".t3lib_div::getIndpEnv('REMOTE_ADDR')."' (".t3lib_div::getIndp break; } } - - $this->formProtection->persistTokens(); } /** diff --git a/typo3/sysext/setup/mod/index.php b/typo3/sysext/setup/mod/index.php index f92ee092a2265d3086901ce5456a39175863ffe4..76795fc9d2f1f416b028b96d45eccfd6bb0ca2d3 100755 --- a/typo3/sysext/setup/mod/index.php +++ b/typo3/sysext/setup/mod/index.php @@ -145,6 +145,8 @@ class SC_mod_user_setup_index { /** * Getter for the form protection instance. + * + * @return t3lib_formprotection_BackendFormProtection */ public function getFormProtection() { return $this->formProtection; @@ -1033,6 +1035,4 @@ $LANG->includeLLFile('EXT:setup/mod/locallang.xml'); $SOBE->init(); $SOBE->main(); $SOBE->printContent(); - -$SOBE->getFormProtection()->persistTokens(); ?> \ No newline at end of file diff --git a/typo3/tce_db.php b/typo3/tce_db.php index 309dd90ccf73a12faa8d4af04e82e6530233d2c3..51a3616efb53e7755d1a850df12088502d751ca0 100644 --- a/typo3/tce_db.php +++ b/typo3/tce_db.php @@ -249,18 +249,7 @@ $formprotection = t3lib_formprotection_Factory::get(); if ($formprotection->validateToken(t3lib_div::_GP('formToken'), 'tceAction')) { $SOBE->initClipboard(); $SOBE->main(); - - // This is done for the clear cache menu, so that it gets a new token - // making it possible to clear cache several times. - if (t3lib_div::_GP('ajaxCall')) { - $token = array(); - $token['value'] = $formprotection->generateToken('tceAction'); - $token['name'] = 'formToken'; - // This will be used by clearcachemenu.js to replace the token for the next call - echo t3lib_BEfunc::getUrlToken('tceAction'); - } } -$formprotection->persistTokens(); $SOBE->finish(); ?> \ No newline at end of file diff --git a/typo3/template.php b/typo3/template.php index bd98584c252740a4f168f75baf19daa5fa5424d8..996aada91643316bc38ce1d69e9b8c51ec1f7457 100644 --- a/typo3/template.php +++ b/typo3/template.php @@ -906,7 +906,6 @@ $str.=$this->docBodyTagBegin(). <!-- Wrapping DIV-section for whole page END --> </div>':'') . $this->endOfPageJsBlock ; - t3lib_formprotection_Factory::get()->persistTokens(); }