• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* MIT License
2  *
3  * Copyright (c) The c-ares project and its contributors
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  *
24  * SPDX-License-Identifier: MIT
25  */
26 #include <stddef.h>
27 #include <stdio.h>
28 #include "ares.h"
29 #include "include/ares_buf.h"
30 #include "include/ares_mem.h"
31 
32 int LLVMFuzzerTestOneInput(const unsigned char *data, unsigned long size);
33 
34 #ifdef USE_LEGACY_FUZZERS
35 
36 /* This implementation calls the legacy c-ares parsers, which historically
37  * all used different logic and parsing.  As of c-ares 1.21.0 these are
38  * simply wrappers around a single parser, and simply convert the parsed
39  * DNS response into the data structures the legacy parsers used which is a
40  * small amount of code and not likely going to vary based on the input data.
41  *
42  * Instead, these days, it makes more sense to test the new parser directly
43  * instead of calling it 10 or 11 times with the same input data to speed up
44  * the number of iterations per second the fuzzer can perform.
45  *
46  * We are keeping this legacy fuzzer test for historic reasons or if someone
47  * finds them of use.
48  */
49 
LLVMFuzzerTestOneInput(const unsigned char * data,unsigned long size)50 int LLVMFuzzerTestOneInput(const unsigned char *data, unsigned long size)
51 {
52   /* Feed the data into each of the ares_parse_*_reply functions. */
53   struct hostent          *host = NULL;
54   struct ares_addrttl      info[5];
55   struct ares_addr6ttl     info6[5];
56   unsigned char            addrv4[4] = { 0x10, 0x20, 0x30, 0x40 };
57   struct ares_srv_reply   *srv       = NULL;
58   struct ares_mx_reply    *mx        = NULL;
59   struct ares_txt_reply   *txt       = NULL;
60   struct ares_soa_reply   *soa       = NULL;
61   struct ares_naptr_reply *naptr     = NULL;
62   struct ares_caa_reply   *caa       = NULL;
63   struct ares_uri_reply   *uri       = NULL;
64   int                      count     = 5;
65   ares_parse_a_reply(data, (int)size, &host, info, &count);
66   if (host) {
67     ares_free_hostent(host);
68   }
69 
70   host  = NULL;
71   count = 5;
72   ares_parse_aaaa_reply(data, (int)size, &host, info6, &count);
73   if (host) {
74     ares_free_hostent(host);
75   }
76 
77   host = NULL;
78   ares_parse_ptr_reply(data, (int)size, addrv4, sizeof(addrv4), AF_INET, &host);
79   if (host) {
80     ares_free_hostent(host);
81   }
82 
83   host = NULL;
84   ares_parse_ns_reply(data, (int)size, &host);
85   if (host) {
86     ares_free_hostent(host);
87   }
88 
89   ares_parse_srv_reply(data, (int)size, &srv);
90   if (srv) {
91     ares_free_data(srv);
92   }
93 
94   ares_parse_mx_reply(data, (int)size, &mx);
95   if (mx) {
96     ares_free_data(mx);
97   }
98 
99   ares_parse_txt_reply(data, (int)size, &txt);
100   if (txt) {
101     ares_free_data(txt);
102   }
103 
104   ares_parse_soa_reply(data, (int)size, &soa);
105   if (soa) {
106     ares_free_data(soa);
107   }
108 
109   ares_parse_naptr_reply(data, (int)size, &naptr);
110   if (naptr) {
111     ares_free_data(naptr);
112   }
113 
114   ares_parse_caa_reply(data, (int)size, &caa);
115   if (caa) {
116     ares_free_data(caa);
117   }
118 
119   ares_parse_uri_reply(data, (int)size, &uri);
120   if (uri) {
121     ares_free_data(uri);
122   }
123 
124   return 0;
125 }
126 
127 #else
128 
LLVMFuzzerTestOneInput(const unsigned char * data,unsigned long size)129 int LLVMFuzzerTestOneInput(const unsigned char *data, unsigned long size)
130 {
131   ares_dns_record_t *dnsrec    = NULL;
132   char              *printdata = NULL;
133   ares_buf_t        *printmsg  = NULL;
134   size_t             i;
135   unsigned char     *datadup     = NULL;
136   size_t             datadup_len = 0;
137 
138   /* There is never a reason to have a size > 65535, it is immediately
139    * rejected by the parser */
140   if (size > 65535) {
141     return -1;
142   }
143 
144   if (ares_dns_parse(data, size, 0, &dnsrec) != ARES_SUCCESS) {
145     goto done;
146   }
147 
148   /* Lets test the message fetchers */
149   printmsg = ares_buf_create();
150   if (printmsg == NULL) {
151     goto done;
152   }
153 
154   ares_buf_append_str(printmsg, ";; ->>HEADER<<- opcode: ");
155   ares_buf_append_str(
156     printmsg, ares_dns_opcode_tostr(ares_dns_record_get_opcode(dnsrec)));
157   ares_buf_append_str(printmsg, ", status: ");
158   ares_buf_append_str(printmsg,
159                       ares_dns_rcode_tostr(ares_dns_record_get_rcode(dnsrec)));
160   ares_buf_append_str(printmsg, ", id: ");
161   ares_buf_append_num_dec(printmsg, (size_t)ares_dns_record_get_id(dnsrec), 0);
162   ares_buf_append_str(printmsg, "\n;; flags: ");
163   ares_buf_append_num_hex(printmsg, (size_t)ares_dns_record_get_flags(dnsrec),
164                           0);
165   ares_buf_append_str(printmsg, "; QUERY: ");
166   ares_buf_append_num_dec(printmsg, ares_dns_record_query_cnt(dnsrec), 0);
167   ares_buf_append_str(printmsg, ", ANSWER: ");
168   ares_buf_append_num_dec(
169     printmsg, ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER), 0);
170   ares_buf_append_str(printmsg, ", AUTHORITY: ");
171   ares_buf_append_num_dec(
172     printmsg, ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_AUTHORITY), 0);
173   ares_buf_append_str(printmsg, ", ADDITIONAL: ");
174   ares_buf_append_num_dec(
175     printmsg, ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ADDITIONAL), 0);
176   ares_buf_append_str(printmsg, "\n\n");
177   ares_buf_append_str(printmsg, ";; QUESTION SECTION:\n");
178   for (i = 0; i < ares_dns_record_query_cnt(dnsrec); i++) {
179     const char         *name;
180     ares_dns_rec_type_t qtype;
181     ares_dns_class_t    qclass;
182 
183     if (ares_dns_record_query_get(dnsrec, i, &name, &qtype, &qclass) !=
184         ARES_SUCCESS) {
185       goto done;
186     }
187 
188     ares_buf_append_str(printmsg, ";");
189     ares_buf_append_str(printmsg, name);
190     ares_buf_append_str(printmsg, ".\t\t\t");
191     ares_buf_append_str(printmsg, ares_dns_class_tostr(qclass));
192     ares_buf_append_str(printmsg, "\t");
193     ares_buf_append_str(printmsg, ares_dns_rec_type_tostr(qtype));
194     ares_buf_append_str(printmsg, "\n");
195   }
196   ares_buf_append_str(printmsg, "\n");
197   for (i = ARES_SECTION_ANSWER; i < ARES_SECTION_ADDITIONAL + 1; i++) {
198     size_t j;
199 
200     ares_buf_append_str(printmsg, ";; ");
201     ares_buf_append_str(printmsg,
202                         ares_dns_section_tostr((ares_dns_section_t)i));
203     ares_buf_append_str(printmsg, " SECTION:\n");
204     for (j = 0; j < ares_dns_record_rr_cnt(dnsrec, (ares_dns_section_t)i);
205          j++) {
206       size_t                   keys_cnt = 0;
207       const ares_dns_rr_key_t *keys     = NULL;
208       ares_dns_rr_t           *rr       = NULL;
209       size_t                   k;
210 
211       rr = ares_dns_record_rr_get(dnsrec, (ares_dns_section_t)i, j);
212       ares_buf_append_str(printmsg, ares_dns_rr_get_name(rr));
213       ares_buf_append_str(printmsg, ".\t\t\t");
214       ares_buf_append_str(printmsg,
215                           ares_dns_class_tostr(ares_dns_rr_get_class(rr)));
216       ares_buf_append_str(printmsg, "\t");
217       ares_buf_append_str(printmsg,
218                           ares_dns_rec_type_tostr(ares_dns_rr_get_type(rr)));
219       ares_buf_append_str(printmsg, "\t");
220       ares_buf_append_num_dec(printmsg, ares_dns_rr_get_ttl(rr), 0);
221       ares_buf_append_str(printmsg, "\t");
222 
223       keys = ares_dns_rr_get_keys(ares_dns_rr_get_type(rr), &keys_cnt);
224       for (k = 0; k < keys_cnt; k++) {
225         char buf[256] = "";
226 
227         ares_buf_append_str(printmsg, ares_dns_rr_key_tostr(keys[k]));
228         ares_buf_append_str(printmsg, "=");
229         switch (ares_dns_rr_key_datatype(keys[k])) {
230           case ARES_DATATYPE_INADDR:
231             ares_inet_ntop(AF_INET, ares_dns_rr_get_addr(rr, keys[k]), buf,
232                            sizeof(buf));
233             ares_buf_append_str(printmsg, buf);
234             break;
235           case ARES_DATATYPE_INADDR6:
236             ares_inet_ntop(AF_INET6, ares_dns_rr_get_addr6(rr, keys[k]), buf,
237                            sizeof(buf));
238             ares_buf_append_str(printmsg, buf);
239             break;
240           case ARES_DATATYPE_U8:
241             ares_buf_append_num_dec(printmsg, ares_dns_rr_get_u8(rr, keys[k]),
242                                     0);
243             break;
244           case ARES_DATATYPE_U16:
245             ares_buf_append_num_dec(printmsg, ares_dns_rr_get_u16(rr, keys[k]),
246                                     0);
247             break;
248           case ARES_DATATYPE_U32:
249             ares_buf_append_num_dec(printmsg, ares_dns_rr_get_u32(rr, keys[k]),
250                                     0);
251             break;
252           case ARES_DATATYPE_NAME:
253           case ARES_DATATYPE_STR:
254             ares_buf_append_byte(printmsg, '"');
255             ares_buf_append_str(printmsg, ares_dns_rr_get_str(rr, keys[k]));
256             ares_buf_append_byte(printmsg, '"');
257             break;
258           case ARES_DATATYPE_BIN:
259             /* TODO */
260             break;
261           case ARES_DATATYPE_BINP:
262             {
263               size_t templen;
264               ares_buf_append_byte(printmsg, '"');
265               ares_buf_append_str(printmsg, (const char *)ares_dns_rr_get_bin(
266                                               rr, keys[k], &templen));
267               ares_buf_append_byte(printmsg, '"');
268             }
269             break;
270           case ARES_DATATYPE_ABINP:
271             {
272               size_t a;
273               for (a = 0; a < ares_dns_rr_get_abin_cnt(rr, keys[k]); a++) {
274                 size_t templen;
275 
276                 if (a != 0) {
277                   ares_buf_append_byte(printmsg, ' ');
278                 }
279                 ares_buf_append_byte(printmsg, '"');
280                 ares_buf_append_str(
281                   printmsg,
282                   (const char *)ares_dns_rr_get_abin(rr, keys[k], a, &templen));
283                 ares_buf_append_byte(printmsg, '"');
284               }
285             }
286             break;
287           case ARES_DATATYPE_OPT:
288             /* TODO */
289             break;
290         }
291         ares_buf_append_str(printmsg, " ");
292       }
293       ares_buf_append_str(printmsg, "\n");
294     }
295   }
296   ares_buf_append_str(printmsg, ";; SIZE: ");
297   ares_buf_append_num_dec(printmsg, size, 0);
298   ares_buf_append_str(printmsg, "\n\n");
299 
300   printdata = ares_buf_finish_str(printmsg, NULL);
301   printmsg  = NULL;
302 
303   /* Write it back out as a dns message to test writer */
304   if (ares_dns_write(dnsrec, &datadup, &datadup_len) != ARES_SUCCESS) {
305     goto done;
306   }
307 
308 done:
309   ares_dns_record_destroy(dnsrec);
310   ares_buf_destroy(printmsg);
311   ares_free(printdata);
312   ares_free(datadup);
313   return 0;
314 }
315 
316 #endif
317