[BUGFIX] Clipboard: Check whether FAL object is an existing file
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / FormProtection / AbstractFormProtection.php
1 <?php
2 namespace TYPO3\CMS\Core\FormProtection;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Crypto\Random;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19
20 /**
21 * This class provides protection against cross-site request forgery (XSRF/CSRF)
22 * for forms.
23 *
24 * For documentation on how to use this class, please see the documentation of
25 * the corresponding subclasses
26 */
27 abstract class AbstractFormProtection
28 {
29 /**
30 * @var \Closure
31 */
32 protected $validationFailedCallback;
33
34 /**
35 * The session token which is used to be hashed during token generation.
36 *
37 * @var string
38 */
39 protected $sessionToken;
40
41 /**
42 * @return string
43 */
44 protected function getSessionToken()
45 {
46 $this->sessionToken = $this->sessionToken ?? $this->retrieveSessionToken();
47 return $this->sessionToken;
48 }
49
50 /**
51 * Frees as much memory as possible.
52 */
53 public function __destruct()
54 {
55 unset($this->sessionToken);
56 }
57
58 /**
59 * Deletes the session token and persists the (empty) token.
60 *
61 * This function is intended to be called when a user logs on or off.
62 */
63 public function clean()
64 {
65 unset($this->sessionToken);
66 $this->persistSessionToken();
67 }
68
69 /**
70 * Generates a token for a form by hashing the given parameters
71 * with the secret session token.
72 *
73 * Calling this function two times with the same parameters will create
74 * the same valid token during one user session.
75 *
76 * @param string $formName
77 * @param string $action
78 * @param string $formInstanceName
79 * @return string the 32-character hex ID of the generated token
80 * @throws \InvalidArgumentException
81 */
82 public function generateToken($formName, $action = '', $formInstanceName = '')
83 {
84 if ($formName == '') {
85 throw new \InvalidArgumentException('$formName must not be empty.', 1294586643);
86 }
87 $tokenId = GeneralUtility::hmac($formName . $action . $formInstanceName . $this->getSessionToken());
88 return $tokenId;
89 }
90
91 /**
92 * Checks whether the token $tokenId is valid in the form $formName with
93 * $formInstanceName.
94 *
95 * @param string $tokenId
96 * @param string $formName
97 * @param string $action
98 * @param string $formInstanceName
99 * @return bool
100 */
101 public function validateToken($tokenId, $formName, $action = '', $formInstanceName = '')
102 {
103 $validTokenId = GeneralUtility::hmac(((string)$formName . (string)$action) . (string)$formInstanceName . $this->getSessionToken());
104 if (hash_equals($validTokenId, (string)$tokenId)) {
105 $isValid = true;
106 } else {
107 $isValid = false;
108 }
109 if (!$isValid) {
110 $this->createValidationErrorMessage();
111 }
112 return $isValid;
113 }
114
115 /**
116 * Generates the random token which is used in the hash for the form tokens.
117 *
118 * @return string
119 */
120 protected function generateSessionToken()
121 {
122 return GeneralUtility::makeInstance(Random::class)->generateRandomHexString(64);
123 }
124
125 /**
126 * Creates or displays an error message telling the user that the submitted
127 * form token is invalid.
128 */
129 protected function createValidationErrorMessage()
130 {
131 if ($this->validationFailedCallback !== null) {
132 $this->validationFailedCallback->__invoke();
133 }
134 }
135
136 /**
137 * Retrieves the session token.
138 *
139 * @return string
140 */
141 abstract protected function retrieveSessionToken();
142
143 /**
144 * Saves the session token so that it can be used by a later incarnation
145 * of this class.
146 *
147 * @internal
148 */
149 abstract public function persistSessionToken();
150 }