1/* Test getnetbyname and getnetbyaddr.
2 Copyright (C) 2016-2022 Free Software Foundation, Inc.
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 <https://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
28static void
29send_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, name: qname, class: qclass, type: qtype);
35 resolv_response_section (b, ns_s_an);
36 resolv_response_open_record (b, name: qname, class: qclass, T_PTR, ttl: 0);
37 resolv_response_add_name (b, name: alias);
38 resolv_response_close_record (b);
39}
40
41static void
42handle_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, alias: "1.in-addr.arpa");
51 break;
52 case 2:
53 send_ptr (b, qname, qclass, qtype, alias: "2.1.in-addr.arpa");
54 break;
55 case 3:
56 send_ptr (b, qname, qclass, qtype, alias: "3.2.1.in-addr.arpa");
57 break;
58 case 4:
59 send_ptr (b, qname, qclass, qtype, alias: "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, name: qname, class: qclass, type: qtype);
65 resolv_response_section (b, ns_s_an);
66 resolv_response_open_record (b, name: qname, class: qclass, T_PTR, ttl: 0);
67 resolv_response_add_name (b, name: "127.in-addr.arpa");
68 resolv_response_close_record (b);
69 resolv_response_open_record (b, name: qname, class: qclass, T_PTR, ttl: 0);
70 resolv_response_add_name (b, name: "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, name: qname, class: qclass, type: qtype);
77 resolv_response_section (b, ns_s_an);
78
79 resolv_response_open_record (b, name: qname, class: qclass, T_PTR, ttl: 0);
80 resolv_response_add_name (b, name: "127.in-addr.arpa");
81 resolv_response_close_record (b);
82
83 resolv_response_open_record (b, name: qname, class: qclass, type: 46 /* RRSIG */, ttl: 0);
84 {
85 char buf[500];
86 memset (s: buf, c: 0x3f, n: 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, name: qname, class: qclass, T_PTR, ttl: 0);
92 resolv_response_add_name (b, name: "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, name: qname, class: qclass, type: qtype);
99 resolv_response_section (b, ns_s_an);
100 resolv_response_open_record (b, name: qname, class: qclass, T_CNAME, ttl: 0);
101 resolv_response_add_name (b, name: "cname.example");
102 resolv_response_close_record (b);
103 resolv_response_open_record (b, name: "cname.example", class: qclass, T_PTR, ttl: 0);
104 resolv_response_add_name (b, name: "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, name: qname, class: qclass, type: qtype);
111 break;
112 case 101:
113 resolv_response_init (b, (struct resolv_response_flags)
114 { .rcode = NXDOMAIN, });
115 resolv_response_add_question (b, name: qname, class: qclass, type: qtype);
116 break;
117 case 102:
118 resolv_response_init (b, (struct resolv_response_flags) {.rcode = SERVFAIL});
119 resolv_response_add_question (b, name: qname, class: qclass, type: 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, name: qname, class: qclass, type: qtype);
127 }
128 else
129 {
130 resolv_response_init (b, (struct resolv_response_flags) {.ancount = 1});
131 resolv_response_add_question (b, name: qname, class: qclass, type: qtype);
132 resolv_response_section (b, ns_s_an);
133 resolv_response_open_record (b, name: qname, class: qclass, T_PTR, ttl: 0);
134 resolv_response_add_name (b, name: "127.in-addr.arpa");
135 resolv_response_close_record (b);
136 resolv_response_open_record (b, name: qname, class: qclass, T_PTR, ttl: 0);
137 resolv_response_add_name (b, name: "example");
138 resolv_response_close_record (b);
139
140 resolv_response_open_record (b, name: qname, class: qclass, T_PTR, ttl: 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, name: "n.example");
148 uint16_t rrtype = htons (T_PTR);
149 resolv_response_add_data (b, &rrtype, sizeof (rrtype));
150 }
151 break;
152 case 104:
153 send_ptr (b, qname, qclass, qtype, alias: "host.example");
154 break;
155 default:
156 FAIL_EXIT1 ("invalid QNAME: %s (code %d)", qname, code);
157 }
158}
159
160static void
161response (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 (haystack: qname, needle: "in-addr.arpa") == NULL)
167 {
168 char *tail;
169 if (sscanf (s: qname, format: "code%d.%ms", &code, &tail) != 2
170 || strcmp (s1: tail, s2: "example") != 0)
171 FAIL_EXIT1 ("invalid QNAME: %s", qname);
172 free (ptr: 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 (s: qname, format: "%d.%d.%d.%d.%ms",
181 components, components + 1, components + 2, components + 3,
182 &tail) != 5
183 || strcmp (s1: tail, s2: "in-addr.arpa") != 0)
184 FAIL_EXIT1 ("invalid QNAME: %s", qname);
185 free (ptr: tail);
186 handle_code (ctx, b, qname, qclass, qtype, code: components[3]);
187 }
188}
189
190static void
191check_reverse (int code, const char *expected)
192{
193 char *query = xasprintf (format: "code=%d", code);
194 check_netent (query_description: query, getnetbyaddr (net: code, AF_INET), expected);
195 free (ptr: query);
196}
197
198/* Test for CVE-2016-3075. */
199static void
200check_long_name (void)
201{
202 struct xmemstream mem;
203 xopen_memstream (stream: &mem);
204
205 char label[65];
206 memset (s: label, c: 'x', n: 63);
207 label[63] = '.';
208 label[64] = '\0';
209 for (unsigned i = 0; i < 64 * 1024 * 1024 / strlen (s: label); ++i)
210 fprintf (stream: mem.out, format: "%s", label);
211
212 xfclose_memstream (stream: &mem);
213
214 check_netent (query_description: "long name", getnetbyname (name: mem.buffer),
215 expected: "error: NO_RECOVERY\n");
216
217 free (ptr: mem.buffer);
218}
219
220static int
221do_test (void)
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 (query_description: "code1.example", getnetbyname (name: "code1.example"),
231 expected: "alias: 1.in-addr.arpa\n"
232 "net: 0x00000001\n");
233 check_netent (query_description: "code2.example", getnetbyname (name: "code2.example"),
234 expected: "alias: 2.1.in-addr.arpa\n"
235 "net: 0x00000102\n");
236 check_netent (query_description: "code3.example", getnetbyname (name: "code3.example"),
237 expected: "alias: 3.2.1.in-addr.arpa\n"
238 "net: 0x00010203\n");
239 check_netent (query_description: "code4.example", getnetbyname (name: "code4.example"),
240 expected: "alias: 4.3.2.1.in-addr.arpa\n"
241 "net: 0x01020304\n");
242 check_netent (query_description: "code5.example", getnetbyname (name: "code5.example"),
243 expected: "alias: 127.in-addr.arpa\n"
244 "alias: 0.in-addr.arpa\n"
245 "net: 0x0000007f\n");
246 check_netent (query_description: "code6.example", getnetbyname (name: "code6.example"),
247 expected: "alias: 127.in-addr.arpa\n"
248 "alias: 0.in-addr.arpa\n"
249 "net: 0x0000007f\n");
250 check_netent (query_description: "code7.example", getnetbyname (name: "code7.example"),
251 expected: "alias: 4.3.2.1.in-addr.arpa\n"
252 "net: 0x01020304\n");
253
254 /* Lookup by name, failure cases. */
255 check_netent (query_description: "code100.example", getnetbyname (name: "code100.example"),
256 expected: "error: NO_ADDRESS\n");
257 check_netent (query_description: "code101.example", getnetbyname (name: "code101.example"),
258 expected: "error: HOST_NOT_FOUND\n");
259 check_netent (query_description: "code102.example", getnetbyname (name: "code102.example"),
260 expected: "error: TRY_AGAIN\n");
261 check_netent (query_description: "code103.example", getnetbyname (name: "code103.example"),
262 expected: "error: NO_RECOVERY\n");
263 /* Test bug #17630. */
264 check_netent (query_description: "code104.example", getnetbyname (name: "code104.example"),
265 expected: "error: TRY_AGAIN\n");
266
267 /* Lookup by address, success cases. */
268 check_reverse (code: 1,
269 expected: "name: 1.in-addr.arpa\n"
270 "net: 0x00000001\n");
271 check_reverse (code: 2,
272 expected: "name: 2.1.in-addr.arpa\n"
273 "net: 0x00000002\n");
274 check_reverse (code: 3,
275 expected: "name: 3.2.1.in-addr.arpa\n"
276 "net: 0x00000003\n");
277 check_reverse (code: 4,
278 expected: "name: 4.3.2.1.in-addr.arpa\n"
279 "net: 0x00000004\n");
280 check_reverse (code: 5,
281 expected: "name: 127.in-addr.arpa\n"
282 "alias: 0.in-addr.arpa\n"
283 "net: 0x00000005\n");
284 check_reverse (code: 6,
285 expected: "name: 127.in-addr.arpa\n"
286 "alias: 0.in-addr.arpa\n"
287 "net: 0x00000006\n");
288 check_reverse (code: 7,
289 expected: "name: 4.3.2.1.in-addr.arpa\n"
290 "net: 0x00000007\n");
291
292 /* Lookup by address, failure cases. */
293 check_reverse (code: 100,
294 expected: "error: NO_ADDRESS\n");
295 check_reverse (code: 101,
296 expected: "error: HOST_NOT_FOUND\n");
297 check_reverse (code: 102,
298 expected: "error: TRY_AGAIN\n");
299 check_reverse (code: 103,
300 expected: "error: NO_RECOVERY\n");
301
302 check_long_name ();
303
304 resolv_test_end (obj);
305
306 return 0;
307}
308
309#include <support/test-driver.c>
310

source code of glibc/resolv/tst-resolv-network.c