1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <math.h>
4 
5 #include "alloc-util.h"
6 #include "dns-domain.h"
7 #include "dns-type.h"
8 #include "escape.h"
9 #include "hexdecoct.h"
10 #include "memory-util.h"
11 #include "resolved-dns-dnssec.h"
12 #include "resolved-dns-packet.h"
13 #include "resolved-dns-rr.h"
14 #include "string-table.h"
15 #include "string-util.h"
16 #include "strv.h"
17 #include "terminal-util.h"
18 
dns_resource_key_new(uint16_t class,uint16_t type,const char * name)19 DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) {
20         DnsResourceKey *k;
21         size_t l;
22 
23         assert(name);
24 
25         l = strlen(name);
26         k = malloc0(sizeof(DnsResourceKey) + l + 1);
27         if (!k)
28                 return NULL;
29 
30         k->n_ref = 1;
31         k->class = class;
32         k->type = type;
33 
34         strcpy((char*) k + sizeof(DnsResourceKey), name);
35 
36         return k;
37 }
38 
dns_resource_key_new_redirect(const DnsResourceKey * key,const DnsResourceRecord * cname)39 DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const DnsResourceRecord *cname) {
40         int r;
41 
42         assert(key);
43         assert(cname);
44 
45         assert(IN_SET(cname->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME));
46 
47         if (cname->key->type == DNS_TYPE_CNAME)
48                 return dns_resource_key_new(key->class, key->type, cname->cname.name);
49         else {
50                 _cleanup_free_ char *destination = NULL;
51                 DnsResourceKey *k;
52 
53                 r = dns_name_change_suffix(dns_resource_key_name(key), dns_resource_key_name(cname->key), cname->dname.name, &destination);
54                 if (r < 0)
55                         return NULL;
56                 if (r == 0)
57                         return dns_resource_key_ref((DnsResourceKey*) key);
58 
59                 k = dns_resource_key_new_consume(key->class, key->type, destination);
60                 if (!k)
61                         return NULL;
62 
63                 TAKE_PTR(destination);
64                 return k;
65         }
66 }
67 
dns_resource_key_new_append_suffix(DnsResourceKey ** ret,DnsResourceKey * key,char * name)68 int dns_resource_key_new_append_suffix(DnsResourceKey **ret, DnsResourceKey *key, char *name) {
69         DnsResourceKey *new_key;
70         char *joined;
71         int r;
72 
73         assert(ret);
74         assert(key);
75         assert(name);
76 
77         if (dns_name_is_root(name)) {
78                 *ret = dns_resource_key_ref(key);
79                 return 0;
80         }
81 
82         r = dns_name_concat(dns_resource_key_name(key), name, 0, &joined);
83         if (r < 0)
84                 return r;
85 
86         new_key = dns_resource_key_new_consume(key->class, key->type, joined);
87         if (!new_key) {
88                 free(joined);
89                 return -ENOMEM;
90         }
91 
92         *ret = new_key;
93         return 0;
94 }
95 
dns_resource_key_new_consume(uint16_t class,uint16_t type,char * name)96 DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name) {
97         DnsResourceKey *k;
98 
99         assert(name);
100 
101         k = new(DnsResourceKey, 1);
102         if (!k)
103                 return NULL;
104 
105         *k = (DnsResourceKey) {
106                 .n_ref = 1,
107                 .class = class,
108                 .type = type,
109                 ._name = name,
110         };
111 
112         return k;
113 }
114 
dns_resource_key_ref(DnsResourceKey * k)115 DnsResourceKey* dns_resource_key_ref(DnsResourceKey *k) {
116 
117         if (!k)
118                 return NULL;
119 
120         /* Static/const keys created with DNS_RESOURCE_KEY_CONST will
121          * set this to -1, they should not be reffed/unreffed */
122         assert(k->n_ref != UINT_MAX);
123 
124         assert(k->n_ref > 0);
125         k->n_ref++;
126 
127         return k;
128 }
129 
dns_resource_key_unref(DnsResourceKey * k)130 DnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) {
131         if (!k)
132                 return NULL;
133 
134         assert(k->n_ref != UINT_MAX);
135         assert(k->n_ref > 0);
136 
137         if (k->n_ref == 1) {
138                 free(k->_name);
139                 free(k);
140         } else
141                 k->n_ref--;
142 
143         return NULL;
144 }
145 
dns_resource_key_name(const DnsResourceKey * key)146 const char* dns_resource_key_name(const DnsResourceKey *key) {
147         const char *name;
148 
149         if (!key)
150                 return NULL;
151 
152         if (key->_name)
153                 name = key->_name;
154         else
155                 name = (char*) key + sizeof(DnsResourceKey);
156 
157         if (dns_name_is_root(name))
158                 return ".";
159         else
160                 return name;
161 }
162 
dns_resource_key_is_address(const DnsResourceKey * key)163 bool dns_resource_key_is_address(const DnsResourceKey *key) {
164         assert(key);
165 
166         /* Check if this is an A or AAAA resource key */
167 
168         return key->class == DNS_CLASS_IN && IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_AAAA);
169 }
170 
dns_resource_key_is_dnssd_ptr(const DnsResourceKey * key)171 bool dns_resource_key_is_dnssd_ptr(const DnsResourceKey *key) {
172         assert(key);
173 
174         /* Check if this is a PTR resource key used in
175            Service Instance Enumeration as described in RFC6763 p4.1. */
176 
177         if (key->type != DNS_TYPE_PTR)
178                 return false;
179 
180         return dns_name_endswith(dns_resource_key_name(key), "_tcp.local") ||
181                 dns_name_endswith(dns_resource_key_name(key), "_udp.local");
182 }
183 
dns_resource_key_equal(const DnsResourceKey * a,const DnsResourceKey * b)184 int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) {
185         int r;
186 
187         if (a == b)
188                 return 1;
189 
190         r = dns_name_equal(dns_resource_key_name(a), dns_resource_key_name(b));
191         if (r <= 0)
192                 return r;
193 
194         if (a->class != b->class)
195                 return 0;
196 
197         if (a->type != b->type)
198                 return 0;
199 
200         return 1;
201 }
202 
dns_resource_key_match_rr(const DnsResourceKey * key,DnsResourceRecord * rr,const char * search_domain)203 int dns_resource_key_match_rr(const DnsResourceKey *key, DnsResourceRecord *rr, const char *search_domain) {
204         int r;
205 
206         assert(key);
207         assert(rr);
208 
209         if (key == rr->key)
210                 return 1;
211 
212         /* Checks if an rr matches the specified key. If a search
213          * domain is specified, it will also be checked if the key
214          * with the search domain suffixed might match the RR. */
215 
216         if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
217                 return 0;
218 
219         if (rr->key->type != key->type && key->type != DNS_TYPE_ANY)
220                 return 0;
221 
222         r = dns_name_equal(dns_resource_key_name(rr->key), dns_resource_key_name(key));
223         if (r != 0)
224                 return r;
225 
226         if (search_domain) {
227                 _cleanup_free_ char *joined = NULL;
228 
229                 r = dns_name_concat(dns_resource_key_name(key), search_domain, 0, &joined);
230                 if (r < 0)
231                         return r;
232 
233                 return dns_name_equal(dns_resource_key_name(rr->key), joined);
234         }
235 
236         return 0;
237 }
238 
dns_resource_key_match_cname_or_dname(const DnsResourceKey * key,const DnsResourceKey * cname,const char * search_domain)239 int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain) {
240         int r;
241 
242         assert(key);
243         assert(cname);
244 
245         if (cname->class != key->class && key->class != DNS_CLASS_ANY)
246                 return 0;
247 
248         if (!dns_type_may_redirect(key->type))
249                 return 0;
250 
251         if (cname->type == DNS_TYPE_CNAME)
252                 r = dns_name_equal(dns_resource_key_name(key), dns_resource_key_name(cname));
253         else if (cname->type == DNS_TYPE_DNAME)
254                 r = dns_name_endswith(dns_resource_key_name(key), dns_resource_key_name(cname));
255         else
256                 return 0;
257 
258         if (r != 0)
259                 return r;
260 
261         if (search_domain) {
262                 _cleanup_free_ char *joined = NULL;
263 
264                 r = dns_name_concat(dns_resource_key_name(key), search_domain, 0, &joined);
265                 if (r < 0)
266                         return r;
267 
268                 if (cname->type == DNS_TYPE_CNAME)
269                         return dns_name_equal(joined, dns_resource_key_name(cname));
270                 else if (cname->type == DNS_TYPE_DNAME)
271                         return dns_name_endswith(joined, dns_resource_key_name(cname));
272         }
273 
274         return 0;
275 }
276 
dns_resource_key_match_soa(const DnsResourceKey * key,const DnsResourceKey * soa)277 int dns_resource_key_match_soa(const DnsResourceKey *key, const DnsResourceKey *soa) {
278         assert(soa);
279         assert(key);
280 
281         /* Checks whether 'soa' is a SOA record for the specified key. */
282 
283         if (soa->class != key->class)
284                 return 0;
285 
286         if (soa->type != DNS_TYPE_SOA)
287                 return 0;
288 
289         return dns_name_endswith(dns_resource_key_name(key), dns_resource_key_name(soa));
290 }
291 
dns_resource_key_hash_func(const DnsResourceKey * k,struct siphash * state)292 static void dns_resource_key_hash_func(const DnsResourceKey *k, struct siphash *state) {
293         assert(k);
294 
295         dns_name_hash_func(dns_resource_key_name(k), state);
296         siphash24_compress(&k->class, sizeof(k->class), state);
297         siphash24_compress(&k->type, sizeof(k->type), state);
298 }
299 
dns_resource_key_compare_func(const DnsResourceKey * x,const DnsResourceKey * y)300 static int dns_resource_key_compare_func(const DnsResourceKey *x, const DnsResourceKey *y) {
301         int r;
302 
303         r = dns_name_compare_func(dns_resource_key_name(x), dns_resource_key_name(y));
304         if (r != 0)
305                 return r;
306 
307         r = CMP(x->type, y->type);
308         if (r != 0)
309                 return r;
310 
311         return CMP(x->class, y->class);
312 }
313 
314 DEFINE_HASH_OPS(dns_resource_key_hash_ops, DnsResourceKey, dns_resource_key_hash_func, dns_resource_key_compare_func);
315 
dns_resource_key_to_string(const DnsResourceKey * key,char * buf,size_t buf_size)316 char* dns_resource_key_to_string(const DnsResourceKey *key, char *buf, size_t buf_size) {
317         const char *c, *t;
318         char *ans = buf;
319 
320         /* If we cannot convert the CLASS/TYPE into a known string,
321            use the format recommended by RFC 3597, Section 5. */
322 
323         c = dns_class_to_string(key->class);
324         t = dns_type_to_string(key->type);
325 
326         (void) snprintf(buf, buf_size, "%s %s%s%.0u %s%s%.0u",
327                         dns_resource_key_name(key),
328                         strempty(c), c ? "" : "CLASS", c ? 0 : key->class,
329                         strempty(t), t ? "" : "TYPE", t ? 0 : key->type);
330 
331         return ans;
332 }
333 
dns_resource_key_reduce(DnsResourceKey ** a,DnsResourceKey ** b)334 bool dns_resource_key_reduce(DnsResourceKey **a, DnsResourceKey **b) {
335         assert(a);
336         assert(b);
337 
338         /* Try to replace one RR key by another if they are identical, thus saving a bit of memory. Note that we do
339          * this only for RR keys, not for RRs themselves, as they carry a lot of additional metadata (where they come
340          * from, validity data, and suchlike), and cannot be replaced so easily by other RRs that have the same
341          * superficial data. */
342 
343         if (!*a)
344                 return false;
345         if (!*b)
346                 return false;
347 
348         /* We refuse merging const keys */
349         if ((*a)->n_ref == UINT_MAX)
350                 return false;
351         if ((*b)->n_ref == UINT_MAX)
352                 return false;
353 
354         /* Already the same? */
355         if (*a == *b)
356                 return true;
357 
358         /* Are they really identical? */
359         if (dns_resource_key_equal(*a, *b) <= 0)
360                 return false;
361 
362         /* Keep the one which already has more references. */
363         if ((*a)->n_ref > (*b)->n_ref)
364                 DNS_RESOURCE_KEY_REPLACE(*b, dns_resource_key_ref(*a));
365         else
366                 DNS_RESOURCE_KEY_REPLACE(*a, dns_resource_key_ref(*b));
367 
368         return true;
369 }
370 
dns_resource_record_new(DnsResourceKey * key)371 DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) {
372         DnsResourceRecord *rr;
373 
374         rr = new(DnsResourceRecord, 1);
375         if (!rr)
376                 return NULL;
377 
378         *rr = (DnsResourceRecord) {
379                 .n_ref = 1,
380                 .key = dns_resource_key_ref(key),
381                 .expiry = USEC_INFINITY,
382                 .n_skip_labels_signer = UINT8_MAX,
383                 .n_skip_labels_source = UINT8_MAX,
384         };
385 
386         return rr;
387 }
388 
dns_resource_record_new_full(uint16_t class,uint16_t type,const char * name)389 DnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name) {
390         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
391 
392         key = dns_resource_key_new(class, type, name);
393         if (!key)
394                 return NULL;
395 
396         return dns_resource_record_new(key);
397 }
398 
dns_resource_record_free(DnsResourceRecord * rr)399 static DnsResourceRecord* dns_resource_record_free(DnsResourceRecord *rr) {
400         assert(rr);
401 
402         if (rr->key) {
403                 switch (rr->key->type) {
404 
405                 case DNS_TYPE_SRV:
406                         free(rr->srv.name);
407                         break;
408 
409                 case DNS_TYPE_PTR:
410                 case DNS_TYPE_NS:
411                 case DNS_TYPE_CNAME:
412                 case DNS_TYPE_DNAME:
413                         free(rr->ptr.name);
414                         break;
415 
416                 case DNS_TYPE_HINFO:
417                         free(rr->hinfo.cpu);
418                         free(rr->hinfo.os);
419                         break;
420 
421                 case DNS_TYPE_TXT:
422                 case DNS_TYPE_SPF:
423                         dns_txt_item_free_all(rr->txt.items);
424                         break;
425 
426                 case DNS_TYPE_SOA:
427                         free(rr->soa.mname);
428                         free(rr->soa.rname);
429                         break;
430 
431                 case DNS_TYPE_MX:
432                         free(rr->mx.exchange);
433                         break;
434 
435                 case DNS_TYPE_DS:
436                         free(rr->ds.digest);
437                         break;
438 
439                 case DNS_TYPE_SSHFP:
440                         free(rr->sshfp.fingerprint);
441                         break;
442 
443                 case DNS_TYPE_DNSKEY:
444                         free(rr->dnskey.key);
445                         break;
446 
447                 case DNS_TYPE_RRSIG:
448                         free(rr->rrsig.signer);
449                         free(rr->rrsig.signature);
450                         break;
451 
452                 case DNS_TYPE_NSEC:
453                         free(rr->nsec.next_domain_name);
454                         bitmap_free(rr->nsec.types);
455                         break;
456 
457                 case DNS_TYPE_NSEC3:
458                         free(rr->nsec3.next_hashed_name);
459                         free(rr->nsec3.salt);
460                         bitmap_free(rr->nsec3.types);
461                         break;
462 
463                 case DNS_TYPE_LOC:
464                 case DNS_TYPE_A:
465                 case DNS_TYPE_AAAA:
466                         break;
467 
468                 case DNS_TYPE_TLSA:
469                         free(rr->tlsa.data);
470                         break;
471 
472                 case DNS_TYPE_CAA:
473                         free(rr->caa.tag);
474                         free(rr->caa.value);
475                         break;
476 
477                 case DNS_TYPE_OPENPGPKEY:
478                 default:
479                         if (!rr->unparsable)
480                                 free(rr->generic.data);
481                 }
482 
483                 if (rr->unparsable)
484                         free(rr->generic.data);
485 
486                 free(rr->wire_format);
487                 dns_resource_key_unref(rr->key);
488         }
489 
490         free(rr->to_string);
491         return mfree(rr);
492 }
493 
494 DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsResourceRecord, dns_resource_record, dns_resource_record_free);
495 
dns_resource_record_new_reverse(DnsResourceRecord ** ret,int family,const union in_addr_union * address,const char * hostname)496 int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) {
497         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
498         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
499         _cleanup_free_ char *ptr = NULL;
500         int r;
501 
502         assert(ret);
503         assert(address);
504         assert(hostname);
505 
506         r = dns_name_reverse(family, address, &ptr);
507         if (r < 0)
508                 return r;
509 
510         key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, ptr);
511         if (!key)
512                 return -ENOMEM;
513 
514         ptr = NULL;
515 
516         rr = dns_resource_record_new(key);
517         if (!rr)
518                 return -ENOMEM;
519 
520         rr->ptr.name = strdup(hostname);
521         if (!rr->ptr.name)
522                 return -ENOMEM;
523 
524         *ret = TAKE_PTR(rr);
525 
526         return 0;
527 }
528 
dns_resource_record_new_address(DnsResourceRecord ** ret,int family,const union in_addr_union * address,const char * name)529 int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name) {
530         DnsResourceRecord *rr;
531 
532         assert(ret);
533         assert(address);
534         assert(family);
535 
536         if (family == AF_INET) {
537 
538                 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, name);
539                 if (!rr)
540                         return -ENOMEM;
541 
542                 rr->a.in_addr = address->in;
543 
544         } else if (family == AF_INET6) {
545 
546                 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, name);
547                 if (!rr)
548                         return -ENOMEM;
549 
550                 rr->aaaa.in6_addr = address->in6;
551         } else
552                 return -EAFNOSUPPORT;
553 
554         *ret = rr;
555 
556         return 0;
557 }
558 
559 #define FIELD_EQUAL(a, b, field) \
560         ((a).field ## _size == (b).field ## _size &&  \
561          memcmp_safe((a).field, (b).field, (a).field ## _size) == 0)
562 
dns_resource_record_payload_equal(const DnsResourceRecord * a,const DnsResourceRecord * b)563 int dns_resource_record_payload_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
564         int r;
565 
566         /* Check if a and b are the same, but don't look at their keys */
567 
568         if (a->unparsable != b->unparsable)
569                 return 0;
570 
571         switch (a->unparsable ? _DNS_TYPE_INVALID : a->key->type) {
572 
573         case DNS_TYPE_SRV:
574                 r = dns_name_equal(a->srv.name, b->srv.name);
575                 if (r <= 0)
576                         return r;
577 
578                 return a->srv.priority == b->srv.priority &&
579                        a->srv.weight == b->srv.weight &&
580                        a->srv.port == b->srv.port;
581 
582         case DNS_TYPE_PTR:
583         case DNS_TYPE_NS:
584         case DNS_TYPE_CNAME:
585         case DNS_TYPE_DNAME:
586                 return dns_name_equal(a->ptr.name, b->ptr.name);
587 
588         case DNS_TYPE_HINFO:
589                 return strcaseeq(a->hinfo.cpu, b->hinfo.cpu) &&
590                        strcaseeq(a->hinfo.os, b->hinfo.os);
591 
592         case DNS_TYPE_SPF: /* exactly the same as TXT */
593         case DNS_TYPE_TXT:
594                 return dns_txt_item_equal(a->txt.items, b->txt.items);
595 
596         case DNS_TYPE_A:
597                 return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
598 
599         case DNS_TYPE_AAAA:
600                 return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0;
601 
602         case DNS_TYPE_SOA:
603                 r = dns_name_equal(a->soa.mname, b->soa.mname);
604                 if (r <= 0)
605                         return r;
606                 r = dns_name_equal(a->soa.rname, b->soa.rname);
607                 if (r <= 0)
608                         return r;
609 
610                 return a->soa.serial  == b->soa.serial &&
611                        a->soa.refresh == b->soa.refresh &&
612                        a->soa.retry   == b->soa.retry &&
613                        a->soa.expire  == b->soa.expire &&
614                        a->soa.minimum == b->soa.minimum;
615 
616         case DNS_TYPE_MX:
617                 if (a->mx.priority != b->mx.priority)
618                         return 0;
619 
620                 return dns_name_equal(a->mx.exchange, b->mx.exchange);
621 
622         case DNS_TYPE_LOC:
623                 assert(a->loc.version == b->loc.version);
624 
625                 return a->loc.size == b->loc.size &&
626                        a->loc.horiz_pre == b->loc.horiz_pre &&
627                        a->loc.vert_pre == b->loc.vert_pre &&
628                        a->loc.latitude == b->loc.latitude &&
629                        a->loc.longitude == b->loc.longitude &&
630                        a->loc.altitude == b->loc.altitude;
631 
632         case DNS_TYPE_DS:
633                 return a->ds.key_tag == b->ds.key_tag &&
634                        a->ds.algorithm == b->ds.algorithm &&
635                        a->ds.digest_type == b->ds.digest_type &&
636                        FIELD_EQUAL(a->ds, b->ds, digest);
637 
638         case DNS_TYPE_SSHFP:
639                 return a->sshfp.algorithm == b->sshfp.algorithm &&
640                        a->sshfp.fptype == b->sshfp.fptype &&
641                        FIELD_EQUAL(a->sshfp, b->sshfp, fingerprint);
642 
643         case DNS_TYPE_DNSKEY:
644                 return a->dnskey.flags == b->dnskey.flags &&
645                        a->dnskey.protocol == b->dnskey.protocol &&
646                        a->dnskey.algorithm == b->dnskey.algorithm &&
647                        FIELD_EQUAL(a->dnskey, b->dnskey, key);
648 
649         case DNS_TYPE_RRSIG:
650                 /* do the fast comparisons first */
651                 return a->rrsig.type_covered == b->rrsig.type_covered &&
652                        a->rrsig.algorithm == b->rrsig.algorithm &&
653                        a->rrsig.labels == b->rrsig.labels &&
654                        a->rrsig.original_ttl == b->rrsig.original_ttl &&
655                        a->rrsig.expiration == b->rrsig.expiration &&
656                        a->rrsig.inception == b->rrsig.inception &&
657                        a->rrsig.key_tag == b->rrsig.key_tag &&
658                        FIELD_EQUAL(a->rrsig, b->rrsig, signature) &&
659                        dns_name_equal(a->rrsig.signer, b->rrsig.signer);
660 
661         case DNS_TYPE_NSEC:
662                 return dns_name_equal(a->nsec.next_domain_name, b->nsec.next_domain_name) &&
663                        bitmap_equal(a->nsec.types, b->nsec.types);
664 
665         case DNS_TYPE_NSEC3:
666                 return a->nsec3.algorithm == b->nsec3.algorithm &&
667                        a->nsec3.flags == b->nsec3.flags &&
668                        a->nsec3.iterations == b->nsec3.iterations &&
669                        FIELD_EQUAL(a->nsec3, b->nsec3, salt) &&
670                        FIELD_EQUAL(a->nsec3, b->nsec3, next_hashed_name) &&
671                        bitmap_equal(a->nsec3.types, b->nsec3.types);
672 
673         case DNS_TYPE_TLSA:
674                 return a->tlsa.cert_usage == b->tlsa.cert_usage &&
675                        a->tlsa.selector == b->tlsa.selector &&
676                        a->tlsa.matching_type == b->tlsa.matching_type &&
677                        FIELD_EQUAL(a->tlsa, b->tlsa, data);
678 
679         case DNS_TYPE_CAA:
680                 return a->caa.flags == b->caa.flags &&
681                        streq(a->caa.tag, b->caa.tag) &&
682                        FIELD_EQUAL(a->caa, b->caa, value);
683 
684         case DNS_TYPE_OPENPGPKEY:
685         default:
686                 return FIELD_EQUAL(a->generic, b->generic, data);
687         }
688 }
689 
dns_resource_record_equal(const DnsResourceRecord * a,const DnsResourceRecord * b)690 int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
691         int r;
692 
693         assert(a);
694         assert(b);
695 
696         if (a == b)
697                 return 1;
698 
699         r = dns_resource_key_equal(a->key, b->key);
700         if (r <= 0)
701                 return r;
702 
703         return dns_resource_record_payload_equal(a, b);
704 }
705 
format_location(uint32_t latitude,uint32_t longitude,uint32_t altitude,uint8_t size,uint8_t horiz_pre,uint8_t vert_pre)706 static char* format_location(uint32_t latitude, uint32_t longitude, uint32_t altitude,
707                              uint8_t size, uint8_t horiz_pre, uint8_t vert_pre) {
708         char *s;
709         char NS = latitude >= 1U<<31 ? 'N' : 'S';
710         char EW = longitude >= 1U<<31 ? 'E' : 'W';
711 
712         int lat = latitude >= 1U<<31 ? (int) (latitude - (1U<<31)) : (int) ((1U<<31) - latitude);
713         int lon = longitude >= 1U<<31 ? (int) (longitude - (1U<<31)) : (int) ((1U<<31) - longitude);
714         double alt = altitude >= 10000000u ? altitude - 10000000u : -(double)(10000000u - altitude);
715         double siz = (size >> 4) * exp10((double) (size & 0xF));
716         double hor = (horiz_pre >> 4) * exp10((double) (horiz_pre & 0xF));
717         double ver = (vert_pre >> 4) * exp10((double) (vert_pre & 0xF));
718 
719         if (asprintf(&s, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm",
720                      (lat / 60000 / 60),
721                      (lat / 60000) % 60,
722                      (lat % 60000) / 1000.,
723                      NS,
724                      (lon / 60000 / 60),
725                      (lon / 60000) % 60,
726                      (lon % 60000) / 1000.,
727                      EW,
728                      alt / 100.,
729                      siz / 100.,
730                      hor / 100.,
731                      ver / 100.) < 0)
732                 return NULL;
733 
734         return s;
735 }
736 
format_timestamp_dns(char * buf,size_t l,time_t sec)737 static int format_timestamp_dns(char *buf, size_t l, time_t sec) {
738         struct tm tm;
739 
740         assert(buf);
741         assert(l > STRLEN("YYYYMMDDHHmmSS"));
742 
743         if (!gmtime_r(&sec, &tm))
744                 return -EINVAL;
745 
746         if (strftime(buf, l, "%Y%m%d%H%M%S", &tm) <= 0)
747                 return -EINVAL;
748 
749         return 0;
750 }
751 
format_types(Bitmap * types)752 static char *format_types(Bitmap *types) {
753         _cleanup_strv_free_ char **strv = NULL;
754         _cleanup_free_ char *str = NULL;
755         unsigned type;
756         int r;
757 
758         BITMAP_FOREACH(type, types) {
759                 if (dns_type_to_string(type)) {
760                         r = strv_extend(&strv, dns_type_to_string(type));
761                         if (r < 0)
762                                 return NULL;
763                 } else {
764                         char *t;
765 
766                         r = asprintf(&t, "TYPE%u", type);
767                         if (r < 0)
768                                 return NULL;
769 
770                         r = strv_consume(&strv, t);
771                         if (r < 0)
772                                 return NULL;
773                 }
774         }
775 
776         str = strv_join(strv, " ");
777         if (!str)
778                 return NULL;
779 
780         return strjoin("( ", str, " )");
781 }
782 
format_txt(DnsTxtItem * first)783 static char *format_txt(DnsTxtItem *first) {
784         size_t c = 1;
785         char *p, *s;
786 
787         LIST_FOREACH(items, i, first)
788                 c += i->length * 4 + 3;
789 
790         p = s = new(char, c);
791         if (!s)
792                 return NULL;
793 
794         LIST_FOREACH(items, i, first) {
795                 if (i != first)
796                         *(p++) = ' ';
797 
798                 *(p++) = '"';
799 
800                 for (size_t j = 0; j < i->length; j++) {
801                         if (i->data[j] < ' ' || i->data[j] == '"' || i->data[j] >= 127) {
802                                 *(p++) = '\\';
803                                 *(p++) = '0' + (i->data[j] / 100);
804                                 *(p++) = '0' + ((i->data[j] / 10) % 10);
805                                 *(p++) = '0' + (i->data[j] % 10);
806                         } else
807                                 *(p++) = i->data[j];
808                 }
809 
810                 *(p++) = '"';
811         }
812 
813         *p = 0;
814         return s;
815 }
816 
dns_resource_record_to_string(DnsResourceRecord * rr)817 const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
818         _cleanup_free_ char *s = NULL, *t = NULL;
819         char k[DNS_RESOURCE_KEY_STRING_MAX];
820         int r;
821 
822         assert(rr);
823 
824         if (rr->to_string)
825                 return rr->to_string;
826 
827         dns_resource_key_to_string(rr->key, k, sizeof(k));
828 
829         switch (rr->unparsable ? _DNS_TYPE_INVALID : rr->key->type) {
830 
831         case DNS_TYPE_SRV:
832                 r = asprintf(&s, "%s %u %u %u %s",
833                              k,
834                              rr->srv.priority,
835                              rr->srv.weight,
836                              rr->srv.port,
837                              strna(rr->srv.name));
838                 if (r < 0)
839                         return NULL;
840                 break;
841 
842         case DNS_TYPE_PTR:
843         case DNS_TYPE_NS:
844         case DNS_TYPE_CNAME:
845         case DNS_TYPE_DNAME:
846                 s = strjoin(k, " ", rr->ptr.name);
847                 if (!s)
848                         return NULL;
849 
850                 break;
851 
852         case DNS_TYPE_HINFO:
853                 s = strjoin(k, " ", rr->hinfo.cpu, " ", rr->hinfo.os);
854                 if (!s)
855                         return NULL;
856                 break;
857 
858         case DNS_TYPE_SPF: /* exactly the same as TXT */
859         case DNS_TYPE_TXT:
860                 t = format_txt(rr->txt.items);
861                 if (!t)
862                         return NULL;
863 
864                 s = strjoin(k, " ", t);
865                 if (!s)
866                         return NULL;
867                 break;
868 
869         case DNS_TYPE_A:
870                 r = in_addr_to_string(AF_INET, (const union in_addr_union*) &rr->a.in_addr, &t);
871                 if (r < 0)
872                         return NULL;
873 
874                 s = strjoin(k, " ", t);
875                 if (!s)
876                         return NULL;
877                 break;
878 
879         case DNS_TYPE_AAAA:
880                 r = in_addr_to_string(AF_INET6, (const union in_addr_union*) &rr->aaaa.in6_addr, &t);
881                 if (r < 0)
882                         return NULL;
883 
884                 s = strjoin(k, " ", t);
885                 if (!s)
886                         return NULL;
887                 break;
888 
889         case DNS_TYPE_SOA:
890                 r = asprintf(&s, "%s %s %s %u %u %u %u %u",
891                              k,
892                              strna(rr->soa.mname),
893                              strna(rr->soa.rname),
894                              rr->soa.serial,
895                              rr->soa.refresh,
896                              rr->soa.retry,
897                              rr->soa.expire,
898                              rr->soa.minimum);
899                 if (r < 0)
900                         return NULL;
901                 break;
902 
903         case DNS_TYPE_MX:
904                 r = asprintf(&s, "%s %u %s",
905                              k,
906                              rr->mx.priority,
907                              rr->mx.exchange);
908                 if (r < 0)
909                         return NULL;
910                 break;
911 
912         case DNS_TYPE_LOC:
913                 assert(rr->loc.version == 0);
914 
915                 t = format_location(rr->loc.latitude,
916                                     rr->loc.longitude,
917                                     rr->loc.altitude,
918                                     rr->loc.size,
919                                     rr->loc.horiz_pre,
920                                     rr->loc.vert_pre);
921                 if (!t)
922                         return NULL;
923 
924                 s = strjoin(k, " ", t);
925                 if (!s)
926                         return NULL;
927                 break;
928 
929         case DNS_TYPE_DS:
930                 t = hexmem(rr->ds.digest, rr->ds.digest_size);
931                 if (!t)
932                         return NULL;
933 
934                 r = asprintf(&s, "%s %u %u %u %s",
935                              k,
936                              rr->ds.key_tag,
937                              rr->ds.algorithm,
938                              rr->ds.digest_type,
939                              t);
940                 if (r < 0)
941                         return NULL;
942                 break;
943 
944         case DNS_TYPE_SSHFP:
945                 t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size);
946                 if (!t)
947                         return NULL;
948 
949                 r = asprintf(&s, "%s %u %u %s",
950                              k,
951                              rr->sshfp.algorithm,
952                              rr->sshfp.fptype,
953                              t);
954                 if (r < 0)
955                         return NULL;
956                 break;
957 
958         case DNS_TYPE_DNSKEY: {
959                 _cleanup_free_ char *alg = NULL;
960                 uint16_t key_tag;
961 
962                 key_tag = dnssec_keytag(rr, true);
963 
964                 r = dnssec_algorithm_to_string_alloc(rr->dnskey.algorithm, &alg);
965                 if (r < 0)
966                         return NULL;
967 
968                 r = asprintf(&t, "%s %u %u %s",
969                              k,
970                              rr->dnskey.flags,
971                              rr->dnskey.protocol,
972                              alg);
973                 if (r < 0)
974                         return NULL;
975 
976                 r = base64_append(&t, r,
977                                   rr->dnskey.key, rr->dnskey.key_size,
978                                   8, columns());
979                 if (r < 0)
980                         return NULL;
981 
982                 r = asprintf(&s, "%s\n"
983                              "        -- Flags:%s%s%s\n"
984                              "        -- Key tag: %u",
985                              t,
986                              rr->dnskey.flags & DNSKEY_FLAG_SEP ? " SEP" : "",
987                              rr->dnskey.flags & DNSKEY_FLAG_REVOKE ? " REVOKE" : "",
988                              rr->dnskey.flags & DNSKEY_FLAG_ZONE_KEY ? " ZONE_KEY" : "",
989                              key_tag);
990                 if (r < 0)
991                         return NULL;
992 
993                 break;
994         }
995 
996         case DNS_TYPE_RRSIG: {
997                 _cleanup_free_ char *alg = NULL;
998                 char expiration[STRLEN("YYYYMMDDHHmmSS") + 1], inception[STRLEN("YYYYMMDDHHmmSS") + 1];
999                 const char *type;
1000 
1001                 type = dns_type_to_string(rr->rrsig.type_covered);
1002 
1003                 r = dnssec_algorithm_to_string_alloc(rr->rrsig.algorithm, &alg);
1004                 if (r < 0)
1005                         return NULL;
1006 
1007                 r = format_timestamp_dns(expiration, sizeof(expiration), rr->rrsig.expiration);
1008                 if (r < 0)
1009                         return NULL;
1010 
1011                 r = format_timestamp_dns(inception, sizeof(inception), rr->rrsig.inception);
1012                 if (r < 0)
1013                         return NULL;
1014 
1015                 /* TYPE?? follows
1016                  * http://tools.ietf.org/html/rfc3597#section-5 */
1017 
1018                 r = asprintf(&s, "%s %s%.*u %s %u %u %s %s %u %s",
1019                              k,
1020                              type ?: "TYPE",
1021                              type ? 0 : 1, type ? 0u : (unsigned) rr->rrsig.type_covered,
1022                              alg,
1023                              rr->rrsig.labels,
1024                              rr->rrsig.original_ttl,
1025                              expiration,
1026                              inception,
1027                              rr->rrsig.key_tag,
1028                              rr->rrsig.signer);
1029                 if (r < 0)
1030                         return NULL;
1031 
1032                 r = base64_append(&s, r,
1033                                   rr->rrsig.signature, rr->rrsig.signature_size,
1034                                   8, columns());
1035                 if (r < 0)
1036                         return NULL;
1037 
1038                 break;
1039         }
1040 
1041         case DNS_TYPE_NSEC:
1042                 t = format_types(rr->nsec.types);
1043                 if (!t)
1044                         return NULL;
1045 
1046                 r = asprintf(&s, "%s %s %s",
1047                              k,
1048                              rr->nsec.next_domain_name,
1049                              t);
1050                 if (r < 0)
1051                         return NULL;
1052                 break;
1053 
1054         case DNS_TYPE_NSEC3: {
1055                 _cleanup_free_ char *salt = NULL, *hash = NULL;
1056 
1057                 if (rr->nsec3.salt_size > 0) {
1058                         salt = hexmem(rr->nsec3.salt, rr->nsec3.salt_size);
1059                         if (!salt)
1060                                 return NULL;
1061                 }
1062 
1063                 hash = base32hexmem(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, false);
1064                 if (!hash)
1065                         return NULL;
1066 
1067                 t = format_types(rr->nsec3.types);
1068                 if (!t)
1069                         return NULL;
1070 
1071                 r = asprintf(&s, "%s %"PRIu8" %"PRIu8" %"PRIu16" %s %s %s",
1072                              k,
1073                              rr->nsec3.algorithm,
1074                              rr->nsec3.flags,
1075                              rr->nsec3.iterations,
1076                              rr->nsec3.salt_size > 0 ? salt : "-",
1077                              hash,
1078                              t);
1079                 if (r < 0)
1080                         return NULL;
1081 
1082                 break;
1083         }
1084 
1085         case DNS_TYPE_TLSA: {
1086                 const char *cert_usage, *selector, *matching_type;
1087 
1088                 cert_usage = tlsa_cert_usage_to_string(rr->tlsa.cert_usage);
1089                 selector = tlsa_selector_to_string(rr->tlsa.selector);
1090                 matching_type = tlsa_matching_type_to_string(rr->tlsa.matching_type);
1091 
1092                 t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size);
1093                 if (!t)
1094                         return NULL;
1095 
1096                 r = asprintf(&s,
1097                              "%s %u %u %u %s\n"
1098                              "        -- Cert. usage: %s\n"
1099                              "        -- Selector: %s\n"
1100                              "        -- Matching type: %s",
1101                              k,
1102                              rr->tlsa.cert_usage,
1103                              rr->tlsa.selector,
1104                              rr->tlsa.matching_type,
1105                              t,
1106                              cert_usage,
1107                              selector,
1108                              matching_type);
1109                 if (r < 0)
1110                         return NULL;
1111 
1112                 break;
1113         }
1114 
1115         case DNS_TYPE_CAA:
1116                 t = octescape(rr->caa.value, rr->caa.value_size);
1117                 if (!t)
1118                         return NULL;
1119 
1120                 r = asprintf(&s, "%s %u %s \"%s\"%s%s%s%.0u",
1121                              k,
1122                              rr->caa.flags,
1123                              rr->caa.tag,
1124                              t,
1125                              rr->caa.flags ? "\n        -- Flags:" : "",
1126                              rr->caa.flags & CAA_FLAG_CRITICAL ? " critical" : "",
1127                              rr->caa.flags & ~CAA_FLAG_CRITICAL ? " " : "",
1128                              rr->caa.flags & ~CAA_FLAG_CRITICAL);
1129                 if (r < 0)
1130                         return NULL;
1131 
1132                 break;
1133 
1134         case DNS_TYPE_OPENPGPKEY:
1135                 r = asprintf(&s, "%s", k);
1136                 if (r < 0)
1137                         return NULL;
1138 
1139                 r = base64_append(&s, r,
1140                                   rr->generic.data, rr->generic.data_size,
1141                                   8, columns());
1142                 if (r < 0)
1143                         return NULL;
1144                 break;
1145 
1146         default:
1147                 t = hexmem(rr->generic.data, rr->generic.data_size);
1148                 if (!t)
1149                         return NULL;
1150 
1151                 /* Format as documented in RFC 3597, Section 5 */
1152                 r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.data_size, t);
1153                 if (r < 0)
1154                         return NULL;
1155                 break;
1156         }
1157 
1158         rr->to_string = s;
1159         return TAKE_PTR(s);
1160 }
1161 
dns_resource_record_payload(DnsResourceRecord * rr,void ** out)1162 ssize_t dns_resource_record_payload(DnsResourceRecord *rr, void **out) {
1163         assert(rr);
1164         assert(out);
1165 
1166         switch (rr->unparsable ? _DNS_TYPE_INVALID : rr->key->type) {
1167         case DNS_TYPE_SRV:
1168         case DNS_TYPE_PTR:
1169         case DNS_TYPE_NS:
1170         case DNS_TYPE_CNAME:
1171         case DNS_TYPE_DNAME:
1172         case DNS_TYPE_HINFO:
1173         case DNS_TYPE_SPF:
1174         case DNS_TYPE_TXT:
1175         case DNS_TYPE_A:
1176         case DNS_TYPE_AAAA:
1177         case DNS_TYPE_SOA:
1178         case DNS_TYPE_MX:
1179         case DNS_TYPE_LOC:
1180         case DNS_TYPE_DS:
1181         case DNS_TYPE_DNSKEY:
1182         case DNS_TYPE_RRSIG:
1183         case DNS_TYPE_NSEC:
1184         case DNS_TYPE_NSEC3:
1185                 return -EINVAL;
1186 
1187         case DNS_TYPE_SSHFP:
1188                 *out = rr->sshfp.fingerprint;
1189                 return rr->sshfp.fingerprint_size;
1190 
1191         case DNS_TYPE_TLSA:
1192                 *out = rr->tlsa.data;
1193                 return rr->tlsa.data_size;
1194 
1195         case DNS_TYPE_OPENPGPKEY:
1196         default:
1197                 *out = rr->generic.data;
1198                 return rr->generic.data_size;
1199         }
1200 }
1201 
dns_resource_record_to_wire_format(DnsResourceRecord * rr,bool canonical)1202 int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical) {
1203 
1204         DnsPacket packet = {
1205                 .n_ref = 1,
1206                 .protocol = DNS_PROTOCOL_DNS,
1207                 .on_stack = true,
1208                 .refuse_compression = true,
1209                 .canonical_form = canonical,
1210         };
1211 
1212         size_t start, rds;
1213         int r;
1214 
1215         assert(rr);
1216 
1217         /* Generates the RR in wire-format, optionally in the
1218          * canonical form as discussed in the DNSSEC RFC 4034, Section
1219          * 6.2. We allocate a throw-away DnsPacket object on the stack
1220          * here, because we need some book-keeping for memory
1221          * management, and can reuse the DnsPacket serializer, that
1222          * can generate the canonical form, too, but also knows label
1223          * compression and suchlike. */
1224 
1225         if (rr->wire_format && rr->wire_format_canonical == canonical)
1226                 return 0;
1227 
1228         r = dns_packet_append_rr(&packet, rr, 0, &start, &rds);
1229         if (r < 0)
1230                 return r;
1231 
1232         assert(start == 0);
1233         assert(packet._data);
1234 
1235         free(rr->wire_format);
1236         rr->wire_format = packet._data;
1237         rr->wire_format_size = packet.size;
1238         rr->wire_format_rdata_offset = rds;
1239         rr->wire_format_canonical = canonical;
1240 
1241         packet._data = NULL;
1242         dns_packet_unref(&packet);
1243 
1244         return 0;
1245 }
1246 
dns_resource_record_signer(DnsResourceRecord * rr,const char ** ret)1247 int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret) {
1248         const char *n;
1249         int r;
1250 
1251         assert(rr);
1252         assert(ret);
1253 
1254         /* Returns the RRset's signer, if it is known. */
1255 
1256         if (rr->n_skip_labels_signer == UINT8_MAX)
1257                 return -ENODATA;
1258 
1259         n = dns_resource_key_name(rr->key);
1260         r = dns_name_skip(n, rr->n_skip_labels_signer, &n);
1261         if (r < 0)
1262                 return r;
1263         if (r == 0)
1264                 return -EINVAL;
1265 
1266         *ret = n;
1267         return 0;
1268 }
1269 
dns_resource_record_source(DnsResourceRecord * rr,const char ** ret)1270 int dns_resource_record_source(DnsResourceRecord *rr, const char **ret) {
1271         const char *n;
1272         int r;
1273 
1274         assert(rr);
1275         assert(ret);
1276 
1277         /* Returns the RRset's synthesizing source, if it is known. */
1278 
1279         if (rr->n_skip_labels_source == UINT8_MAX)
1280                 return -ENODATA;
1281 
1282         n = dns_resource_key_name(rr->key);
1283         r = dns_name_skip(n, rr->n_skip_labels_source, &n);
1284         if (r < 0)
1285                 return r;
1286         if (r == 0)
1287                 return -EINVAL;
1288 
1289         *ret = n;
1290         return 0;
1291 }
1292 
dns_resource_record_is_signer(DnsResourceRecord * rr,const char * zone)1293 int dns_resource_record_is_signer(DnsResourceRecord *rr, const char *zone) {
1294         const char *signer;
1295         int r;
1296 
1297         assert(rr);
1298 
1299         r = dns_resource_record_signer(rr, &signer);
1300         if (r < 0)
1301                 return r;
1302 
1303         return dns_name_equal(zone, signer);
1304 }
1305 
dns_resource_record_is_synthetic(DnsResourceRecord * rr)1306 int dns_resource_record_is_synthetic(DnsResourceRecord *rr) {
1307         int r;
1308 
1309         assert(rr);
1310 
1311         /* Returns > 0 if the RR is generated from a wildcard, and is not the asterisk name itself */
1312 
1313         if (rr->n_skip_labels_source == UINT8_MAX)
1314                 return -ENODATA;
1315 
1316         if (rr->n_skip_labels_source == 0)
1317                 return 0;
1318 
1319         if (rr->n_skip_labels_source > 1)
1320                 return 1;
1321 
1322         r = dns_name_startswith(dns_resource_key_name(rr->key), "*");
1323         if (r < 0)
1324                 return r;
1325 
1326         return !r;
1327 }
1328 
dns_resource_record_hash_func(const DnsResourceRecord * rr,struct siphash * state)1329 void dns_resource_record_hash_func(const DnsResourceRecord *rr, struct siphash *state) {
1330         assert(rr);
1331 
1332         dns_resource_key_hash_func(rr->key, state);
1333 
1334         switch (rr->unparsable ? _DNS_TYPE_INVALID : rr->key->type) {
1335 
1336         case DNS_TYPE_SRV:
1337                 siphash24_compress(&rr->srv.priority, sizeof(rr->srv.priority), state);
1338                 siphash24_compress(&rr->srv.weight, sizeof(rr->srv.weight), state);
1339                 siphash24_compress(&rr->srv.port, sizeof(rr->srv.port), state);
1340                 dns_name_hash_func(rr->srv.name, state);
1341                 break;
1342 
1343         case DNS_TYPE_PTR:
1344         case DNS_TYPE_NS:
1345         case DNS_TYPE_CNAME:
1346         case DNS_TYPE_DNAME:
1347                 dns_name_hash_func(rr->ptr.name, state);
1348                 break;
1349 
1350         case DNS_TYPE_HINFO:
1351                 string_hash_func(rr->hinfo.cpu, state);
1352                 string_hash_func(rr->hinfo.os, state);
1353                 break;
1354 
1355         case DNS_TYPE_TXT:
1356         case DNS_TYPE_SPF: {
1357                 LIST_FOREACH(items, j, rr->txt.items) {
1358                         siphash24_compress_safe(j->data, j->length, state);
1359 
1360                         /* Add an extra NUL byte, so that "a" followed by "b" doesn't result in the same hash as "ab"
1361                          * followed by "". */
1362                         siphash24_compress_byte(0, state);
1363                 }
1364                 break;
1365         }
1366 
1367         case DNS_TYPE_A:
1368                 siphash24_compress(&rr->a.in_addr, sizeof(rr->a.in_addr), state);
1369                 break;
1370 
1371         case DNS_TYPE_AAAA:
1372                 siphash24_compress(&rr->aaaa.in6_addr, sizeof(rr->aaaa.in6_addr), state);
1373                 break;
1374 
1375         case DNS_TYPE_SOA:
1376                 dns_name_hash_func(rr->soa.mname, state);
1377                 dns_name_hash_func(rr->soa.rname, state);
1378                 siphash24_compress(&rr->soa.serial, sizeof(rr->soa.serial), state);
1379                 siphash24_compress(&rr->soa.refresh, sizeof(rr->soa.refresh), state);
1380                 siphash24_compress(&rr->soa.retry, sizeof(rr->soa.retry), state);
1381                 siphash24_compress(&rr->soa.expire, sizeof(rr->soa.expire), state);
1382                 siphash24_compress(&rr->soa.minimum, sizeof(rr->soa.minimum), state);
1383                 break;
1384 
1385         case DNS_TYPE_MX:
1386                 siphash24_compress(&rr->mx.priority, sizeof(rr->mx.priority), state);
1387                 dns_name_hash_func(rr->mx.exchange, state);
1388                 break;
1389 
1390         case DNS_TYPE_LOC:
1391                 siphash24_compress(&rr->loc.version, sizeof(rr->loc.version), state);
1392                 siphash24_compress(&rr->loc.size, sizeof(rr->loc.size), state);
1393                 siphash24_compress(&rr->loc.horiz_pre, sizeof(rr->loc.horiz_pre), state);
1394                 siphash24_compress(&rr->loc.vert_pre, sizeof(rr->loc.vert_pre), state);
1395                 siphash24_compress(&rr->loc.latitude, sizeof(rr->loc.latitude), state);
1396                 siphash24_compress(&rr->loc.longitude, sizeof(rr->loc.longitude), state);
1397                 siphash24_compress(&rr->loc.altitude, sizeof(rr->loc.altitude), state);
1398                 break;
1399 
1400         case DNS_TYPE_SSHFP:
1401                 siphash24_compress(&rr->sshfp.algorithm, sizeof(rr->sshfp.algorithm), state);
1402                 siphash24_compress(&rr->sshfp.fptype, sizeof(rr->sshfp.fptype), state);
1403                 siphash24_compress_safe(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, state);
1404                 break;
1405 
1406         case DNS_TYPE_DNSKEY:
1407                 siphash24_compress(&rr->dnskey.flags, sizeof(rr->dnskey.flags), state);
1408                 siphash24_compress(&rr->dnskey.protocol, sizeof(rr->dnskey.protocol), state);
1409                 siphash24_compress(&rr->dnskey.algorithm, sizeof(rr->dnskey.algorithm), state);
1410                 siphash24_compress_safe(rr->dnskey.key, rr->dnskey.key_size, state);
1411                 break;
1412 
1413         case DNS_TYPE_RRSIG:
1414                 siphash24_compress(&rr->rrsig.type_covered, sizeof(rr->rrsig.type_covered), state);
1415                 siphash24_compress(&rr->rrsig.algorithm, sizeof(rr->rrsig.algorithm), state);
1416                 siphash24_compress(&rr->rrsig.labels, sizeof(rr->rrsig.labels), state);
1417                 siphash24_compress(&rr->rrsig.original_ttl, sizeof(rr->rrsig.original_ttl), state);
1418                 siphash24_compress(&rr->rrsig.expiration, sizeof(rr->rrsig.expiration), state);
1419                 siphash24_compress(&rr->rrsig.inception, sizeof(rr->rrsig.inception), state);
1420                 siphash24_compress(&rr->rrsig.key_tag, sizeof(rr->rrsig.key_tag), state);
1421                 dns_name_hash_func(rr->rrsig.signer, state);
1422                 siphash24_compress_safe(rr->rrsig.signature, rr->rrsig.signature_size, state);
1423                 break;
1424 
1425         case DNS_TYPE_NSEC:
1426                 dns_name_hash_func(rr->nsec.next_domain_name, state);
1427                 /* FIXME: we leave out the type bitmap here. Hash
1428                  * would be better if we'd take it into account
1429                  * too. */
1430                 break;
1431 
1432         case DNS_TYPE_DS:
1433                 siphash24_compress(&rr->ds.key_tag, sizeof(rr->ds.key_tag), state);
1434                 siphash24_compress(&rr->ds.algorithm, sizeof(rr->ds.algorithm), state);
1435                 siphash24_compress(&rr->ds.digest_type, sizeof(rr->ds.digest_type), state);
1436                 siphash24_compress_safe(rr->ds.digest, rr->ds.digest_size, state);
1437                 break;
1438 
1439         case DNS_TYPE_NSEC3:
1440                 siphash24_compress(&rr->nsec3.algorithm, sizeof(rr->nsec3.algorithm), state);
1441                 siphash24_compress(&rr->nsec3.flags, sizeof(rr->nsec3.flags), state);
1442                 siphash24_compress(&rr->nsec3.iterations, sizeof(rr->nsec3.iterations), state);
1443                 siphash24_compress_safe(rr->nsec3.salt, rr->nsec3.salt_size, state);
1444                 siphash24_compress_safe(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, state);
1445                 /* FIXME: We leave the bitmaps out */
1446                 break;
1447 
1448         case DNS_TYPE_TLSA:
1449                 siphash24_compress(&rr->tlsa.cert_usage, sizeof(rr->tlsa.cert_usage), state);
1450                 siphash24_compress(&rr->tlsa.selector, sizeof(rr->tlsa.selector), state);
1451                 siphash24_compress(&rr->tlsa.matching_type, sizeof(rr->tlsa.matching_type), state);
1452                 siphash24_compress_safe(rr->tlsa.data, rr->tlsa.data_size, state);
1453                 break;
1454 
1455         case DNS_TYPE_CAA:
1456                 siphash24_compress(&rr->caa.flags, sizeof(rr->caa.flags), state);
1457                 string_hash_func(rr->caa.tag, state);
1458                 siphash24_compress_safe(rr->caa.value, rr->caa.value_size, state);
1459                 break;
1460 
1461         case DNS_TYPE_OPENPGPKEY:
1462         default:
1463                 siphash24_compress_safe(rr->generic.data, rr->generic.data_size, state);
1464                 break;
1465         }
1466 }
1467 
dns_resource_record_compare_func(const DnsResourceRecord * x,const DnsResourceRecord * y)1468 int dns_resource_record_compare_func(const DnsResourceRecord *x, const DnsResourceRecord *y) {
1469         int r;
1470 
1471         r = dns_resource_key_compare_func(x->key, y->key);
1472         if (r != 0)
1473                 return r;
1474 
1475         if (dns_resource_record_payload_equal(x, y) > 0)
1476                 return 0;
1477 
1478         /* We still use CMP() here, even though don't implement proper
1479          * ordering, since the hashtable doesn't need ordering anyway. */
1480         return CMP(x, y);
1481 }
1482 
1483 DEFINE_HASH_OPS(dns_resource_record_hash_ops, DnsResourceRecord, dns_resource_record_hash_func, dns_resource_record_compare_func);
1484 
dns_resource_record_copy(DnsResourceRecord * rr)1485 DnsResourceRecord *dns_resource_record_copy(DnsResourceRecord *rr) {
1486         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *copy = NULL;
1487         DnsResourceRecord *t;
1488 
1489         assert(rr);
1490 
1491         copy = dns_resource_record_new(rr->key);
1492         if (!copy)
1493                 return NULL;
1494 
1495         copy->ttl = rr->ttl;
1496         copy->expiry = rr->expiry;
1497         copy->n_skip_labels_signer = rr->n_skip_labels_signer;
1498         copy->n_skip_labels_source = rr->n_skip_labels_source;
1499         copy->unparsable = rr->unparsable;
1500 
1501         switch (rr->unparsable ? _DNS_TYPE_INVALID : rr->key->type) {
1502 
1503         case DNS_TYPE_SRV:
1504                 copy->srv.priority = rr->srv.priority;
1505                 copy->srv.weight = rr->srv.weight;
1506                 copy->srv.port = rr->srv.port;
1507                 copy->srv.name = strdup(rr->srv.name);
1508                 if (!copy->srv.name)
1509                         return NULL;
1510                 break;
1511 
1512         case DNS_TYPE_PTR:
1513         case DNS_TYPE_NS:
1514         case DNS_TYPE_CNAME:
1515         case DNS_TYPE_DNAME:
1516                 copy->ptr.name = strdup(rr->ptr.name);
1517                 if (!copy->ptr.name)
1518                         return NULL;
1519                 break;
1520 
1521         case DNS_TYPE_HINFO:
1522                 copy->hinfo.cpu = strdup(rr->hinfo.cpu);
1523                 if (!copy->hinfo.cpu)
1524                         return NULL;
1525 
1526                 copy->hinfo.os = strdup(rr->hinfo.os);
1527                 if (!copy->hinfo.os)
1528                         return NULL;
1529                 break;
1530 
1531         case DNS_TYPE_TXT:
1532         case DNS_TYPE_SPF:
1533                 copy->txt.items = dns_txt_item_copy(rr->txt.items);
1534                 if (!copy->txt.items)
1535                         return NULL;
1536                 break;
1537 
1538         case DNS_TYPE_A:
1539                 copy->a = rr->a;
1540                 break;
1541 
1542         case DNS_TYPE_AAAA:
1543                 copy->aaaa = rr->aaaa;
1544                 break;
1545 
1546         case DNS_TYPE_SOA:
1547                 copy->soa.mname = strdup(rr->soa.mname);
1548                 if (!copy->soa.mname)
1549                         return NULL;
1550                 copy->soa.rname = strdup(rr->soa.rname);
1551                 if (!copy->soa.rname)
1552                         return NULL;
1553                 copy->soa.serial = rr->soa.serial;
1554                 copy->soa.refresh = rr->soa.refresh;
1555                 copy->soa.retry = rr->soa.retry;
1556                 copy->soa.expire = rr->soa.expire;
1557                 copy->soa.minimum = rr->soa.minimum;
1558                 break;
1559 
1560         case DNS_TYPE_MX:
1561                 copy->mx.priority = rr->mx.priority;
1562                 copy->mx.exchange = strdup(rr->mx.exchange);
1563                 if (!copy->mx.exchange)
1564                         return NULL;
1565                 break;
1566 
1567         case DNS_TYPE_LOC:
1568                 copy->loc = rr->loc;
1569                 break;
1570 
1571         case DNS_TYPE_SSHFP:
1572                 copy->sshfp.algorithm = rr->sshfp.algorithm;
1573                 copy->sshfp.fptype = rr->sshfp.fptype;
1574                 copy->sshfp.fingerprint = memdup(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size);
1575                 if (!copy->sshfp.fingerprint)
1576                         return NULL;
1577                 copy->sshfp.fingerprint_size = rr->sshfp.fingerprint_size;
1578                 break;
1579 
1580         case DNS_TYPE_DNSKEY:
1581                 copy->dnskey.flags = rr->dnskey.flags;
1582                 copy->dnskey.protocol = rr->dnskey.protocol;
1583                 copy->dnskey.algorithm = rr->dnskey.algorithm;
1584                 copy->dnskey.key = memdup(rr->dnskey.key, rr->dnskey.key_size);
1585                 if (!copy->dnskey.key)
1586                         return NULL;
1587                 copy->dnskey.key_size = rr->dnskey.key_size;
1588                 break;
1589 
1590         case DNS_TYPE_RRSIG:
1591                 copy->rrsig.type_covered = rr->rrsig.type_covered;
1592                 copy->rrsig.algorithm = rr->rrsig.algorithm;
1593                 copy->rrsig.labels = rr->rrsig.labels;
1594                 copy->rrsig.original_ttl = rr->rrsig.original_ttl;
1595                 copy->rrsig.expiration = rr->rrsig.expiration;
1596                 copy->rrsig.inception = rr->rrsig.inception;
1597                 copy->rrsig.key_tag = rr->rrsig.key_tag;
1598                 copy->rrsig.signer = strdup(rr->rrsig.signer);
1599                 if (!copy->rrsig.signer)
1600                         return NULL;
1601                 copy->rrsig.signature = memdup(rr->rrsig.signature, rr->rrsig.signature_size);
1602                 if (!copy->rrsig.signature)
1603                         return NULL;
1604                 copy->rrsig.signature_size = rr->rrsig.signature_size;
1605                 break;
1606 
1607         case DNS_TYPE_NSEC:
1608                 copy->nsec.next_domain_name = strdup(rr->nsec.next_domain_name);
1609                 if (!copy->nsec.next_domain_name)
1610                         return NULL;
1611                 if (rr->nsec.types) {
1612                         copy->nsec.types = bitmap_copy(rr->nsec.types);
1613                         if (!copy->nsec.types)
1614                                 return NULL;
1615                 }
1616                 break;
1617 
1618         case DNS_TYPE_DS:
1619                 copy->ds.key_tag = rr->ds.key_tag;
1620                 copy->ds.algorithm = rr->ds.algorithm;
1621                 copy->ds.digest_type = rr->ds.digest_type;
1622                 copy->ds.digest = memdup(rr->ds.digest, rr->ds.digest_size);
1623                 if (!copy->ds.digest)
1624                         return NULL;
1625                 copy->ds.digest_size = rr->ds.digest_size;
1626                 break;
1627 
1628         case DNS_TYPE_NSEC3:
1629                 copy->nsec3.algorithm = rr->nsec3.algorithm;
1630                 copy->nsec3.flags = rr->nsec3.flags;
1631                 copy->nsec3.iterations = rr->nsec3.iterations;
1632                 copy->nsec3.salt = memdup(rr->nsec3.salt, rr->nsec3.salt_size);
1633                 if (!copy->nsec3.salt)
1634                         return NULL;
1635                 copy->nsec3.salt_size = rr->nsec3.salt_size;
1636                 copy->nsec3.next_hashed_name = memdup(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size);
1637                 if (!copy->nsec3.next_hashed_name)
1638                         return NULL;
1639                 copy->nsec3.next_hashed_name_size = rr->nsec3.next_hashed_name_size;
1640                 if (rr->nsec3.types) {
1641                         copy->nsec3.types = bitmap_copy(rr->nsec3.types);
1642                         if (!copy->nsec3.types)
1643                                 return NULL;
1644                 }
1645                 break;
1646 
1647         case DNS_TYPE_TLSA:
1648                 copy->tlsa.cert_usage = rr->tlsa.cert_usage;
1649                 copy->tlsa.selector = rr->tlsa.selector;
1650                 copy->tlsa.matching_type = rr->tlsa.matching_type;
1651                 copy->tlsa.data = memdup(rr->tlsa.data, rr->tlsa.data_size);
1652                 if (!copy->tlsa.data)
1653                         return NULL;
1654                 copy->tlsa.data_size = rr->tlsa.data_size;
1655                 break;
1656 
1657         case DNS_TYPE_CAA:
1658                 copy->caa.flags = rr->caa.flags;
1659                 copy->caa.tag = strdup(rr->caa.tag);
1660                 if (!copy->caa.tag)
1661                         return NULL;
1662                 copy->caa.value = memdup(rr->caa.value, rr->caa.value_size);
1663                 if (!copy->caa.value)
1664                         return NULL;
1665                 copy->caa.value_size = rr->caa.value_size;
1666                 break;
1667 
1668         case DNS_TYPE_OPT:
1669         default:
1670                 copy->generic.data = memdup(rr->generic.data, rr->generic.data_size);
1671                 if (!copy->generic.data)
1672                         return NULL;
1673                 copy->generic.data_size = rr->generic.data_size;
1674                 break;
1675         }
1676 
1677         t = TAKE_PTR(copy);
1678 
1679         return t;
1680 }
1681 
dns_resource_record_clamp_ttl(DnsResourceRecord ** rr,uint32_t max_ttl)1682 int dns_resource_record_clamp_ttl(DnsResourceRecord **rr, uint32_t max_ttl) {
1683         DnsResourceRecord *old_rr, *new_rr;
1684         uint32_t new_ttl;
1685 
1686         assert(rr);
1687         old_rr = *rr;
1688 
1689         if (old_rr->key->type == DNS_TYPE_OPT)
1690                 return -EINVAL;
1691 
1692         new_ttl = MIN(old_rr->ttl, max_ttl);
1693         if (new_ttl == old_rr->ttl)
1694                 return 0;
1695 
1696         if (old_rr->n_ref == 1) {
1697                 /* Patch in place */
1698                 old_rr->ttl = new_ttl;
1699                 return 1;
1700         }
1701 
1702         new_rr = dns_resource_record_copy(old_rr);
1703         if (!new_rr)
1704                 return -ENOMEM;
1705 
1706         new_rr->ttl = new_ttl;
1707 
1708         DNS_RR_REPLACE(*rr, new_rr);
1709         return 1;
1710 }
1711 
dns_resource_record_is_link_local_address(DnsResourceRecord * rr)1712 bool dns_resource_record_is_link_local_address(DnsResourceRecord *rr) {
1713         assert(rr);
1714 
1715         if (rr->key->class != DNS_CLASS_IN)
1716                 return false;
1717 
1718         if (rr->key->type == DNS_TYPE_A)
1719                 return in4_addr_is_link_local(&rr->a.in_addr);
1720 
1721         if (rr->key->type == DNS_TYPE_AAAA)
1722                 return in6_addr_is_link_local(&rr->aaaa.in6_addr);
1723 
1724         return false;
1725 }
1726 
dns_resource_record_get_cname_target(DnsResourceKey * key,DnsResourceRecord * cname,char ** ret)1727 int dns_resource_record_get_cname_target(DnsResourceKey *key, DnsResourceRecord *cname, char **ret) {
1728         _cleanup_free_ char *d = NULL;
1729         int r;
1730 
1731         assert(key);
1732         assert(cname);
1733 
1734         /* Checks if the RR `cname` is a CNAME/DNAME RR that matches the specified `key`. If so, returns the
1735          * target domain. If not, returns -EUNATCH */
1736 
1737         if (key->class != cname->key->class && key->class != DNS_CLASS_ANY)
1738                 return -EUNATCH;
1739 
1740         if (!dns_type_may_redirect(key->type)) /* This key type is not subject to CNAME/DNAME redirection?
1741                                                 * Then let's refuse right-away */
1742                 return -EUNATCH;
1743 
1744         if (cname->key->type == DNS_TYPE_CNAME) {
1745                 r = dns_name_equal(dns_resource_key_name(key),
1746                                    dns_resource_key_name(cname->key));
1747                 if (r < 0)
1748                         return r;
1749                 if (r == 0)
1750                         return -EUNATCH; /* CNAME RR key doesn't actually match the original key */
1751 
1752                 d = strdup(cname->cname.name);
1753                 if (!d)
1754                         return -ENOMEM;
1755 
1756         } else if (cname->key->type == DNS_TYPE_DNAME) {
1757 
1758                 r = dns_name_change_suffix(
1759                                 dns_resource_key_name(key),
1760                                 dns_resource_key_name(cname->key),
1761                                 cname->dname.name,
1762                                 &d);
1763                 if (r < 0)
1764                         return r;
1765                 if (r == 0)
1766                         return -EUNATCH; /* DNAME RR key doesn't actually match the original key */
1767 
1768         } else
1769                 return -EUNATCH; /* Not a CNAME/DNAME RR, hence doesn't match the proposition either */
1770 
1771         *ret = TAKE_PTR(d);
1772         return 0;
1773 }
1774 
dns_txt_item_free_all(DnsTxtItem * i)1775 DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i) {
1776         DnsTxtItem *n;
1777 
1778         if (!i)
1779                 return NULL;
1780 
1781         n = i->items_next;
1782 
1783         free(i);
1784         return dns_txt_item_free_all(n);
1785 }
1786 
dns_txt_item_equal(DnsTxtItem * a,DnsTxtItem * b)1787 bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b) {
1788 
1789         if (a == b)
1790                 return true;
1791 
1792         if (!a != !b)
1793                 return false;
1794 
1795         if (!a)
1796                 return true;
1797 
1798         if (a->length != b->length)
1799                 return false;
1800 
1801         if (memcmp(a->data, b->data, a->length) != 0)
1802                 return false;
1803 
1804         return dns_txt_item_equal(a->items_next, b->items_next);
1805 }
1806 
dns_txt_item_copy(DnsTxtItem * first)1807 DnsTxtItem *dns_txt_item_copy(DnsTxtItem *first) {
1808         DnsTxtItem *copy = NULL, *end = NULL;
1809 
1810         LIST_FOREACH(items, i, first) {
1811                 DnsTxtItem *j;
1812 
1813                 j = memdup(i, offsetof(DnsTxtItem, data) + i->length + 1);
1814                 if (!j) {
1815                         dns_txt_item_free_all(copy);
1816                         return NULL;
1817                 }
1818 
1819                 LIST_INSERT_AFTER(items, copy, end, j);
1820                 end = j;
1821         }
1822 
1823         return copy;
1824 }
1825 
dns_txt_item_new_empty(DnsTxtItem ** ret)1826 int dns_txt_item_new_empty(DnsTxtItem **ret) {
1827         DnsTxtItem *i;
1828 
1829         /* RFC 6763, section 6.1 suggests to treat
1830          * empty TXT RRs as equivalent to a TXT record
1831          * with a single empty string. */
1832 
1833         i = malloc0(offsetof(DnsTxtItem, data) + 1); /* for safety reasons we add an extra NUL byte */
1834         if (!i)
1835                 return -ENOMEM;
1836 
1837         *ret = i;
1838 
1839         return 0;
1840 }
1841 
1842 static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
1843         /* Mnemonics as listed on https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
1844         [DNSSEC_ALGORITHM_RSAMD5]             = "RSAMD5",
1845         [DNSSEC_ALGORITHM_DH]                 = "DH",
1846         [DNSSEC_ALGORITHM_DSA]                = "DSA",
1847         [DNSSEC_ALGORITHM_ECC]                = "ECC",
1848         [DNSSEC_ALGORITHM_RSASHA1]            = "RSASHA1",
1849         [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1]     = "DSA-NSEC3-SHA1",
1850         [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1] = "RSASHA1-NSEC3-SHA1",
1851         [DNSSEC_ALGORITHM_RSASHA256]          = "RSASHA256",
1852         [DNSSEC_ALGORITHM_RSASHA512]          = "RSASHA512",
1853         [DNSSEC_ALGORITHM_ECC_GOST]           = "ECC-GOST",
1854         [DNSSEC_ALGORITHM_ECDSAP256SHA256]    = "ECDSAP256SHA256",
1855         [DNSSEC_ALGORITHM_ECDSAP384SHA384]    = "ECDSAP384SHA384",
1856         [DNSSEC_ALGORITHM_ED25519]            = "ED25519",
1857         [DNSSEC_ALGORITHM_ED448]              = "ED448",
1858         [DNSSEC_ALGORITHM_INDIRECT]           = "INDIRECT",
1859         [DNSSEC_ALGORITHM_PRIVATEDNS]         = "PRIVATEDNS",
1860         [DNSSEC_ALGORITHM_PRIVATEOID]         = "PRIVATEOID",
1861 };
1862 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_algorithm, int, 255);
1863 
1864 static const char* const dnssec_digest_table[_DNSSEC_DIGEST_MAX_DEFINED] = {
1865         /* Names as listed on https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
1866         [DNSSEC_DIGEST_SHA1]            = "SHA-1",
1867         [DNSSEC_DIGEST_SHA256]          = "SHA-256",
1868         [DNSSEC_DIGEST_GOST_R_34_11_94] = "GOST_R_34.11-94",
1869         [DNSSEC_DIGEST_SHA384]          = "SHA-384",
1870 };
1871 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_digest, int, 255);
1872