Skip to content

Commit 4ca9774

Browse files
authored
Merge pull request dokuwiki#4466 from dokuwiki/trustedproxies
Remove remaining uses of old proxy settings
2 parents 0c1ebe4 + 7caad01 commit 4ca9774

File tree

7 files changed

+222
-184
lines changed

7 files changed

+222
-184
lines changed

_test/tests/inc/Ip.test.php renamed to _test/tests/inc/IpTest.php

Lines changed: 141 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
<?php
22

3+
namespace dokuwiki\test;
4+
5+
use dokuwiki\Input\Input;
36
use dokuwiki\Ip;
47

5-
class ip_test extends DokuWikiTest {
8+
class IpTest extends \DokuWikiTest {
69

710
/**
811
* The data provider for ipToNumber() tests.
@@ -294,4 +297,141 @@ public function test_forwarded_for($config, string $header, string $remoteAddr,
294297

295298
$this->assertSame($expected, $result);
296299
}
300+
301+
/**
302+
* Data provider for test_is_ssl().
303+
*
304+
* @return mixed[][] Returns an array of test cases.
305+
*/
306+
public function is_ssl_provider(): array
307+
{
308+
// The new default configuration value.
309+
$default = ['::1', 'fe80::/10', '127.0.0.0/8', '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'];
310+
311+
$tests = [
312+
// Running behind an SSL proxy, HTTP between server and proxy
313+
// Proxy (REMOTE_ADDR) is matched by trustedproxies config
314+
// HTTPS not set, HTTP_X_FORWARDED_PROTO set to https
315+
[$default, '127.0.0.1', '', 'https', true],
316+
317+
// Running behind an SSL proxy, HTTP between server and proxy
318+
// Proxy (REMOTE_ADDR) is not matched by trustedproxies config
319+
// HTTPS not set, HTTP_X_FORWARDED_PROTO set to https
320+
[[], '8.8.8.8', '', 'https', false],
321+
322+
// Running behind a plain HTTP proxy, HTTP between server and proxy
323+
// HTTPS not set, HTTP_X_FORWARDED_PROTO set to http
324+
[$default, '127.0.0.1', '', 'http', false],
325+
326+
// Running behind an SSL proxy, HTTP between server and proxy
327+
// HTTPS set to off, HTTP_X_FORWARDED_PROTO set to https
328+
[$default, '127.0.0.1', 'off', 'https', true],
329+
330+
// Not running behind a proxy, HTTPS server
331+
// HTTPS set to on, HTTP_X_FORWARDED_PROTO not set
332+
[[], '8.8.8.8', 'on', '', true],
333+
334+
// Not running behind a proxy, plain HTTP server
335+
// HTTPS not set, HTTP_X_FORWARDED_PROTO not set
336+
[[], '8.8.8.8', '', '', false],
337+
338+
// Not running behind a proxy, plain HTTP server
339+
// HTTPS set to off, HTTP_X_FORWARDED_PROTO not set
340+
[[], '8.8.8.8', 'off', '', false],
341+
342+
// Running behind an SSL proxy, SSL between proxy and HTTP server
343+
// HTTPS set to on, HTTP_X_FORWARDED_PROTO set to https
344+
[$default, '127.0.0.1', 'on', 'https', true],
345+
];
346+
347+
return $tests;
348+
}
349+
350+
/**
351+
* Test isSsl().
352+
*
353+
* @dataProvider is_ssl_provider
354+
*
355+
* @param string|string[] $config The trustedproxies config value.
356+
* @param string $remoteAddr The REMOTE_ADDR value.
357+
* @param string $https The HTTPS value.
358+
* @param string $forwardedProto The HTTP_X_FORWARDED_PROTO value.
359+
* @param bool $expected The expected result from isSsl().
360+
*
361+
* @return void
362+
*/
363+
public function test_is_ssl($config, string $remoteAddr, string $https, string $forwardedProto, bool $expected): void
364+
{
365+
/* @var Input $INPUT */
366+
global $INPUT, $conf;
367+
368+
$conf['trustedproxies'] = $config;
369+
$INPUT->server->set('REMOTE_ADDR', $remoteAddr);
370+
$INPUT->server->set('HTTPS', $https);
371+
$INPUT->server->set('HTTP_X_FORWARDED_PROTO', $forwardedProto);
372+
373+
$result = Ip::isSsl();
374+
375+
$this->assertSame($expected, $result);
376+
}
377+
378+
/**
379+
* Data provider for test_host_name().
380+
*
381+
* @return mixed[][] Returns an array of test cases.
382+
*/
383+
public function host_name_provider(): array
384+
{
385+
// The new default configuration value.
386+
$default = ['::1', 'fe80::/10', '127.0.0.0/8', '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'];
387+
388+
$tests = [
389+
// X-Forwarded-Host with trusted proxy
390+
[$default, '127.0.0.1', 'proxy.example.com', 'www.example.com', 'server.local', 'proxy.example.com'],
391+
392+
// X-Forwarded-Host with untrusted proxy (should fall back to HTTP_HOST)
393+
[[], '8.8.8.8', 'proxy.example.com', 'www.example.com', 'server.local', 'www.example.com'],
394+
395+
// No X-Forwarded-Host, use HTTP_HOST
396+
[$default, '127.0.0.1', '', 'www.example.com', 'server.local', 'www.example.com'],
397+
398+
// No X-Forwarded-Host or HTTP_HOST, use SERVER_NAME
399+
[$default, '127.0.0.1', '', '', 'server.local', 'server.local'],
400+
401+
// No headers set, should fall back to system hostname
402+
[$default, '127.0.0.1', '', '', '', php_uname('n')],
403+
];
404+
405+
return $tests;
406+
}
407+
408+
/**
409+
* Test hostName().
410+
*
411+
* @dataProvider host_name_provider
412+
*
413+
* @param string|string[] $config The trustedproxies config value.
414+
* @param string $remoteAddr The REMOTE_ADDR value.
415+
* @param string $forwardedHost The HTTP_X_FORWARDED_HOST value.
416+
* @param string $httpHost The HTTP_HOST value.
417+
* @param string $serverName The SERVER_NAME value.
418+
* @param string $expected The expected result from hostName().
419+
*
420+
* @return void
421+
*/
422+
public function test_host_name($config, string $remoteAddr, string $forwardedHost, string $httpHost, string $serverName, string $expected): void
423+
{
424+
/* @var Input $INPUT */
425+
global $INPUT, $conf;
426+
427+
$conf['trustedproxies'] = $config;
428+
$INPUT->server->set('REMOTE_ADDR', $remoteAddr);
429+
$INPUT->server->set('HTTP_X_FORWARDED_HOST', $forwardedHost);
430+
$INPUT->server->set('HTTP_HOST', $httpHost);
431+
$INPUT->server->set('SERVER_NAME', $serverName);
432+
433+
$result = Ip::hostName();
434+
435+
$this->assertSame($expected, $result);
436+
}
297437
}

_test/tests/inc/init_checkssl.test.php

Lines changed: 0 additions & 119 deletions
This file was deleted.

inc/Ip.php

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22

33
/**
4-
* DokuWiki IP address functions.
4+
* DokuWiki IP address and reverse proxy functions.
55
*
66
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
77
* @author Zebra North <[email protected]>
@@ -280,4 +280,53 @@ public static function clientIps(): array
280280

281281
return $ips;
282282
}
283+
284+
/**
285+
* Get the host name of the server.
286+
*
287+
* The host name is sourced from, in order of preference:
288+
*
289+
* - The X-Forwarded-Host header if it exists and the proxies are trusted.
290+
* - The HTTP_HOST header.
291+
* - The SERVER_NAME header.
292+
* - The system's host name.
293+
*
294+
* @return string Returns the host name of the server.
295+
*/
296+
public static function hostName(): string
297+
{
298+
/* @var Input $INPUT */
299+
global $INPUT;
300+
301+
$remoteAddr = $INPUT->server->str('REMOTE_ADDR');
302+
if ($INPUT->server->str('HTTP_X_FORWARDED_HOST') && self::proxyIsTrusted($remoteAddr)) {
303+
return $INPUT->server->str('HTTP_X_FORWARDED_HOST');
304+
} elseif ($INPUT->server->str('HTTP_HOST')) {
305+
return $INPUT->server->str('HTTP_HOST');
306+
} elseif ($INPUT->server->str('SERVER_NAME')) {
307+
return $INPUT->server->str('SERVER_NAME');
308+
} else {
309+
return php_uname('n');
310+
}
311+
}
312+
313+
/**
314+
* Is the connection using the HTTPS protocol?
315+
*
316+
* Will use the X-Forwarded-Proto header if it exists and the proxies are trusted, otherwise
317+
* the HTTPS environment is used.
318+
*
319+
* @return bool
320+
*/
321+
public static function isSsl(): bool
322+
{
323+
/* @var Input $INPUT */
324+
global $INPUT;
325+
326+
$remoteAddr = $INPUT->server->str('REMOTE_ADDR');
327+
if ($INPUT->server->has('HTTP_X_FORWARDED_PROTO') && self::proxyIsTrusted($remoteAddr)) {
328+
return $INPUT->server->str('HTTP_X_FORWARDED_PROTO') === 'https';
329+
}
330+
return !preg_match('/^(|off|false|disabled)$/i', $INPUT->server->str('HTTPS', 'off'));
331+
}
283332
}

