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 
28 static void
send_ptr(struct resolv_response_builder * b,const char * qname,uint16_t qclass,uint16_t qtype,const char * alias)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
handle_code(const struct resolv_response_context * ctx,struct resolv_response_builder * b,const char * qname,uint16_t qclass,uint16_t qtype,int code)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;
152     case 104:
153       send_ptr (b, qname, qclass, qtype, "host.example");
154       break;
155     default:
156       FAIL_EXIT1 ("invalid QNAME: %s (code %d)", qname, code);
157     }
158 }
159 
160 static void
response(const struct resolv_response_context * ctx,struct resolv_response_builder * b,const char * qname,uint16_t qclass,uint16_t qtype)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
check_reverse(int code,const char * expected)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
check_long_name(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 
220 static int
do_test(void)221 do_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 ("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");
263   /* Test bug #17630.  */
264   check_netent ("code104.example", getnetbyname ("code104.example"),
265                 "error: TRY_AGAIN\n");
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);
305 
306   return 0;
307 }
308 
309 #include <support/test-driver.c>
310