]>
Commit | Line | Data |
---|---|---|
5840c75c | 1 | /* Test getnetbyname and getnetbyaddr. |
04277e02 | 2 | Copyright (C) 2016-2019 Free Software Foundation, Inc. |
5840c75c FW |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library; if not, see | |
17 | <http://www.gnu.org/licenses/>. */ | |
18 | ||
19 | #include <netdb.h> | |
20 | #include <stdlib.h> | |
21 | #include <string.h> | |
22 | #include <support/check.h> | |
23 | #include <support/check_nss.h> | |
24 | #include <support/resolv_test.h> | |
25 | #include <support/support.h> | |
26 | #include <support/xmemstream.h> | |
27 | ||
28 | static void | |
29 | send_ptr (struct resolv_response_builder *b, | |
30 | const char *qname, uint16_t qclass, uint16_t qtype, | |
31 | const char *alias) | |
32 | { | |
33 | resolv_response_init (b, (struct resolv_response_flags) {}); | |
34 | resolv_response_add_question (b, qname, qclass, qtype); | |
35 | resolv_response_section (b, ns_s_an); | |
36 | resolv_response_open_record (b, qname, qclass, T_PTR, 0); | |
37 | resolv_response_add_name (b, alias); | |
38 | resolv_response_close_record (b); | |
39 | } | |
40 | ||
41 | static void | |
42 | handle_code (const struct resolv_response_context *ctx, | |
43 | struct resolv_response_builder *b, | |
44 | const char *qname, uint16_t qclass, uint16_t qtype, | |
45 | int code) | |
46 | { | |
47 | switch (code) | |
48 | { | |
49 | case 1: | |
50 | send_ptr (b, qname, qclass, qtype, "1.in-addr.arpa"); | |
51 | break; | |
52 | case 2: | |
53 | send_ptr (b, qname, qclass, qtype, "2.1.in-addr.arpa"); | |
54 | break; | |
55 | case 3: | |
56 | send_ptr (b, qname, qclass, qtype, "3.2.1.in-addr.arpa"); | |
57 | break; | |
58 | case 4: | |
59 | send_ptr (b, qname, qclass, qtype, "4.3.2.1.in-addr.arpa"); | |
60 | break; | |
61 | case 5: | |
62 | /* Test multiple PTR records. */ | |
63 | resolv_response_init (b, (struct resolv_response_flags) {}); | |
64 | resolv_response_add_question (b, qname, qclass, qtype); | |
65 | resolv_response_section (b, ns_s_an); | |
66 | resolv_response_open_record (b, qname, qclass, T_PTR, 0); | |
67 | resolv_response_add_name (b, "127.in-addr.arpa"); | |
68 | resolv_response_close_record (b); | |
69 | resolv_response_open_record (b, qname, qclass, T_PTR, 0); | |
70 | resolv_response_add_name (b, "0.in-addr.arpa"); | |
71 | resolv_response_close_record (b); | |
72 | break; | |
73 | case 6: | |
74 | /* Test skipping of RRSIG record. */ | |
75 | resolv_response_init (b, (struct resolv_response_flags) { }); | |
76 | resolv_response_add_question (b, qname, qclass, qtype); | |
77 | resolv_response_section (b, ns_s_an); | |
78 | ||
79 | resolv_response_open_record (b, qname, qclass, T_PTR, 0); | |
80 | resolv_response_add_name (b, "127.in-addr.arpa"); | |
81 | resolv_response_close_record (b); | |
82 | ||
83 | resolv_response_open_record (b, qname, qclass, 46 /* RRSIG */, 0); | |
84 | { | |
85 | char buf[500]; | |
86 | memset (buf, 0x3f, sizeof (buf)); | |
87 | resolv_response_add_data (b, buf, sizeof (buf)); | |
88 | } | |
89 | resolv_response_close_record (b); | |
90 | ||
91 | resolv_response_open_record (b, qname, qclass, T_PTR, 0); | |
92 | resolv_response_add_name (b, "0.in-addr.arpa"); | |
93 | resolv_response_close_record (b); | |
94 | break; | |
95 | case 7: | |
96 | /* Test CNAME handling. */ | |
97 | resolv_response_init (b, (struct resolv_response_flags) { }); | |
98 | resolv_response_add_question (b, qname, qclass, qtype); | |
99 | resolv_response_section (b, ns_s_an); | |
100 | resolv_response_open_record (b, qname, qclass, T_CNAME, 0); | |
101 | resolv_response_add_name (b, "cname.example"); | |
102 | resolv_response_close_record (b); | |
103 | resolv_response_open_record (b, "cname.example", qclass, T_PTR, 0); | |
104 | resolv_response_add_name (b, "4.3.2.1.in-addr.arpa"); | |
105 | resolv_response_close_record (b); | |
106 | break; | |
107 | ||
108 | case 100: | |
109 | resolv_response_init (b, (struct resolv_response_flags) { .rcode = 0, }); | |
110 | resolv_response_add_question (b, qname, qclass, qtype); | |
111 | break; | |
112 | case 101: | |
113 | resolv_response_init (b, (struct resolv_response_flags) | |
114 | { .rcode = NXDOMAIN, }); | |
115 | resolv_response_add_question (b, qname, qclass, qtype); | |
116 | break; | |
117 | case 102: | |
118 | resolv_response_init (b, (struct resolv_response_flags) {.rcode = SERVFAIL}); | |
119 | resolv_response_add_question (b, qname, qclass, qtype); | |
120 | break; | |
121 | case 103: | |
122 | /* Check response length matching. */ | |
123 | if (!ctx->tcp) | |
124 | { | |
125 | resolv_response_init (b, (struct resolv_response_flags) {.tc = true}); | |
126 | resolv_response_add_question (b, qname, qclass, qtype); | |
127 | } | |
128 | else | |
129 | { | |
130 | resolv_response_init (b, (struct resolv_response_flags) {.ancount = 1}); | |
131 | resolv_response_add_question (b, qname, qclass, qtype); | |
132 | resolv_response_section (b, ns_s_an); | |
133 | resolv_response_open_record (b, qname, qclass, T_PTR, 0); | |
134 | resolv_response_add_name (b, "127.in-addr.arpa"); | |
135 | resolv_response_close_record (b); | |
136 | resolv_response_open_record (b, qname, qclass, T_PTR, 0); | |
137 | resolv_response_add_name (b, "example"); | |
138 | resolv_response_close_record (b); | |
139 | ||
140 | resolv_response_open_record (b, qname, qclass, T_PTR, 0); | |
141 | size_t to_fill = 65535 - resolv_response_length (b) | |
142 | - 2 /* length, "n" */ - 2 /* compression reference */ | |
143 | - 2 /* RR type */; | |
144 | for (size_t i = 0; i < to_fill; ++i) | |
145 | resolv_response_add_data (b, "", 1); | |
146 | resolv_response_close_record (b); | |
147 | resolv_response_add_name (b, "n.example"); | |
148 | uint16_t rrtype = htons (T_PTR); | |
149 | resolv_response_add_data (b, &rrtype, sizeof (rrtype)); | |
150 | } | |
151 | break; | |
ac806026 AH |
152 | case 104: |
153 | send_ptr (b, qname, qclass, qtype, "host.example"); | |
154 | break; | |
5840c75c FW |
155 | default: |
156 | FAIL_EXIT1 ("invalid QNAME: %s (code %d)", qname, code); | |
157 | } | |
158 | } | |
159 | ||
160 | static void | |
161 | response (const struct resolv_response_context *ctx, | |
162 | struct resolv_response_builder *b, | |
163 | const char *qname, uint16_t qclass, uint16_t qtype) | |
164 | { | |
165 | int code; | |
166 | if (strstr (qname, "in-addr.arpa") == NULL) | |
167 | { | |
168 | char *tail; | |
169 | if (sscanf (qname, "code%d.%ms", &code, &tail) != 2 | |
170 | || strcmp (tail, "example") != 0) | |
171 | FAIL_EXIT1 ("invalid QNAME: %s", qname); | |
172 | free (tail); | |
173 | handle_code (ctx, b, qname, qclass, qtype, code); | |
174 | } | |
175 | else | |
176 | { | |
177 | /* Reverse lookup. */ | |
178 | int components[4]; | |
179 | char *tail; | |
180 | if (sscanf (qname, "%d.%d.%d.%d.%ms", | |
181 | components, components + 1, components + 2, components + 3, | |
182 | &tail) != 5 | |
183 | || strcmp (tail, "in-addr.arpa") != 0) | |
184 | FAIL_EXIT1 ("invalid QNAME: %s", qname); | |
185 | free (tail); | |
186 | handle_code (ctx, b, qname, qclass, qtype, components[3]); | |
187 | } | |
188 | } | |
189 | ||
190 | static void | |
191 | check_reverse (int code, const char *expected) | |
192 | { | |
193 | char *query = xasprintf ("code=%d", code); | |
194 | check_netent (query, getnetbyaddr (code, AF_INET), expected); | |
195 | free (query); | |
196 | } | |
197 | ||
198 | /* Test for CVE-2016-3075. */ | |
199 | static void | |
200 | check_long_name (void) | |
201 | { | |
202 | struct xmemstream mem; | |
203 | xopen_memstream (&mem); | |
204 | ||
205 | char label[65]; | |
206 | memset (label, 'x', 63); | |
207 | label[63] = '.'; | |
208 | label[64] = '\0'; | |
209 | for (unsigned i = 0; i < 64 * 1024 * 1024 / strlen (label); ++i) | |
210 | fprintf (mem.out, "%s", label); | |
211 | ||
212 | xfclose_memstream (&mem); | |
213 | ||
214 | check_netent ("long name", getnetbyname (mem.buffer), | |
215 | "error: NO_RECOVERY\n"); | |
216 | ||
217 | free (mem.buffer); | |
218 | } | |
219 | ||
a19c0a1d FW |
220 | static int |
221 | do_test (void) | |
5840c75c FW |
222 | { |
223 | struct resolv_test *obj = resolv_test_start | |
224 | ((struct resolv_redirect_config) | |
225 | { | |
226 | .response_callback = response | |
227 | }); | |
228 | ||
229 | /* Lookup by name, success cases. */ | |
230 | check_netent ("code1.example", getnetbyname ("code1.example"), | |
231 | "alias: 1.in-addr.arpa\n" | |
232 | "net: 0x00000001\n"); | |
233 | check_netent ("code2.example", getnetbyname ("code2.example"), | |
234 | "alias: 2.1.in-addr.arpa\n" | |
235 | "net: 0x00000102\n"); | |
236 | check_netent ("code3.example", getnetbyname ("code3.example"), | |
237 | "alias: 3.2.1.in-addr.arpa\n" | |
238 | "net: 0x00010203\n"); | |
239 | check_netent ("code4.example", getnetbyname ("code4.example"), | |
240 | "alias: 4.3.2.1.in-addr.arpa\n" | |
241 | "net: 0x01020304\n"); | |
242 | check_netent ("code5.example", getnetbyname ("code5.example"), | |
243 | "alias: 127.in-addr.arpa\n" | |
244 | "alias: 0.in-addr.arpa\n" | |
245 | "net: 0x0000007f\n"); | |
246 | check_netent ("code6.example", getnetbyname ("code6.example"), | |
247 | "alias: 127.in-addr.arpa\n" | |
248 | "alias: 0.in-addr.arpa\n" | |
249 | "net: 0x0000007f\n"); | |
250 | check_netent ("code7.example", getnetbyname ("code7.example"), | |
251 | "alias: 4.3.2.1.in-addr.arpa\n" | |
252 | "net: 0x01020304\n"); | |
253 | ||
254 | /* Lookup by name, failure cases. */ | |
255 | check_netent ("code100.example", getnetbyname ("code100.example"), | |
256 | "error: NO_ADDRESS\n"); | |
257 | check_netent ("code101.example", getnetbyname ("code101.example"), | |
258 | "error: HOST_NOT_FOUND\n"); | |
259 | check_netent ("code102.example", getnetbyname ("code102.example"), | |
260 | "error: TRY_AGAIN\n"); | |
261 | check_netent ("code103.example", getnetbyname ("code103.example"), | |
262 | "error: NO_RECOVERY\n"); | |
ac806026 AH |
263 | /* Test bug #17630. */ |
264 | check_netent ("code104.example", getnetbyname ("code104.example"), | |
265 | "error: TRY_AGAIN\n"); | |
5840c75c FW |
266 | |
267 | /* Lookup by address, success cases. */ | |
268 | check_reverse (1, | |
269 | "name: 1.in-addr.arpa\n" | |
270 | "net: 0x00000001\n"); | |
271 | check_reverse (2, | |
272 | "name: 2.1.in-addr.arpa\n" | |
273 | "net: 0x00000002\n"); | |
274 | check_reverse (3, | |
275 | "name: 3.2.1.in-addr.arpa\n" | |
276 | "net: 0x00000003\n"); | |
277 | check_reverse (4, | |
278 | "name: 4.3.2.1.in-addr.arpa\n" | |
279 | "net: 0x00000004\n"); | |
280 | check_reverse (5, | |
281 | "name: 127.in-addr.arpa\n" | |
282 | "alias: 0.in-addr.arpa\n" | |
283 | "net: 0x00000005\n"); | |
284 | check_reverse (6, | |
285 | "name: 127.in-addr.arpa\n" | |
286 | "alias: 0.in-addr.arpa\n" | |
287 | "net: 0x00000006\n"); | |
288 | check_reverse (7, | |
289 | "name: 4.3.2.1.in-addr.arpa\n" | |
290 | "net: 0x00000007\n"); | |
291 | ||
292 | /* Lookup by address, failure cases. */ | |
293 | check_reverse (100, | |
294 | "error: NO_ADDRESS\n"); | |
295 | check_reverse (101, | |
296 | "error: HOST_NOT_FOUND\n"); | |
297 | check_reverse (102, | |
298 | "error: TRY_AGAIN\n"); | |
299 | check_reverse (103, | |
300 | "error: NO_RECOVERY\n"); | |
301 | ||
302 | check_long_name (); | |
303 | ||
304 | resolv_test_end (obj); | |
a19c0a1d FW |
305 | |
306 | return 0; | |
5840c75c | 307 | } |
a19c0a1d FW |
308 | |
309 | #include <support/test-driver.c> |