inc/auth.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ function auth_logoff($keepbc = false)
536536
setcookie(DOKU_COOKIE, '', [
537537
'expires' => time() - 600000,
538538
'path' => $cookieDir,
539-
'secure' => ($conf['securecookie'] && is_ssl()),
539+
'secure' => ($conf['securecookie'] && \dokuwiki\Ip::isSsl()),
540540
'httponly' => true,
541541
'samesite' => $conf['samesitecookie'] ?: null, // null means browser default
542542
]);
@@ -1402,7 +1402,7 @@ function auth_setCookie($user, $pass, $sticky)
14021402
setcookie(DOKU_COOKIE, $cookie, [
14031403
'expires' => $time,
14041404
'path' => $cookieDir,
1405-
'secure' => ($conf['securecookie'] && is_ssl()),
1405+
'secure' => ($conf['securecookie'] && \dokuwiki\Ip::isSsl()),
14061406
'httponly' => true,
14071407
'samesite' => $conf['samesitecookie'] ?: null, // null means browser default
14081408
]);

inc/common.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1957,7 +1957,7 @@ function set_doku_pref($pref, $val)
19571957
setcookie('DOKU_PREFS', $cookieVal, [
19581958
'expires' => time() + 365 * 24 * 3600,
19591959
'path' => $cookieDir,
1960-
'secure' => ($conf['securecookie'] && is_ssl()),
1960+
'secure' => ($conf['securecookie'] && Ip::isSsl()),
19611961
'samesite' => 'Lax'
19621962
]);
19631963
}

0 commit comments

Comments
 (0)