[BUGFIX] Abandon one time CSRF tokens
authorHelmut Hummel <helmut.hummel@typo3.org>
Sun, 20 Mar 2011 18:15:57 +0000 (19:15 +0100)
committerHelmut Hummel <typo3@helmut-hummel.de>
Fri, 29 Apr 2011 22:02:46 +0000 (00:02 +0200)
Abandon the extra security feature of having one time tokens and create tokens
which are valid during a whole login session. Additionally create only one random token,
store it in the session and create the real URL and form tokens by hashing the scope strings
with the secret session token.

To enable re-login, store the session token in the registry and retrieve it in case a
re-login happens.

Thanks to Marion Eher (Bluechip.at) for sponsoring
this fix with 75 beers during the bug auction at T3BOARD11.

Resolves: #25359
Change-Id: If37990fbc1ae3701777e8218cc1bc8760a4d6a55
Releases: 4.6, 4.5
Reviewed-on: http://review.typo3.org/1364
Reviewed-by: Helmut Hummel
Tested-by: Helmut Hummel
23 files changed:
t3lib/class.t3lib_befunc.php
t3lib/class.t3lib_pagerenderer.php
t3lib/class.t3lib_tceforms.php
t3lib/formprotection/class.t3lib_formprotection_abstract.php
t3lib/formprotection/class.t3lib_formprotection_backendformprotection.php
t3lib/formprotection/class.t3lib_formprotection_disabledformprotection.php
t3lib/formprotection/class.t3lib_formprotection_factory.php
t3lib/formprotection/class.t3lib_formprotection_installtoolformprotection.php
tests/t3lib/formprotection/class.t3lib_formprotection_AbstractTest.php
tests/t3lib/formprotection/class.t3lib_formprotection_BackendFormProtectionTest.php
tests/t3lib/formprotection/class.t3lib_formprotection_InstallToolFormProtectionTest.php
tests/t3lib/formprotection/fixtures/class.t3lib_formprotection_testing.php
typo3/alt_clickmenu.php
typo3/classes/class.ajaxlogin.php
typo3/classes/class.clearcachemenu.php
typo3/index.php
typo3/js/clearcachemenu.js
typo3/js/loginrefresh.js
typo3/logout.php
typo3/sysext/install/mod/class.tx_install.php
typo3/sysext/setup/mod/index.php
typo3/tce_db.php
typo3/template.php

index 135211a..09ba414 100644 (file)
@@ -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);
        }
 
        /*******************************************
index 1918839..fc287a9 100644 (file)
@@ -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) {
index 86aee82..ba7ae5c 100644 (file)
@@ -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) . '" />';
        }
 
        /**
index ba2dddb..313bc1c 100644 (file)
  * @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
index 06ad114..045a043 100644 (file)
@@ -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="' .
  * 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
  *      )
  * ) {
  * }
  * </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.
         *
@@ -122,6 +94,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
         */
        public function __construct() {
@@ -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;
        }
 
        /**
index 18c878d..dff5a89 100644 (file)
@@ -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.
        }
 }
index c7ad85b..062092a 100644 (file)
  * 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"
index d764b08..0921633 100644 (file)
  * 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'
  * ) {
  * }
  * </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
  */
 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
         *
         * @var tx_install
@@ -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;
        }
 }
 
index fc27611..2b3e358 100644 (file)
@@ -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)
                );
        }
@@ -364,52 +294,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
-        */
        public function validateTokenForValidTokenNotCallsCreateValidationErrorMessage() {
                $fixture = $this->getMock(
                        't3lib_formProtection_Testing', array('createValidationErrorMessage')
index 38374f4..7c158be 100644 (file)
@@ -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();
        }
 
 
index f396679..8dc593d 100644 (file)
@@ -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']
                );
        }
 
index 0c472c9..2ce5c85 100644 (file)
  */
 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'])) {
index de22429..6655660 100644 (file)
@@ -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);
                }
index 001fe6b..ec86bdc 100644 (file)
@@ -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'])) {
index 96b135a..3abdb74 100644 (file)
@@ -112,8 +112,6 @@ class ClearCacheMenu implements backend_toolbarItem {
                                $hookObject->manipulateCacheActions($this->cacheActions, $this->optionValues);
                        }
                }
-
-               t3lib_formprotection_Factory::get()->persistTokens();
        }
 
        /**
index e9891cf..2b7fb7b 100644 (file)
@@ -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();
                                        }
                                ');
index 0a7c653..25b30f9 100644 (file)
@@ -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)
                        });
                }
index de0871b..33ca93b 100644 (file)
@@ -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
-                                       );
-                       }
-
-               });
        }
 });
 
index 759b678..c11ada3 100644 (file)
@@ -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';
index 8d239e2..0abb71e 100755 (executable)
@@ -925,8 +925,6 @@ REMOTE_ADDR was '".t3lib_div::getIndpEnv('REMOTE_ADDR')."' (".t3lib_div::getIndp
                                break;
                        }
                }
-
-               $this->formProtection->persistTokens();
        }
 
        /**
index f92ee09..76795fc 100755 (executable)
@@ -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
index 309dd90..51a3616 100644 (file)
@@ -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
index bd98584..996aada 100644 (file)
@@ -906,7 +906,6 @@ $str.=$this->docBodyTagBegin().
 
 <!-- Wrapping DIV-section for whole page END -->
 </div>':'') . $this->endOfPageJsBlock ;
-                       t3lib_formprotection_Factory::get()->persistTokens();
                }