Added feature #16437: Introduce a form protection API (Thanks to the Security Team...
[Packages/TYPO3.CMS.git] / tests / t3lib / formprotection / t3lib_formprotection_AbstractTest.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2010 Oliver Klee (typo3-coding@oliverklee.de)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24
25 require_once('fixtures/class.t3lib_formprotection_testing.php');
26
27 /**
28 * Testcase for the t3lib_formprotection_Abstract class.
29 *
30 * $Id$
31 *
32 * @package TYPO3
33 * @subpackage t3lib
34 *
35 * @author Oliver Klee <typo3-coding@oliverklee.de>
36 */
37 class t3lib_formprotection_AbstractTest extends tx_phpunit_testcase {
38 /**
39 * @var t3lib_formProtection_Testing
40 */
41 private $fixture;
42
43 public function setUp() {
44 $this->fixture = new t3lib_formProtection_Testing();
45 }
46
47 public function tearDown() {
48 $this->fixture->__destruct();
49 unset($this->fixture);
50 }
51
52
53 /////////////////////////////////////////
54 // Tests concerning the basic functions
55 /////////////////////////////////////////
56
57 /**
58 * @test
59 */
60 public function constructionRetrievesTokens() {
61 $className = uniqid('t3lib_formProtection');
62 eval(
63 'class ' . $className . ' extends t3lib_formProtection_Testing {' .
64 'public $tokensHaveBeenRetrieved = FALSE; ' .
65 'protected function retrieveTokens() {' .
66 '$this->tokensHaveBeenRetrieved = TRUE;' .
67 '}' .
68 '}'
69 );
70
71 $fixture = new $className();
72
73 $this->assertTrue(
74 $fixture->tokensHaveBeenRetrieved
75 );
76 }
77
78 /**
79 * @test
80 */
81 public function cleanMakesTokenInvalid() {
82 $formName = 'foo';
83 $tokenId = $this->fixture->generateToken($formName);
84
85 $this->fixture->clean();
86
87 $this->assertFalse(
88 $this->fixture->validateToken($tokenId, $formName)
89 );
90 }
91
92 /**
93 * @test
94 */
95 public function cleanPersistsTokens() {
96 $fixture = $this->getMock(
97 't3lib_formProtection_Testing', array('persistTokens')
98 );
99 $fixture->expects($this->once())->method('persistTokens');
100
101 $fixture->clean();
102 }
103
104
105 ///////////////////////////////////
106 // Tests concerning generateToken
107 ///////////////////////////////////
108
109 /**
110 * @test
111 */
112 public function generateTokenFormForEmptyFormNameThrowsException() {
113 $this->setExpectedException(
114 'InvalidArgumentException', '$formName must not be empty.'
115 );
116
117 $this->fixture->generateToken('', 'edit', 'bar');
118 }
119
120 /**
121 * @test
122 */
123 public function generateTokenFormForEmptyActionNotThrowsException() {
124 $this->fixture->generateToken('foo', '', '42');
125 }
126
127 /**
128 * @test
129 */
130 public function generateTokenFormForEmptyFormInstanceNameNotThrowsException() {
131 $this->fixture->generateToken('foo', 'edit', '');
132 }
133
134 /**
135 * @test
136 */
137 public function generateTokenFormForOmittedActionAndFormInstanceNameNotThrowsException() {
138 $this->fixture->generateToken('foo');
139 }
140
141 /**
142 * @test
143 */
144 public function generateTokenReturns32CharacterHexToken() {
145 $this->assertRegexp(
146 '/^[0-9a-f]{32}$/',
147 $this->fixture->generateToken('foo')
148 );
149 }
150
151 /**
152 * @test
153 */
154 public function generateTokenCalledTwoTimesWithSameParametersReturnsDifferentTokens() {
155 $this->assertNotEquals(
156 $this->fixture->generateToken('foo', 'edit', 'bar'),
157 $this->fixture->generateToken('foo', 'edit', 'bar')
158 );
159 }
160
161 /**
162 * @test
163 */
164 public function generatingTooManyTokensInvalidatesOldestToken() {
165 $this->fixture->setMaximumNumberOfTokens(2);
166
167 $formName = 'foo';
168
169 $token1 = $this->fixture->generateToken($formName);
170 $token2 = $this->fixture->generateToken($formName);
171 $token3 = $this->fixture->generateToken($formName);
172
173 $this->assertFalse(
174 $this->fixture->validateToken($token1, $formName)
175 );
176 }
177
178 /**
179 * @test
180 */
181 public function generatingTooManyTokensNotInvalidatesNewestToken() {
182 $this->fixture->setMaximumNumberOfTokens(2);
183
184 $formName = 'foo';
185 $formInstanceName = 'bar';
186
187 $token1 = $this->fixture->generateToken($formName);
188 $token2 = $this->fixture->generateToken($formName);
189 $token3 = $this->fixture->generateToken($formName);
190
191 $this->assertTrue(
192 $this->fixture->validateToken($token3, $formName)
193 );
194 }
195
196 /**
197 * @test
198 */
199 public function generatingTooManyTokensNotInvalidatesTokenInTheMiddle() {
200 $this->fixture->setMaximumNumberOfTokens(2);
201
202 $formName = 'foo';
203 $formInstanceName = 'bar';
204
205 $token1 = $this->fixture->generateToken($formName);
206 $token2 = $this->fixture->generateToken($formName);
207 $token3 = $this->fixture->generateToken($formName);
208
209 $this->assertTrue(
210 $this->fixture->validateToken($token2, $formName)
211 );
212 }
213
214
215 ///////////////////////////////////
216 // Tests concerning validateToken
217 ///////////////////////////////////
218
219 /**
220 * @test
221 */
222 public function validateTokenWithFourEmptyParametersNotThrowsException() {
223 $this->fixture->validateToken('', '', '', '');
224 }
225
226 /**
227 * @test
228 */
229 public function validateTokenWithTwoEmptyAndTwoMissingParametersNotThrowsException() {
230 $this->fixture->validateToken('', '');
231 }
232
233 /**
234 * @test
235 */
236 public function validateTokenWithDataFromGenerateTokenWithFormInstanceNameReturnsTrue() {
237 $formName = 'foo';
238 $action = 'edit';
239 $formInstanceName = 'bar';
240
241 $this->assertTrue(
242 $this->fixture->validateToken(
243 $this->fixture->generateToken($formName, $action, $formInstanceName),
244 $formName,
245 $action,
246 $formInstanceName
247 )
248 );
249 }
250
251 /**
252 * @test
253 */
254 public function validateTokenWithDataFromGenerateTokenWithMissingActionAndFormInstanceNameReturnsTrue() {
255 $formName = 'foo';
256
257 $this->assertTrue(
258 $this->fixture->validateToken(
259 $this->fixture->generateToken($formName), $formName
260 )
261 );
262 }
263
264 /**
265 * @test
266 */
267 public function validateTokenWithValidDataDropsToken() {
268 $formName = 'foo';
269
270 $fixture = $this->getMock(
271 't3lib_formProtection_Testing', array('dropToken')
272 );
273
274 $tokenId = $fixture->generateToken($formName);
275 $fixture->expects($this->once())->method('dropToken')
276 ->with($tokenId);
277
278 $fixture->validateToken($tokenId, $formName);
279 }
280
281 /**
282 * @test
283 */
284 public function validateTokenWithValidDataCalledTwoTimesReturnsFalseOnSecondCall() {
285 $formName = 'foo';
286 $action = 'edit';
287 $formInstanceName = 'bar';
288
289 $tokenId = $this->fixture->generateToken($formName, $action, $formInstanceName);
290
291 $this->fixture->validateToken($tokenId, $formName, $action, $formInstanceName);
292
293 $this->assertFalse(
294 $this->fixture->validateToken($tokenId, $formName, $action, $formInstanceName)
295 );
296 }
297
298 /**
299 * @test
300 */
301 public function validateTokenWithMismatchingTokenIdReturnsFalse() {
302 $formName = 'foo';
303 $action = 'edit';
304 $formInstanceName = 'bar';
305
306 $this->fixture->generateToken($formName, $action, $formInstanceName);
307
308 $this->assertFalse(
309 $this->fixture->validateToken(
310 'Hello world!', $formName, $action, $formInstanceName
311 )
312 );
313 }
314
315 /**
316 * @test
317 */
318 public function validateTokenWithMismatchingFormNameReturnsFalse() {
319 $formName = 'foo';
320 $action = 'edit';
321 $formInstanceName = 'bar';
322
323 $tokenId = $this->fixture->generateToken($formName, $action, $formInstanceName);
324
325 $this->assertFalse(
326 $this->fixture->validateToken(
327 $tokenId, 'espresso', $action, $formInstanceName
328 )
329 );
330 }
331
332 /**
333 * @test
334 */
335 public function validateTokenWithMismatchingActionReturnsFalse() {
336 $formName = 'foo';
337 $action = 'edit';
338 $formInstanceName = 'bar';
339
340 $tokenId = $this->fixture->generateToken($formName, $action, $formInstanceName);
341
342 $this->assertFalse(
343 $this->fixture->validateToken(
344 $tokenId, $formName, 'delete', $formInstanceName
345 )
346 );
347 }
348
349 /**
350 * @test
351 */
352 public function validateTokenWithMismatchingFormInstanceNameReturnsFalse() {
353 $formName = 'foo';
354 $action = 'edit';
355 $formInstanceName = 'bar';
356
357 $tokenId = $this->fixture->generateToken($formName, $action, $formInstanceName);
358
359 $this->assertFalse(
360 $this->fixture->validateToken(
361 $tokenId, $formName, $action, 'beer'
362 )
363 );
364 }
365
366 /**
367 * @test
368 */
369 public function validateTokenWithTwoTokensForSameFormNameAndActionAndFormInstanceNameReturnsTrueForBoth() {
370 $formName = 'foo';
371 $action = 'edit';
372 $formInstanceName = 'bar';
373
374 $tokenId1 = $this->fixture->generateToken($formName, $action, $formInstanceName);
375 $tokenId2 = $this->fixture->generateToken($formName, $action, $formInstanceName);
376
377 $this->assertTrue(
378 $this->fixture->validateToken(
379 $tokenId1, $formName, $action, $formInstanceName
380 )
381 );
382 $this->assertTrue(
383 $this->fixture->validateToken(
384 $tokenId2, $formName, $action, $formInstanceName
385 )
386 );
387 }
388
389 /**
390 * @test
391 */
392 public function validateTokenWithTwoTokensForSameFormNameAndActionAndFormInstanceNameCalledInReverseOrderReturnsTrueForBoth() {
393 $formName = 'foo';
394 $action = 'edit';
395 $formInstanceName = 'bar';
396
397 $tokenId1 = $this->fixture->generateToken($formName, $action, $formInstanceName);
398 $tokenId2 = $this->fixture->generateToken($formName, $action, $formInstanceName);
399
400 $this->assertTrue(
401 $this->fixture->validateToken(
402 $tokenId2, $formName, $action, $formInstanceName
403 )
404 );
405 $this->assertTrue(
406 $this->fixture->validateToken(
407 $tokenId1, $formName, $action, $formInstanceName
408 )
409 );
410 }
411
412 /**
413 * @test
414 */
415 public function validateTokenForValidTokenNotCallsCreateValidationErrorMessage() {
416 $fixture = $this->getMock(
417 't3lib_formProtection_Testing', array('createValidationErrorMessage')
418 );
419 $fixture->expects($this->never())->method('createValidationErrorMessage');
420
421 $formName = 'foo';
422 $action = 'edit';
423 $formInstanceName = 'bar';
424
425 $token = $fixture->generateToken($formName, $action, $formInstanceName);
426 $fixture->validateToken(
427 $token, $formName, $action, $formInstanceName
428 );
429
430 $fixture->__destruct();
431 }
432
433 /**
434 * @test
435 */
436 public function validateTokenForInvalidTokenCallsCreateValidationErrorMessage() {
437 $fixture = $this->getMock(
438 't3lib_formProtection_Testing', array('createValidationErrorMessage')
439 );
440 $fixture->expects($this->once())->method('createValidationErrorMessage');
441
442 $formName = 'foo';
443 $action = 'edit';
444 $formInstanceName = 'bar';
445
446 $fixture->generateToken($formName, $action, $formInstanceName);
447 $fixture->validateToken(
448 'an invalid token ...', $formName, $action, $formInstanceName
449 );
450
451 $fixture->__destruct();
452 }
453
454 /**
455 * @test
456 */
457 public function validateTokenForInvalidFormNameCallsCreateValidationErrorMessage() {
458 $fixture = $this->getMock(
459 't3lib_formProtection_Testing', array('createValidationErrorMessage')
460 );
461 $fixture->expects($this->once())->method('createValidationErrorMessage');
462
463 $formName = 'foo';
464 $action = 'edit';
465 $formInstanceName = 'bar';
466
467 $token = $fixture->generateToken($formName, $action, $formInstanceName);
468 $fixture->validateToken(
469 $token, 'another form name', $action, $formInstanceName
470 );
471
472 $fixture->__destruct();
473 }
474 }
475 ?>