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