xref: /dokuwiki/_test/tests/inc/common_clientip.test.php (revision d5dd5d1b1d2bd9d3299e5d0114855dae264944df)
1f8369d7dSTobias Sarnowski<?php
2f8369d7dSTobias Sarnowski
3f8369d7dSTobias Sarnowskiclass common_clientIP_test extends DokuWikiTest {
4f8369d7dSTobias Sarnowski
5608cdefcSZebra North    /**
6*d5dd5d1bSAndreas Gohr     * @var mixed[] $configs Possible values for $conf['trustedproxies'].
7608cdefcSZebra North     */
8608cdefcSZebra North    private $configs = [
9608cdefcSZebra North        '^(::1|[fF][eE]80:|127\.|10\.|192\.168\.|172\.((1[6-9])|(2[0-9])|(3[0-1]))\.)',
10608cdefcSZebra North        ['::1', 'fe80::/10', '127.0.0.0/8', '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'],
11608cdefcSZebra North    ];
12445b9378SPhy
13a7580321SZebra North    /**
14a7580321SZebra North     * The data provider for clientIP() tests.
15a7580321SZebra North     *
16a7580321SZebra North     * @return mixed[][] Returns an array of test cases.
17a7580321SZebra North     */
18a7580321SZebra North    public function client_ip_all_provider() : array {
19a7580321SZebra North        // Malicious code in a header.
20a7580321SZebra North        $bad = '<?php die("hacked"); ?>';
21a7580321SZebra North
22a7580321SZebra North        // Letters A, B, C, D, E will be substitued with an IPv4 or IPv6 address.
23a7580321SZebra North        $tests = [
24a7580321SZebra North            // A single IP with no other headers.
25a7580321SZebra North            ['A', false, '', '', false, 'A'],
26a7580321SZebra North            ['A', true, '', '', false, 'A'],
27a7580321SZebra North            ['A', false, '', '', true, 'A'],
28a7580321SZebra North            ['A', true, '', '', true, 'A'],
29a7580321SZebra North
30a7580321SZebra North            // A X-Real-IP header.
31a7580321SZebra North            ['A', false, 'B', '', false, 'A'],
32a7580321SZebra North            ['A', true, 'B', '', false, 'B,A'],
33a7580321SZebra North            ['A', false, 'B', '', true, 'A'],
34a7580321SZebra North            ['A', true, 'B', '', true, 'B'],
35a7580321SZebra North
36a7580321SZebra North            // An X-Forwarded-For header from an untrusted proxy.
37a7580321SZebra North            ['A', false, 'B', 'C', false, 'A'],
38a7580321SZebra North            ['A', true, 'B', 'C', false, 'B,A'],
39a7580321SZebra North            ['A', false, 'B', 'C', true, 'A'],
40a7580321SZebra North            ['A', true, 'B', 'C', true, 'B'],
41a7580321SZebra North
42a7580321SZebra North            // An X-Forwarded-For header from a trusted proxy.
43a7580321SZebra North            ['D', false, 'B', 'C', false, 'C,D'],
44a7580321SZebra North            ['D', true, 'B', 'C', false, 'B,C,D'],
45a7580321SZebra North            ['D', false, 'B', 'C', true, 'C'],
46a7580321SZebra North            ['D', true, 'B', 'C', true, 'B'],
47a7580321SZebra North
48a7580321SZebra North            // An X-Forwarded-For header with proxies from an untrusted proxy.
49a7580321SZebra North            ['A', false, 'B', 'C,E', false, 'A'],
50a7580321SZebra North            ['A', true, 'B', 'C,E', false, 'B,A'],
51a7580321SZebra North            ['A', false, 'B', 'C,E', true, 'A'],
52a7580321SZebra North            ['A', true, 'B', 'C,E', true, 'B'],
53a7580321SZebra North
54608cdefcSZebra North            // An X-Forwarded-For header with untrusted proxies from a trusted proxy.
55608cdefcSZebra North            ['D', false, 'B', 'C,E', false, 'D'],
56608cdefcSZebra North            ['D', true, 'B', 'C,E', false, 'B,D'],
57608cdefcSZebra North            ['D', false, 'B', 'C,E', true, 'D'],
58a7580321SZebra North            ['D', true, 'B', 'C,E', true, 'B'],
59a7580321SZebra North
60a7580321SZebra North            // An X-Forwarded-For header with an invalid proxy from a trusted proxy.
61608cdefcSZebra North            ['D', false, 'B', 'C,invalid,E', false, 'D'],
62608cdefcSZebra North            ['D', true, 'B', 'C,invalid,E', false, 'B,D'],
63608cdefcSZebra North            ['D', false, 'B', 'C,invalid,E', true, 'D'],
64a7580321SZebra North            ['D', true, 'B', 'C,invalid,E', true, 'B'],
65a7580321SZebra North
66a7580321SZebra North            // Malicious X-Real-IP and X-Forwarded-For headers.
67a7580321SZebra North            ['A', false, $bad, $bad, false, 'A'],
68a7580321SZebra North            ['A', true, $bad, $bad, false, 'A'],
69a7580321SZebra North            ['A', false, $bad, $bad, true, 'A'],
70a7580321SZebra North            ['A', true, $bad, $bad, true, 'A'],
71a7580321SZebra North
72a7580321SZebra North            // Malicious remote address, X-Real-IP and X-Forwarded-For headers.
73a7580321SZebra North            [$bad, false, $bad, $bad, false, '0.0.0.0'],
74a7580321SZebra North            [$bad, true, $bad, $bad, false, '0.0.0.0'],
75a7580321SZebra North            [$bad, false, $bad, $bad, true, '0.0.0.0'],
76a7580321SZebra North            [$bad, true, $bad, $bad, true, '0.0.0.0'],
77a7580321SZebra North        ];
78a7580321SZebra North
79a7580321SZebra North        return $tests;
80f8369d7dSTobias Sarnowski    }
81f8369d7dSTobias Sarnowski
82a7580321SZebra North    /**
83a7580321SZebra North     * Test clientIP() with IPv6 addresses.
84a7580321SZebra North     *
85a7580321SZebra North     * @dataProvider client_ip_all_provider
86a7580321SZebra North     *
87a7580321SZebra North     * @param string $remoteAddr   The TCP/IP remote IP address.
88a7580321SZebra North     * @param bool   $useRealIp    True if using the X-Real-IP header is enabled in the config.
89a7580321SZebra North     * @param string $realIp       The X-Real-IP header.
90a7580321SZebra North     * @param string $forwardedFor The X-Forwarded-For header.
91a7580321SZebra North     * @param bool   $single       True to return the most likely client IP, false to return all candidates.
92a7580321SZebra North     * @param string $expected     The expected function result.
93a7580321SZebra North     *
94a7580321SZebra North     * @return void
95a7580321SZebra North     */
96a7580321SZebra North    public function test_client_ip_v4(string $remoteAddr, bool $useRealIp, string $realIp, string $forwardedFor, bool $single, string $expected) : void {
97a7580321SZebra North        global $conf;
98a7580321SZebra North
99a7580321SZebra North        $addresses = [
100a7580321SZebra North            'A' => '123.123.123.123',
101a7580321SZebra North            'B' => '22.22.22.22',
102a7580321SZebra North            'C' => '33.33.33.33',
103a7580321SZebra North            'D' => '192.168.11.1',
104a7580321SZebra North            'E' => '44.44.44.44',
105a7580321SZebra North        ];
106a7580321SZebra North
107a7580321SZebra North        $_SERVER['REMOTE_ADDR']          = str_replace(array_keys($addresses), array_values($addresses), $remoteAddr);
108a7580321SZebra North        $_SERVER['HTTP_X_REAL_IP']       = str_replace(array_keys($addresses), array_values($addresses), $realIp);
109a7580321SZebra North        $_SERVER['HTTP_X_FORWARDED_FOR'] = str_replace(array_keys($addresses), array_values($addresses), $forwardedFor);
110a7580321SZebra North        $conf['realip'] = $useRealIp;
111a7580321SZebra North
112608cdefcSZebra North        foreach ($this->configs as $config) {
113*d5dd5d1bSAndreas Gohr            $conf['trustedproxies'] = $config;
114a7580321SZebra North            $this->assertEquals(str_replace(array_keys($addresses), array_values($addresses), $expected), clientIP($single));
115f8369d7dSTobias Sarnowski        }
116608cdefcSZebra North    }
117f8369d7dSTobias Sarnowski
118a7580321SZebra North    /**
119a7580321SZebra North     * Test clientIP() with IPv6 addresses.
120a7580321SZebra North     *
121a7580321SZebra North     * @dataProvider client_ip_all_provider
122a7580321SZebra North     *
123a7580321SZebra North     * @param string $remoteAddr   The TCP/IP remote IP address.
124a7580321SZebra North     * @param bool   $useRealIp    True if using the X-Real-IP header is enabled in the config.
125a7580321SZebra North     * @param string $realIp       The X-Real-IP header.
126a7580321SZebra North     * @param string $forwardedFor The X-Forwarded-For header.
127a7580321SZebra North     * @param bool   $single       True to return the most likely client IP, false to return all candidates.
128a7580321SZebra North     * @param string $expected     The expected function result.
129a7580321SZebra North     *
130a7580321SZebra North     * @return void
131a7580321SZebra North     */
132a7580321SZebra North    public function test_client_ip_v6(string $remoteAddr, bool $useRealIp, string $realIp, string $forwardedFor, bool $single, string $expected) : void {
133a7580321SZebra North        global $conf;
134a7580321SZebra North
135a7580321SZebra North        $addresses = [
136a7580321SZebra North            'A' => '1234:1234:1234:1234:1234:1234:1234:1234',
137a7580321SZebra North            'B' => '22:aa:22:bb:22:cc:22:dd',
138a7580321SZebra North            'C' => '33:aa:33:bb:33:cc:33:dd',
139a7580321SZebra North            'D' => '::1',
140a7580321SZebra North            'E' => '44:aa:44:bb:44:cc:44:dd',
141a7580321SZebra North        ];
142a7580321SZebra North
143a7580321SZebra North        $_SERVER['REMOTE_ADDR']          = str_replace(array_keys($addresses), array_values($addresses), $remoteAddr);
144a7580321SZebra North        $_SERVER['HTTP_X_REAL_IP']       = str_replace(array_keys($addresses), array_values($addresses), $realIp);
145a7580321SZebra North        $_SERVER['HTTP_X_FORWARDED_FOR'] = str_replace(array_keys($addresses), array_values($addresses), $forwardedFor);
146a7580321SZebra North        $conf['realip'] = $useRealIp;
147a7580321SZebra North
148608cdefcSZebra North        foreach ($this->configs as $config) {
149*d5dd5d1bSAndreas Gohr            $conf['trustedproxies'] = $config;
150a7580321SZebra North            $this->assertEquals(str_replace(array_keys($addresses), array_values($addresses), $expected), clientIP($single));
151f8369d7dSTobias Sarnowski        }
152f8369d7dSTobias Sarnowski    }
153608cdefcSZebra North}
154