1 /*------------------------------------------------------------------------------
2  *
3  * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4  * The YADIFA TM software product is provided under the BSD 3-clause license:
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *        * Redistributions in binary form must reproduce the above copyright
13  *          notice, this list of conditions and the following disclaimer in the
14  *          documentation and/or other materials provided with the distribution.
15  *        * Neither the name of EURid nor the names of its contributors may be
16  *          used to endorse or promote products derived from this software
17  *          without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  *------------------------------------------------------------------------------
32  *
33  */
34 
35 #include <dnscore/format.h>
36 #include "dns-stream-input.h"
37 
38 #define DNSISDT_TAG 0x54445359534e44
39 
40 struct dns_stream_input_data_s
41 {
42     u8 *domain;
43 };
44 
45 static ya_result
axfr_record_input_data_feed(struct input_stream_input_data_s * input_data)46 axfr_record_input_data_feed(struct input_stream_input_data_s *input_data)
47 {
48     ya_result ret = SUCCESS;
49 
50     for(;;)
51     {
52         switch(input_data->indexes[0])
53         {
54             case 0:
55             {
56                 static const u16 apex[] = {TYPE_SOA, TYPE_NS, TYPE_NS, TYPE_MX};
57                 static const size_t apex_size = sizeof(apex) / sizeof(u16);
58                 record_input_data_feed_serial_set(1);
59 
60                 if(input_data->indexes[1] < (s64)apex_size)
61                 {
62                     ret = record_input_data_feed(input_data, apex, apex_size, input_domain_get(input_data->input), &input_data->indexes[1]);
63                     return ret;
64                 }
65 
66                 ++input_data->indexes[0];
67                 input_data->indexes[1]= 0;
68                 break;
69             }
70             case 1:
71             case 2:
72             case 3:
73             case 4:
74             case 5:
75             case 6:
76             {
77                 static const u16 delegation[] = {TYPE_NS, TYPE_NS};
78                 static const size_t delegation_size = sizeof(delegation) / sizeof(u16);
79 
80                 if(input_data->indexes[1] < (s64)delegation_size)
81                 {
82 
83                     char fqdn[256];
84                     u8 wire[256];
85 
86                     snformat(fqdn, sizeof(fqdn), "subdomain-%i.%{dnsname}", input_data->indexes[0], input_domain_get(input_data->input));
87                     cstr_to_dnsname(wire, fqdn);
88 
89                     ret = record_input_data_feed(input_data, delegation, delegation_size, wire, &input_data->indexes[1]);
90                     return ret;
91                 }
92 
93                 ++input_data->indexes[0];
94                 input_data->indexes[1]= 0;
95                 break;
96             }
97             case 7:
98             {
99                 static const u16 end_soa[] = {TYPE_SOA};
100                 static const size_t end_soa_size = sizeof(end_soa) / sizeof(u16);
101 
102                 if(input_data->indexes[1] < (s64)end_soa_size)
103                 {
104                     ret = record_input_data_feed(input_data, end_soa, end_soa_size, input_domain_get(input_data->input), &input_data->indexes[1]);
105                     return ret;
106                 }
107 
108                 ++input_data->indexes[0];
109                 input_data->indexes[1]= 0;
110                 break;
111             }
112             default:
113             {
114                 ret = 0;
115                 return ret;
116             }
117         }
118     }
119 }
120 
121 static ya_result
cve_2021_25214_ixfr_record_input_data_feed(struct input_stream_input_data_s * input_data)122 cve_2021_25214_ixfr_record_input_data_feed(struct input_stream_input_data_s *input_data)
123 {
124     ya_result ret = SUCCESS;
125 
126     for(;;)
127     {
128         switch(input_data->indexes[0])
129         {
130             case 0:
131             {
132                 static const u16 last_soa[] = {TYPE_SOA};
133                 static const size_t apex_size = sizeof(last_soa) / sizeof(u16);
134                 record_input_data_feed_serial_set(2);
135 
136                 ret = record_input_data_feed(input_data, last_soa, apex_size, input_domain_get(input_data->input), &input_data->indexes[1]);
137 
138                 ++input_data->indexes[0];
139                 input_data->indexes[1]= 0;
140 
141                 ++input_data->indexes[0];
142 
143                 return ret;
144             }
145             case 1:
146             {
147                 static const u16 remove_soa[] = {TYPE_SOA};
148                 static const size_t apex_size = sizeof(remove_soa) / sizeof(u16);
149                 record_input_data_feed_serial_set(1);
150 
151                 ret = record_input_data_feed(input_data, remove_soa, apex_size, input_domain_get(input_data->input), &input_data->indexes[1]);
152                 //ret = record_input_data_feed(input_data, remove_soa, apex_size, "\005other", &input_data->indexes[1]);
153 
154                 ++input_data->indexes[0];
155                 input_data->indexes[1]= 0;
156                 return ret;
157             }
158             case 2:
159             {
160                 static const u16 remove_soa[] = {TYPE_SOA};
161                 static const size_t apex_size = sizeof(remove_soa) / sizeof(u16);
162                 record_input_data_feed_serial_set(1);
163 
164                 ret = record_input_data_feed(input_data, remove_soa, apex_size, (const u8*)"\005other", &input_data->indexes[1]);
165 
166                 ++input_data->indexes[0];
167                 input_data->indexes[1]= 0;
168                 return ret;
169             }
170             case 3:
171             {
172                 static const u16 remove_records_soa[] = {TYPE_NS, TYPE_MX};
173                 static const size_t apex_size = sizeof(remove_records_soa) / sizeof(u16);
174 
175                 ret = record_input_data_feed(input_data, remove_records_soa, apex_size, input_domain_get(input_data->input), &input_data->indexes[1]);
176 
177                 if(input_data->indexes[1] >= (s64)apex_size)
178                 {
179                     ++input_data->indexes[0];
180                     input_data->indexes[1]= 0;
181                 }
182                 return ret;
183             }
184             case 4:
185             {
186                 static const u16 add_soa[] = {TYPE_SOA};
187                 static const size_t apex_size = sizeof(add_soa) / sizeof(u16);
188                 record_input_data_feed_serial_set(2);
189 
190                 ret = record_input_data_feed(input_data, add_soa, apex_size, input_domain_get(input_data->input), &input_data->indexes[1]);
191 
192                 ++input_data->indexes[0];
193                 input_data->indexes[1]= 0;
194                 return ret;
195             }
196             case 5:
197             {
198                 static const u16 add_records_soa[] = {TYPE_NS, TYPE_NS, TYPE_NS, TYPE_MX};
199                 static const size_t apex_size = sizeof(add_records_soa) / sizeof(u16);
200 
201                 ret = record_input_data_feed(input_data, add_records_soa, apex_size, input_domain_get(input_data->input), &input_data->indexes[1]);
202 
203                 if(input_data->indexes[1] >= (s64)apex_size)
204                 {
205                     ++input_data->indexes[0];
206                     input_data->indexes[1]= 0;
207                 }
208                 return ret;
209             }
210             case 6:
211             {
212                 static const u16 last_soa[] = {TYPE_SOA};
213                 static const size_t apex_size = sizeof(last_soa) / sizeof(u16);
214                 record_input_data_feed_serial_set(2);
215 
216                 ret = record_input_data_feed(input_data, last_soa, apex_size, input_domain_get(input_data->input), &input_data->indexes[1]);
217 
218                 ++input_data->indexes[0];
219                 input_data->indexes[1]= 0;
220                 return ret;
221             }
222             default:
223             {
224                 ret = 0;
225                 return ret;
226             }
227         }
228     }
229 }
230 
231 static ya_result
ixfr_record_input_data_feed(struct input_stream_input_data_s * input_data)232 ixfr_record_input_data_feed(struct input_stream_input_data_s *input_data)
233 {
234     ya_result ret = SUCCESS;
235 
236     for(;;)
237     {
238         switch(input_data->indexes[0])
239         {
240             case 0:
241             {
242                 static const u16 last_soa[] = {TYPE_SOA};
243                 static const size_t apex_size = sizeof(last_soa) / sizeof(u16);
244                 record_input_data_feed_serial_set(2);
245 
246                 ret = record_input_data_feed(input_data, last_soa, apex_size, input_domain_get(input_data->input), &input_data->indexes[1]);
247 
248                 ++input_data->indexes[0];
249                 input_data->indexes[1]= 0;
250                 return ret;
251             }
252             case 1:
253             {
254                 static const u16 remove_soa[] = {TYPE_SOA};
255                 static const size_t apex_size = sizeof(remove_soa) / sizeof(u16);
256                 record_input_data_feed_serial_set(1);
257 
258                 ret = record_input_data_feed(input_data, remove_soa, apex_size, input_domain_get(input_data->input), &input_data->indexes[1]);
259 
260                 ++input_data->indexes[0];
261                 input_data->indexes[1]= 0;
262                 return ret;
263             }
264             case 2:
265             {
266                 static const u16 remove_records_soa[] = {TYPE_NS, TYPE_MX};
267                 static const size_t apex_size = sizeof(remove_records_soa) / sizeof(u16);
268 
269                 ret = record_input_data_feed(input_data, remove_records_soa, apex_size, input_domain_get(input_data->input), &input_data->indexes[1]);
270 
271                 if(input_data->indexes[1] >= (s64)apex_size)
272                 {
273                     ++input_data->indexes[0];
274                     input_data->indexes[1]= 0;
275                 }
276                 return ret;
277             }
278             case 3:
279             {
280                 static const u16 add_soa[] = {TYPE_SOA};
281                 static const size_t apex_size = sizeof(add_soa) / sizeof(u16);
282                 record_input_data_feed_serial_set(2);
283 
284                 ret = record_input_data_feed(input_data, add_soa, apex_size, input_domain_get(input_data->input), &input_data->indexes[1]);
285 
286                 ++input_data->indexes[0];
287                 input_data->indexes[1]= 0;
288                 return ret;
289             }
290             case 4:
291             {
292                 static const u16 add_records_soa[] = {TYPE_NS, TYPE_NS, TYPE_NS, TYPE_MX};
293                 static const size_t apex_size = sizeof(add_records_soa) / sizeof(u16);
294 
295                 ret = record_input_data_feed(input_data, add_records_soa, apex_size, input_domain_get(input_data->input), &input_data->indexes[1]);
296 
297                 if(input_data->indexes[1] >= (s64)apex_size)
298                 {
299                     ++input_data->indexes[0];
300                     input_data->indexes[1]= 0;
301                 }
302                 return ret;
303             }
304             case 5:
305             {
306                 static const u16 last_soa[] = {TYPE_SOA};
307                 static const size_t apex_size = sizeof(last_soa) / sizeof(u16);
308                 record_input_data_feed_serial_set(2);
309 
310                 ret = record_input_data_feed(input_data, last_soa, apex_size, input_domain_get(input_data->input), &input_data->indexes[1]);
311 
312                 ++input_data->indexes[0];
313                 input_data->indexes[1]= 0;
314                 return ret;
315             }
316             default:
317             {
318                 ret = 0;
319                 return ret;
320             }
321         }
322     }
323 }
324 
dns_stream_input_domain_get(struct input_s * input)325 static const u8 *dns_stream_input_domain_get(struct input_s *input)
326 {
327     struct dns_stream_input_data_s *data = (struct dns_stream_input_data_s*)input->data;
328     return data->domain;
329 }
330 
dns_stream_input_axfr_input_stream_init(struct input_s * input,input_stream * is)331 static ya_result dns_stream_input_axfr_input_stream_init(struct input_s *input, input_stream *is)
332 {
333     ya_result ret = input_stream_input_init(is, input, axfr_record_input_data_feed);
334     return ret;
335 }
336 
dns_stream_input_ixfr_input_stream_init(struct input_s * input,u32 serial_value,input_stream * is)337 static ya_result dns_stream_input_ixfr_input_stream_init(struct input_s *input, u32 serial_value, input_stream *is)
338 {
339     (void)serial_value;
340     ya_result ret = input_stream_input_init(is, input, ixfr_record_input_data_feed);
341     return ret;
342 }
343 
dns_stream_input_cve_2021_25214_ixfr_input_stream_init(struct input_s * input,u32 serial_value,input_stream * is)344 static ya_result dns_stream_input_cve_2021_25214_ixfr_input_stream_init(struct input_s *input, u32 serial_value, input_stream *is)
345 {
346     (void)serial_value;
347     ya_result ret = input_stream_input_init(is, input, cve_2021_25214_ixfr_record_input_data_feed);
348     return ret;
349 }
350 
dns_stream_input_finalise(struct input_s * input)351 static ya_result dns_stream_input_finalise(struct input_s *input)
352 {
353     struct dns_stream_input_data_s *data = (struct dns_stream_input_data_s*)input->data;
354     dnsname_free(data->domain);
355     free(data);
356     input->data = NULL;
357     return SUCCESS;
358 }
359 
360 static input_vtbl_t dns_stream_input_vtbl =
361 {
362     dns_stream_input_domain_get,
363     dns_stream_input_axfr_input_stream_init,
364     dns_stream_input_ixfr_input_stream_init,
365     dns_stream_input_finalise
366 };
367 
368 ya_result
dns_stream_input_init(struct input_s * input,const u8 * fqdn)369 dns_stream_input_init(struct input_s *input, const u8 *fqdn)
370 {
371     struct dns_stream_input_data_s *data;
372     MALLOC_OBJECT_OR_DIE(data, struct dns_stream_input_data_s, DNSISDT_TAG);
373     data->domain = dnsname_dup(fqdn);
374     input->data = data;
375     input->vtbl = &dns_stream_input_vtbl;
376     return SUCCESS;
377 }
378 
379 static input_vtbl_t dns_stream_cve_2021_25214_input_vtbl =
380 {
381     dns_stream_input_domain_get,
382     dns_stream_input_axfr_input_stream_init,
383     dns_stream_input_cve_2021_25214_ixfr_input_stream_init,
384     dns_stream_input_finalise
385 };
386 
387 ya_result
dns_stream_cve_2021_25214_input_init(struct input_s * input,const u8 * fqdn)388 dns_stream_cve_2021_25214_input_init(struct input_s *input, const u8 *fqdn)
389 {
390     struct dns_stream_input_data_s *data;
391     MALLOC_OBJECT_OR_DIE(data, struct dns_stream_input_data_s, DNSISDT_TAG);
392     data->domain = dnsname_dup(fqdn);
393     input->data = data;
394     input->vtbl = &dns_stream_cve_2021_25214_input_vtbl;
395     return SUCCESS;
396 }
397