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