‪TYPO3CMS  11.5
VerifyHostHeaderTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Prophecy\PhpUnit\ProphecyTrait;
21 use Psr\Http\Message\ResponseInterface;
22 use Psr\Http\Message\ServerRequestInterface;
23 use Psr\Http\Server\RequestHandlerInterface;
25 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
26 
27 class ‪VerifyHostHeaderTest extends UnitTestCase
28 {
29  use ProphecyTrait;
30 
35  {
36  $subject = new ‪VerifyHostHeader('');
37  $serverParams = $_SERVER;
38  self::assertFalse($subject->isAllowedHostHeaderValue('evil.foo.bar', $serverParams));
39  }
40 
41  public static function ‪hostnamesMatchingTrustedHostsConfigurationDataProvider(): array
42  {
43  return [
44  'hostname without port matching' => ['lolli.did.this', '.*\.did\.this'],
45  'other hostname without port matching' => ['helmut.did.this', '.*\.did\.this'],
46  'two different hostnames without port matching 1st host' => ['helmut.is.secure', '(helmut\.is\.secure|lolli\.is\.secure)'],
47  'two different hostnames without port matching 2nd host' => ['lolli.is.secure', '(helmut\.is\.secure|lolli\.is\.secure)'],
48  'hostname with port matching' => ['lolli.did.this:42', '.*\.did\.this:42'],
49  'hostnames are case insensitive 1' => ['lolli.DID.this:42', '.*\.did.this:42'],
50  'hostnames are case insensitive 2' => ['lolli.did.this:42', '.*\.DID.this:42'],
51  ];
52  }
53 
55  {
56  return [
57  'hostname without port' => ['lolli.did.this', 'helmut\.did\.this'],
58  'hostname with port, but port not allowed' => ['lolli.did.this:42', 'helmut\.did\.this'],
59  'two different hostnames in pattern but host header starts with different value #1' => ['sub.helmut.is.secure', '(helmut\.is\.secure|lolli\.is\.secure)'],
60  'two different hostnames in pattern but host header starts with different value #2' => ['sub.lolli.is.secure', '(helmut\.is\.secure|lolli\.is\.secure)'],
61  'two different hostnames in pattern but host header ends with different value #1' => ['helmut.is.secure.tld', '(helmut\.is\.secure|lolli\.is\.secure)'],
62  'two different hostnames in pattern but host header ends with different value #2' => ['lolli.is.secure.tld', '(helmut\.is\.secure|lolli\.is\.secure)'],
63  ];
64  }
65 
72  public function ‪isAllowedHostHeaderValueReturnsTrueIfHostValueMatches(string $httpHost, string $hostNamePattern): void
73  {
74  $serverParams = $_SERVER;
75 
76  $subject = new ‪VerifyHostHeader($hostNamePattern);
77  self::assertTrue($subject->isAllowedHostHeaderValue($httpHost, $serverParams));
78  }
79 
86  public function ‪isAllowedHostHeaderValueReturnsFalseIfHostValueMatches(string $httpHost, string $hostNamePattern): void
87  {
88  $serverParams = $_SERVER;
89 
90  $subject = new VerifyHostHeader($hostNamePattern);
91  self::assertFalse($subject->isAllowedHostHeaderValue($httpHost, $serverParams));
92  }
93 
94  public function ‪serverNamePatternDataProvider(): array
95  {
96  return [
97  'host value matches server name and server port is default http' => [
98  'httpHost' => 'secure.web.server',
99  'serverName' => 'secure.web.server',
100  'isAllowed' => true,
101  'serverPort' => '80',
102  'ssl' => 'Off',
103  ],
104  'host value matches server name if compared case insensitive 1' => [
105  'httpHost' => 'secure.web.server',
106  'serverName' => 'secure.WEB.server',
107  'isAllowed' => true,
108  ],
109  'host value matches server name if compared case insensitive 2' => [
110  'httpHost' => 'secure.WEB.server',
111  'serverName' => 'secure.web.server',
112  'isAllowed' => true,
113  ],
114  'host value matches server name and server port is default https' => [
115  'httpHost' => 'secure.web.server',
116  'serverName' => 'secure.web.server',
117  'isAllowed' => true,
118  'serverPort' => '443',
119  'ssl' => 'On',
120  ],
121  'host value matches server name and server port' => [
122  'httpHost' => 'secure.web.server:88',
123  'serverName' => 'secure.web.server',
124  'isAllowed' => true,
125  'serverPort' => '88',
126  ],
127  'host value matches server name case insensitive 1 and server port' => [
128  'httpHost' => 'secure.WEB.server:88',
129  'serverName' => 'secure.web.server',
130  'isAllowed' => true,
131  'serverPort' => '88',
132  ],
133  'host value matches server name case insensitive 2 and server port' => [
134  'httpHost' => 'secure.web.server:88',
135  'serverName' => 'secure.WEB.server',
136  'isAllowed' => true,
137  'serverPort' => '88',
138  ],
139  'host value is ipv6 but matches server name and server port' => [
140  'httpHost' => '[::1]:81',
141  'serverName' => '[::1]',
142  'isAllowed' => true,
143  'serverPort' => '81',
144  ],
145  'host value does not match server name' => [
146  'httpHost' => 'insecure.web.server',
147  'serverName' => 'secure.web.server',
148  'isAllowed' => false,
149  ],
150  'host value does not match server port' => [
151  'httpHost' => 'secure.web.server:88',
152  'serverName' => 'secure.web.server',
153  'isAllowed' => false,
154  'serverPort' => '89',
155  ],
156  'host value has default port that does not match server port' => [
157  'httpHost' => 'secure.web.server',
158  'serverName' => 'secure.web.server',
159  'isAllowed' => false,
160  'serverPort' => '81',
161  'ssl' => 'Off',
162  ],
163  'host value has default port that does not match server ssl port' => [
164  'httpHost' => 'secure.web.server',
165  'serverName' => 'secure.web.server',
166  'isAllowed' => false,
167  'serverPort' => '444',
168  'ssl' => 'On',
169  ],
170  ];
171  }
172 
184  string $httpHost,
185  string $serverName,
186  bool $isAllowed,
187  string $serverPort = '80',
188  string $ssl = 'Off'
189  ): void {
190  $serverParams = $_SERVER;
191  $serverParams['SERVER_NAME'] = $serverName;
192  $serverParams['SERVER_PORT'] = $serverPort;
193  $serverParams['HTTPS'] = $ssl;
194 
196 
197  self::assertSame($isAllowed, $subject->isAllowedHostHeaderValue($httpHost, $serverParams));
198  }
199 
211  string $httpHost,
212  string $serverName,
213  bool $isAllowed,
214  string $serverPort = '80',
215  string $ssl = 'Off'
216  ): void {
217  $serverParams = $_SERVER;
218  $serverParams['REMOTE_ADDR'] = '10.0.0.1';
219  $serverParams['SERVER_NAME'] = $serverName;
220  $serverParams['SERVER_PORT'] = $serverPort;
221  $serverParams['HTTPS'] = $ssl;
222 
223  $subject = new VerifyHostHeader(‪VerifyHostHeader::ENV_TRUSTED_HOSTS_PATTERN_SERVER_NAME);
224 
225  self::assertSame($isAllowed, $subject->isAllowedHostHeaderValue($httpHost, $serverParams));
226  }
227 
234  public function ‪processThrowsExceptionForNotAllowedHostnameValues(string $httpHost, string $hostNamePattern): void
235  {
236  $this->expectException(\UnexpectedValueException::class);
237  $this->expectExceptionCode(1396795884);
238 
239  $serverParams = $_SERVER;
240  $serverParams['HTTP_HOST'] = $httpHost;
241 
242  $subject = new VerifyHostHeader($hostNamePattern);
243 
244  $requestProphecy = $this->prophesize(ServerRequestInterface::class);
245  $requestProphecy->getServerParams()->willReturn($serverParams);
246 
247  $requestHandlerProphecy = $this->prophesize(RequestHandlerInterface::class);
248 
249  $subject->process($requestProphecy->reveal(), $requestHandlerProphecy->reveal());
250  }
251 
258  public function ‪processAllowsAllHostnameValuesIfHostPatternIsSetToAllowAll(string $httpHost, string $hostNamePattern): void
259  {
260  $serverParams = $_SERVER;
261  $serverParams['HTTP_HOST'] = $httpHost;
262 
263  $subject = new VerifyHostHeader(‪VerifyHostHeader::ENV_TRUSTED_HOSTS_PATTERN_ALLOW_ALL);
264  $requestProphecy = $this->prophesize(ServerRequestInterface::class);
265  $requestProphecy->getServerParams()->willReturn($serverParams);
266 
267  $responseProphecy = $this->prophesize(ResponseInterface::class);
268 
269  $requestHandlerProphecy = $this->prophesize(RequestHandlerInterface::class);
270  $requestHandlerProphecy->handle($requestProphecy)->willReturn($responseProphecy->reveal())->shouldBeCalled();
271 
272  $subject->process($requestProphecy->reveal(), $requestHandlerProphecy->reveal());
273  }
274 }
‪TYPO3\CMS\Core\Tests\Unit\Middleware\VerifyHostHeaderTest\isAllowedHostHeaderValueReturnsFalseIfHostValueMatches
‪isAllowedHostHeaderValueReturnsFalseIfHostValueMatches(string $httpHost, string $hostNamePattern)
Definition: VerifyHostHeaderTest.php:85
‪TYPO3\CMS\Core\Tests\Unit\Middleware\VerifyHostHeaderTest\hostnamesNotMatchingTrustedHostsConfigurationDataProvider
‪static hostnamesNotMatchingTrustedHostsConfigurationDataProvider()
Definition: VerifyHostHeaderTest.php:53
‪TYPO3\CMS\Core\Tests\Unit\Middleware\VerifyHostHeaderTest\processThrowsExceptionForNotAllowedHostnameValues
‪processThrowsExceptionForNotAllowedHostnameValues(string $httpHost, string $hostNamePattern)
Definition: VerifyHostHeaderTest.php:233
‪TYPO3\CMS\Core\Tests\Unit\Middleware\VerifyHostHeaderTest
Definition: VerifyHostHeaderTest.php:28
‪TYPO3\CMS\Core\Tests\Unit\Middleware\VerifyHostHeaderTest\isAllowedHostHeaderValueWorksCorrectlyWithWithServerNamePattern
‪isAllowedHostHeaderValueWorksCorrectlyWithWithServerNamePattern(string $httpHost, string $serverName, bool $isAllowed, string $serverPort='80', string $ssl='Off')
Definition: VerifyHostHeaderTest.php:182
‪TYPO3\CMS\Core\Tests\Unit\Middleware\VerifyHostHeaderTest\isAllowedHostHeaderValueReturnsFalseIfTrustedHostsIsNotConfigured
‪isAllowedHostHeaderValueReturnsFalseIfTrustedHostsIsNotConfigured()
Definition: VerifyHostHeaderTest.php:33
‪TYPO3\CMS\Core\Tests\Unit\Middleware\VerifyHostHeaderTest\hostnamesMatchingTrustedHostsConfigurationDataProvider
‪static hostnamesMatchingTrustedHostsConfigurationDataProvider()
Definition: VerifyHostHeaderTest.php:40
‪TYPO3\CMS\Core\Tests\Unit\Middleware\VerifyHostHeaderTest\processAllowsAllHostnameValuesIfHostPatternIsSetToAllowAll
‪processAllowsAllHostnameValuesIfHostPatternIsSetToAllowAll(string $httpHost, string $hostNamePattern)
Definition: VerifyHostHeaderTest.php:257
‪TYPO3\CMS\Core\Tests\Unit\Middleware\VerifyHostHeaderTest\isAllowedHostHeaderValueReturnsTrueIfHostValueMatches
‪isAllowedHostHeaderValueReturnsTrueIfHostValueMatches(string $httpHost, string $hostNamePattern)
Definition: VerifyHostHeaderTest.php:71
‪TYPO3\CMS\Core\Tests\Unit\Middleware\VerifyHostHeaderTest\serverNamePatternDataProvider
‪serverNamePatternDataProvider()
Definition: VerifyHostHeaderTest.php:93
‪TYPO3\CMS\Core\Tests\Unit\Middleware
Definition: VerifyHostHeaderTest.php:18
‪TYPO3\CMS\Core\Tests\Unit\Middleware\VerifyHostHeaderTest\isAllowedHostHeaderValueWorksCorrectlyWithWithServerNamePatternAndSslProxy
‪isAllowedHostHeaderValueWorksCorrectlyWithWithServerNamePatternAndSslProxy(string $httpHost, string $serverName, bool $isAllowed, string $serverPort='80', string $ssl='Off')
Definition: VerifyHostHeaderTest.php:209
‪TYPO3\CMS\Core\Middleware\VerifyHostHeader\ENV_TRUSTED_HOSTS_PATTERN_ALLOW_ALL
‪const ENV_TRUSTED_HOSTS_PATTERN_ALLOW_ALL
Definition: VerifyHostHeader.php:32
‪TYPO3\CMS\Core\Middleware\VerifyHostHeader\ENV_TRUSTED_HOSTS_PATTERN_SERVER_NAME
‪const ENV_TRUSTED_HOSTS_PATTERN_SERVER_NAME
Definition: VerifyHostHeader.php:33
‪TYPO3\CMS\Core\Middleware\VerifyHostHeader
Definition: VerifyHostHeader.php:31