]> git.saurik.com Git - apple/mdnsresponder.git/blob - ServiceRegistration/fromwire.c
mDNSResponder-1310.40.42.tar.gz
[apple/mdnsresponder.git] / ServiceRegistration / fromwire.c
1 /* fromwire.c
2 *
3 * Copyright (c) 2018, 2019 Apple Computer, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * DNS wire-format functions.
18 *
19 * These are really simple functions for constructing DNS messages wire format.
20 * The flow is that there is a transaction structure which contains pointers to both
21 * a message output buffer and a response input buffer. The structure is initialized,
22 * and then the various wire format functions are called repeatedly to store data.
23 * If an error occurs during this process, it's okay to just keep going, because the
24 * error is recorded in the transaction; once all of the copy-in functions have been
25 * called, the error status can be checked once at the end.
26 */
27
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <sys/socket.h>
33 #include <arpa/inet.h>
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include "srp.h"
37 #include "dns-msg.h"
38
39 bool
40 dns_opt_parse(dns_edns0_t *NONNULL *NULLABLE ret, dns_rr_t *rr)
41 {
42 dns_edns0_t *edns0, **p_edns0 = ret;
43 unsigned offset = 0;
44 dns_rdata_unparsed_t opt;
45
46 // This would be a weird coding error.
47 if (rr->type != dns_rrtype_opt) {
48 return false;
49 }
50 opt = rr->data.unparsed;
51
52 // RDATA is a series of TLVs
53 while (offset < opt.len) {
54 uint16_t tlv_type, tlv_len;
55
56 // Parse the TLV type and length.
57 if (!dns_u16_parse(opt.data, opt.len, &offset, &tlv_type) ||
58 !dns_u16_parse(opt.data, opt.len, &offset, &tlv_len))
59 {
60 return false;
61 }
62
63 // Range check the contents.
64 if (offset + tlv_len > opt.len) {
65 return false;
66 }
67
68 edns0 = calloc(1, tlv_len + sizeof(*edns0));
69 if (edns0 == NULL) {
70 return false;
71 }
72 // Stash the record.
73 edns0->length = tlv_len;
74 edns0->type = tlv_type;
75 memcpy(edns0->data, &opt.data[offset], tlv_len);
76 *p_edns0 = edns0;
77 p_edns0 = &edns0->next;
78 offset += tlv_len;
79 }
80 return true;
81 }
82
83 dns_label_t * NULLABLE
84 dns_label_parse(const uint8_t *buf, unsigned mlen, unsigned *NONNULL offp)
85 {
86 uint8_t llen = buf[*offp];
87 dns_label_t *rv;
88
89 // Make sure that we got the data this label claims to encompass.
90 if (*offp + llen + 1 > mlen) {
91 DEBUG("claimed length of label is too long: %u > %u.\n", *offp + llen + 1, mlen);
92 return NULL;
93 }
94
95 rv = calloc(1, (sizeof(*rv) - DNS_MAX_LABEL_SIZE) + llen + 1);
96 if (rv == NULL) {
97 DEBUG("memory allocation for %u byte label (%.*s) failed.\n",
98 *offp + llen + 1, *offp + llen + 1, &buf[*offp + 1]);
99 return NULL;
100 }
101
102 rv->len = llen;
103 memcpy(rv->data, &buf[*offp + 1], llen);
104 rv->data[llen] = 0; // We NUL-terminate the label for convenience
105 *offp += llen + 1;
106 return rv;
107 }
108
109 static bool
110 dns_name_parse_in(dns_label_t *NONNULL *NULLABLE ret, const uint8_t *buf, unsigned len,
111 unsigned *NONNULL offp, unsigned base)
112 {
113 dns_label_t *rv;
114
115 if (*offp == len) {
116 return false;
117 }
118
119 // A pointer?
120 if ((buf[*offp] & 0xC0) == 0xC0) {
121 unsigned pointer;
122 if (*offp + 2 > len) {
123 DEBUG("incomplete compression pointer: %u > %u", *offp + 2, len);
124 return false;
125 }
126 pointer = (((unsigned)buf[*offp] & 0x3f) << 8) | (unsigned)buf[*offp + 1];
127 *offp += 2;
128 if (pointer < DNS_HEADER_SIZE) {
129 // Don't allow pointers into the header.
130 DEBUG("compression pointer points into header: %u.\n", pointer);
131 return false;
132 }
133 pointer -= DNS_HEADER_SIZE;
134 if (pointer >= base) {
135 // Don't allow a pointer forward, or to a pointer we've already visited.
136 DEBUG("compression pointer points forward: %u >= %u.\n", pointer, base);
137 return false;
138 }
139 if (buf[pointer] & 0xC0) {
140 // If this is a pointer to a pointer, it's not valid.
141 DEBUG("compression pointer points into pointer: %u %02x%02x.\n", pointer,
142 buf[pointer], pointer + 1 < len ? buf[pointer + 1] : 0xFF);
143 return false;
144 }
145 if (buf[pointer] + pointer >= base || buf[pointer] + pointer >= *offp) {
146 // Possibly this isn't worth checking.
147 DEBUG("compression pointer points to something that goes past current position: %u %u\n",
148 pointer, buf[pointer]);
149 return false;
150 }
151 return dns_name_parse_in(ret, buf, len, &pointer, pointer);
152 }
153 // We don't support binary labels, which are historical, and at this time there are no other valid
154 // DNS label types.
155 if (buf[*offp] & 0xC0) {
156 DEBUG("invalid label type: %x\n", buf[*offp]);
157 return false;
158 }
159
160 rv = dns_label_parse(buf, len, offp);
161 if (rv == NULL) {
162 return false;
163 }
164
165 *ret = rv;
166
167 if (rv->len == 0) {
168 return true;
169 }
170 return dns_name_parse_in(&rv->next, buf, len, offp, base);
171 }
172
173 bool
174 dns_name_parse(dns_label_t *NONNULL *NULLABLE ret, const uint8_t *buf,
175 unsigned len, unsigned *NONNULL offp, unsigned base)
176 {
177 dns_label_t *rv = NULL, *next;
178
179 if (!dns_name_parse_in(&rv, buf, len, offp, base)) {
180 for (; rv != NULL; rv = next) {
181 next = rv->next;
182 free(rv);
183 }
184 return false;
185 }
186 *ret = rv;
187 return true;
188 }
189
190 bool
191 dns_u8_parse(const uint8_t *buf, unsigned len, unsigned *NONNULL offp, uint8_t *NONNULL ret)
192 {
193 uint8_t rv;
194 if (*offp + 1 > len) {
195 DEBUG("dns_u8_parse: not enough room: %u > %u.\n", *offp + 1, len);
196 return false;
197 }
198
199 rv = buf[*offp];
200 *offp += 1;
201 *ret = rv;
202 return true;
203 }
204
205 bool
206 dns_u16_parse(const uint8_t *buf, unsigned len, unsigned *NONNULL offp, uint16_t *NONNULL ret)
207 {
208 uint16_t rv;
209 if (*offp + 2 > len) {
210 DEBUG("dns_u16_parse: not enough room: %u > %u.\n", *offp + 2, len);
211 return false;
212 }
213
214 rv = ((uint16_t)(buf[*offp]) << 8) | (uint16_t)(buf[*offp + 1]);
215 *offp += 2;
216 *ret = rv;
217 return true;
218 }
219
220 bool
221 dns_u32_parse(const uint8_t *buf, unsigned len, unsigned *NONNULL offp, uint32_t *NONNULL ret)
222 {
223 uint32_t rv;
224 if (*offp + 4 > len) {
225 DEBUG("dns_u32_parse: not enough room: %u > %u.\n", *offp + 4, len);
226 return false;
227 }
228
229 rv = (((uint32_t)(buf[*offp]) << 24) | ((uint32_t)(buf[*offp + 1]) << 16) |
230 ((uint32_t)(buf[*offp + 2]) << 8) | (uint32_t)(buf[*offp + 3]));
231 *offp += 4;
232 *ret = rv;
233 return true;
234 }
235
236 static void
237 dns_rrdata_dump(dns_rr_t *rr)
238 {
239 int i;
240 char nbuf[INET6_ADDRSTRLEN];
241 char buf[DNS_MAX_NAME_SIZE_ESCAPED + 1];
242 char outbuf[2048];
243 char *obp;
244 ssize_t output_len, avail = 2048;
245
246 #define ADVANCE(result, start, remaining) \
247 output_len = strlen(start); \
248 result = start + output_len; \
249 avail = (remaining) - output_len
250 #define DEPCHAR(ch) \
251 do { \
252 if (avail > 1) { \
253 *obp++ = (ch); \
254 *obp = 0; \
255 --avail; \
256 } \
257 } while (0)
258
259
260 switch(rr->type) {
261 case dns_rrtype_key:
262 snprintf(outbuf, sizeof(outbuf),
263 "KEY <AC %d> <Z %d> <XT %d> <ZZ %d> <NAMTYPE %d> <ZZZZ %d> <ORY %d> %d %d ",
264 ((rr->data.key.flags & 0xC000) >> 14 & 3), ((rr->data.key.flags & 0x2000) >> 13) & 1,
265 ((rr->data.key.flags & 0x1000) >> 12) & 1, ((rr->data.key.flags & 0xC00) >> 10) & 3,
266 ((rr->data.key.flags & 0x300) >> 8) & 3, ((rr->data.key.flags & 0xF0) >> 4) & 15,
267 rr->data.key.flags & 15, rr->data.key.protocol, rr->data.key.algorithm);
268 ADVANCE(obp, outbuf, sizeof outbuf);
269
270 for (i = 0; i < rr->data.key.len; i++) {
271 if (i == 0) {
272 snprintf(obp, avail, "%d [%02x", rr->data.key.len, rr->data.key.key[i]);
273 ADVANCE(obp, obp, avail);
274 } else {
275 snprintf(obp, avail, " %02x", rr->data.key.key[i]);
276 ADVANCE(obp, obp, avail);
277 }
278 }
279 DEPCHAR(']');
280 break;
281
282 case dns_rrtype_sig:
283 dns_name_print(rr->data.sig.signer, buf, sizeof(buf));
284 snprintf(outbuf, sizeof(outbuf), "SIG %d %d %d %lu %lu %lu %d %s",
285 rr->data.sig.type, rr->data.sig.algorithm, rr->data.sig.label,
286 (unsigned long)rr->data.sig.rrttl, (unsigned long)rr->data.sig.expiry,
287 (unsigned long)rr->data.sig.inception, rr->data.sig.key_tag, buf);
288 ADVANCE(obp, outbuf, sizeof outbuf);
289 for (i = 0; i < rr->data.sig.len; i++) {
290 if (i == 0) {
291 snprintf(obp, avail, "%d [%02x", rr->data.sig.len, rr->data.sig.signature[i]);
292 ADVANCE(obp, obp, avail);
293 } else {
294 snprintf(obp, avail, " %02x", rr->data.sig.signature[i]);
295 ADVANCE(obp, obp, avail);
296 }
297 }
298 DEPCHAR(']');
299 break;
300
301 case dns_rrtype_srv:
302 dns_name_print(rr->data.srv.name, buf, sizeof(buf));
303 snprintf(outbuf, sizeof(outbuf), "SRV %d %d %d %s", rr->data.srv.priority, rr->data.srv.weight,
304 rr->data.srv.port, buf);
305 ADVANCE(obp, outbuf, sizeof(outbuf));
306 break;
307
308 case dns_rrtype_ptr:
309 dns_name_print(rr->data.ptr.name, buf, sizeof(buf));
310 snprintf(outbuf, sizeof(outbuf), "PTR %s", buf);
311 ADVANCE(obp, outbuf, sizeof(outbuf));
312 break;
313
314 case dns_rrtype_cname:
315 dns_name_print(rr->data.cname.name, buf, sizeof(buf));
316 snprintf(outbuf, sizeof(outbuf), "CNAME %s", buf);
317 ADVANCE(obp, outbuf, sizeof(outbuf));
318 break;
319
320 case dns_rrtype_a:
321 inet_ntop(AF_INET, &rr->data.a, nbuf, sizeof(nbuf));
322 snprintf(outbuf, sizeof(outbuf), "A %s", nbuf);
323 ADVANCE(obp, outbuf, sizeof(outbuf));
324 break;
325
326 case dns_rrtype_aaaa:
327 inet_ntop(AF_INET6, &rr->data.aaaa, nbuf, sizeof(nbuf));
328 snprintf(outbuf, sizeof(outbuf), "AAAA %s", nbuf);
329 ADVANCE(obp, outbuf, sizeof(outbuf));
330 break;
331
332 case dns_rrtype_txt:
333 strcpy(outbuf, "TXT ");
334 ADVANCE(obp, outbuf, sizeof(outbuf));
335 for (i = 0; i < rr->data.txt.len; i++) {
336 if (isascii(rr->data.txt.data[i]) && isprint(rr->data.txt.data[i])) {
337 DEPCHAR(rr->data.txt.data[i]);
338 } else {
339 snprintf(obp, avail, "<%x>", rr->data.txt.data[i]);
340 ADVANCE(obp, obp, avail);
341 }
342 }
343 DEPCHAR('"');
344 break;
345
346 default:
347 snprintf(outbuf, sizeof(outbuf), "<rrtype %d>:", rr->type);
348 ADVANCE(obp, outbuf, sizeof(outbuf));
349 if (rr->data.unparsed.len == 0) {
350 snprintf(obp, avail, " <none>");
351 ADVANCE(obp, obp, avail);
352 } else {
353 for (i = 0; i < rr->data.unparsed.len; i++) {
354 snprintf(obp, avail, " %02x", rr->data.unparsed.data[i]);
355 ADVANCE(obp, obp, avail);
356 }
357 }
358 break;
359 }
360 DEBUG(PUB_S_SRP, outbuf);
361 }
362
363 bool
364 dns_rdata_parse_data(dns_rr_t *NONNULL rr, const uint8_t *buf, unsigned *NONNULL offp, unsigned target, unsigned rdlen,
365 unsigned rrstart)
366 {
367 switch(rr->type) {
368 case dns_rrtype_key:
369 if (!dns_u16_parse(buf, target, offp, &rr->data.key.flags) ||
370 !dns_u8_parse(buf, target, offp, &rr->data.key.protocol) ||
371 !dns_u8_parse(buf, target, offp, &rr->data.key.algorithm)) {
372 return false;
373 }
374 rr->data.key.len = target - *offp;
375 rr->data.key.key = malloc(rr->data.key.len);
376 if (!rr->data.key.key) {
377 return false;
378 }
379 memcpy(rr->data.key.key, &buf[*offp], rr->data.key.len);
380 *offp += rr->data.key.len;
381 break;
382
383 case dns_rrtype_sig:
384 rr->data.sig.start = rrstart;
385 if (!dns_u16_parse(buf, target, offp, &rr->data.sig.type) ||
386 !dns_u8_parse(buf, target, offp, &rr->data.sig.algorithm) ||
387 !dns_u8_parse(buf, target, offp, &rr->data.sig.label) ||
388 !dns_u32_parse(buf, target, offp, &rr->data.sig.rrttl) ||
389 !dns_u32_parse(buf, target, offp, &rr->data.sig.expiry) ||
390 !dns_u32_parse(buf, target, offp, &rr->data.sig.inception) ||
391 !dns_u16_parse(buf, target, offp, &rr->data.sig.key_tag) ||
392 !dns_name_parse(&rr->data.sig.signer, buf, target, offp, *offp)) {
393 return false;
394 }
395 // The signature is what's left of the RRDATA. It covers the message up to the signature, so we
396 // remember where it starts so as to know what memory to cover to validate it.
397 rr->data.sig.len = target - *offp;
398 rr->data.sig.signature = malloc(rr->data.sig.len);
399 if (!rr->data.sig.signature) {
400 return false;
401 }
402 memcpy(rr->data.sig.signature, &buf[*offp], rr->data.sig.len);
403 *offp += rr->data.sig.len;
404 break;
405
406 case dns_rrtype_srv:
407 if (!dns_u16_parse(buf, target, offp, &rr->data.srv.priority) ||
408 !dns_u16_parse(buf, target, offp, &rr->data.srv.weight) ||
409 !dns_u16_parse(buf, target, offp, &rr->data.srv.port)) {
410 return false;
411 }
412 // This fallthrough assumes that the first element in the srv, ptr and cname structs is
413 // a pointer to a domain name.
414
415 case dns_rrtype_ns:
416 case dns_rrtype_ptr:
417 case dns_rrtype_cname:
418 if (!dns_name_parse(&rr->data.ptr.name, buf, target, offp, *offp)) {
419 return false;
420 }
421 break;
422
423 case dns_rrtype_a:
424 if (rdlen != 4) {
425 DEBUG("dns_rdata_parse: A rdlen is not 4: %u", rdlen);
426 return false;
427 }
428 memcpy(&rr->data.a, &buf[*offp], rdlen);
429 *offp = target;
430 break;
431
432 case dns_rrtype_aaaa:
433 if (rdlen != 16) {
434 DEBUG("dns_rdata_parse: AAAA rdlen is not 16: %u", rdlen);
435 return false;
436 }
437 memcpy(&rr->data.aaaa, &buf[*offp], rdlen);
438 *offp = target;
439 break;
440
441 case dns_rrtype_txt:
442 rr->data.txt.len = target - *offp;
443 rr->data.txt.data = malloc(rr->data.txt.len);
444 if (rr->data.txt.data == NULL) {
445 DEBUG("dns_rdata_parse: no memory for TXT RR");
446 return false;
447 }
448 memcpy(rr->data.txt.data, &buf[*offp], rr->data.txt.len);
449 *offp = target;
450 break;
451
452 default:
453 if (rdlen > 0) {
454 rr->data.unparsed.data = malloc(rdlen);
455 if (rr->data.unparsed.data == NULL) {
456 return false;
457 }
458 memcpy(rr->data.unparsed.data, &buf[*offp], rdlen);
459 }
460 rr->data.unparsed.len = rdlen;
461 *offp = target;
462 break;
463 }
464 if (*offp != target) {
465 DEBUG("dns_rdata_parse: parse for rrtype %d not fully contained: %u %u", rr->type, target, *offp);
466 return false;
467 }
468 return true;
469 }
470
471 static bool
472 dns_rdata_parse(dns_rr_t *NONNULL rr,
473 const uint8_t *buf, unsigned len, unsigned *NONNULL offp, unsigned rrstart)
474 {
475 uint16_t rdlen;
476 unsigned target;
477
478 if (!dns_u16_parse(buf, len, offp, &rdlen)) {
479 return false;
480 }
481 target = *offp + rdlen;
482 if (target > len) {
483 return false;
484 }
485 return dns_rdata_parse_data(rr, buf, offp, target, rdlen, rrstart);
486 }
487
488 bool
489 dns_rr_parse(dns_rr_t *NONNULL rr,
490 const uint8_t *buf, unsigned len, unsigned *NONNULL offp, bool rrdata_expected)
491 {
492 int rrstart = *offp; // Needed to mark the start of the SIG RR for SIG(0).
493
494 memset(rr, 0, sizeof(*rr));
495 if (!dns_name_parse(&rr->name, buf, len, offp, *offp)) {
496 return false;
497 }
498
499 if (!dns_u16_parse(buf, len, offp, &rr->type)) {
500 return false;
501 }
502
503 if (!dns_u16_parse(buf, len, offp, &rr->qclass)) {
504 return false;
505 }
506
507 if (rrdata_expected) {
508 if (!dns_u32_parse(buf, len, offp, &rr->ttl)) {
509 return false;
510 }
511 if (!dns_rdata_parse(rr, buf, len, offp, rrstart)) {
512 return false;
513 }
514 }
515
516 DNS_NAME_GEN_SRP(rr->name, name_buf);
517 DEBUG("rrtype: %u qclass: %u name: " PRI_DNS_NAME_SRP PUB_S_SRP,
518 rr->type, rr->qclass, DNS_NAME_PARAM_SRP(rr->name, name_buf), rrdata_expected ? " rrdata:" : "");
519 if (rrdata_expected) {
520 dns_rrdata_dump(rr);
521 }
522 return true;
523 }
524
525 void
526 dns_rrdata_free(dns_rr_t *rr)
527 {
528 switch(rr->type) {
529 case dns_rrtype_a:
530 case dns_rrtype_aaaa:
531 break;
532
533 case dns_rrtype_key:
534 free(rr->data.key.key);
535 break;
536
537 case dns_rrtype_sig:
538 dns_name_free(rr->data.sig.signer);
539 free(rr->data.sig.signature);
540 break;
541
542 case dns_rrtype_srv:
543 case dns_rrtype_ptr:
544 case dns_rrtype_cname:
545 dns_name_free(rr->data.ptr.name);
546 #ifndef __clang_analyzer__
547 rr->data.ptr.name = NULL;
548 #endif
549 break;
550
551 case dns_rrtype_txt:
552 free(rr->data.txt.data);
553 #ifndef __clang_analyzer__
554 rr->data.txt.data = NULL;
555 #endif
556 break;
557
558 default:
559 if (rr->data.unparsed.len > 0 && rr->data.unparsed.data != NULL) {
560 free(rr->data.unparsed.data);
561 }
562 rr->data.unparsed.data = NULL;
563 }
564 }
565
566 void
567 dns_message_free(dns_message_t *message)
568 {
569 int i;
570 dns_edns0_t *edns0, *next;
571
572 #define FREE(count, sets) \
573 if (message->sets) { \
574 for (i = 0; i < message->count; i++) { \
575 dns_rr_t *set = &message->sets[i]; \
576 if (set->name) { \
577 dns_name_free(set->name); \
578 } \
579 dns_rrdata_free(set); \
580 } \
581 free(message->sets); \
582 }
583 FREE(qdcount, questions);
584 FREE(ancount, answers);
585 FREE(nscount, authority);
586 FREE(arcount, additional);
587 #undef FREE
588 for (edns0 = message->edns0; edns0 != NULL; edns0 = next) {
589 next = edns0->next;
590 free(edns0);
591 }
592 free(message);
593 }
594
595 bool
596 dns_wire_parse(dns_message_t *NONNULL *NULLABLE ret, dns_wire_t *message, unsigned len)
597 {
598 unsigned offset = 0;
599 unsigned data_len = len - DNS_HEADER_SIZE;
600 dns_message_t *rv = calloc(1, sizeof(*rv));
601 int i;
602
603 if (rv == NULL) {
604 return false;
605 }
606
607 #define PARSE(count, sets, name, rrdata_expected) \
608 rv->count = ntohs(message->count); \
609 if (rv->count > 50) { \
610 rv->count = 0; \
611 dns_message_free(rv); \
612 return false; \
613 } \
614 DEBUG("Section %s, %d records", name, rv->count); \
615 \
616 if (rv->count != 0) { \
617 rv->sets = calloc(rv->count, sizeof(*rv->sets)); \
618 if (rv->sets == NULL) { \
619 dns_message_free(rv); \
620 return false; \
621 } \
622 } \
623 \
624 for (i = 0; i < rv->count; i++) { \
625 if (!dns_rr_parse(&rv->sets[i], message->data, data_len, &offset, rrdata_expected)) { \
626 dns_message_free(rv); \
627 ERROR(name " %d RR parse failed.\n", i); \
628 return false; \
629 } \
630 }
631 PARSE(qdcount, questions, "question", false);
632 PARSE(ancount, answers, "answers", true);
633 PARSE(nscount, authority, "authority", true);
634 PARSE(arcount, additional, "additional", true);
635 #undef PARSE
636
637 for (i = 0; i < rv->arcount; i++) {
638 // Parse EDNS(0)
639 if (rv->additional[i].type == dns_rrtype_opt) {
640 if (!dns_opt_parse(&rv->edns0, &rv->additional[i])) {
641 dns_message_free(rv);
642 return false;
643 }
644 }
645 }
646 *ret = rv;
647 return true;
648 }
649
650 // Local Variables:
651 // mode: C
652 // tab-width: 4
653 // c-file-style: "bsd"
654 // c-basic-offset: 4
655 // fill-column: 108
656 // indent-tabs-mode: nil
657 // End: