1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 #pragma once
3 
4 #include <netinet/in.h>
5 
6 #include "bitmap.h"
7 #include "dns-def.h"
8 #include "dns-type.h"
9 #include "hashmap.h"
10 #include "in-addr-util.h"
11 #include "list.h"
12 #include "string-util.h"
13 #include "time-util.h"
14 
15 typedef struct DnsResourceKey DnsResourceKey;
16 typedef struct DnsResourceRecord DnsResourceRecord;
17 typedef struct DnsTxtItem DnsTxtItem;
18 
19 /* DNSKEY RR flags */
20 #define DNSKEY_FLAG_SEP            (UINT16_C(1) << 0)
21 #define DNSKEY_FLAG_REVOKE         (UINT16_C(1) << 7)
22 #define DNSKEY_FLAG_ZONE_KEY       (UINT16_C(1) << 8)
23 
24 /* mDNS RR flags */
25 #define MDNS_RR_CACHE_FLUSH_OR_QU  (UINT16_C(1) << 15)
26 
27 /* DNSSEC algorithm identifiers, see
28  * http://tools.ietf.org/html/rfc4034#appendix-A.1 and
29  * https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
30 enum {
31         DNSSEC_ALGORITHM_RSAMD5 = 1,
32         DNSSEC_ALGORITHM_DH,
33         DNSSEC_ALGORITHM_DSA,
34         DNSSEC_ALGORITHM_ECC,
35         DNSSEC_ALGORITHM_RSASHA1,
36         DNSSEC_ALGORITHM_DSA_NSEC3_SHA1,
37         DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1,
38         DNSSEC_ALGORITHM_RSASHA256 = 8,        /* RFC 5702 */
39         DNSSEC_ALGORITHM_RSASHA512 = 10,       /* RFC 5702 */
40         DNSSEC_ALGORITHM_ECC_GOST = 12,        /* RFC 5933 */
41         DNSSEC_ALGORITHM_ECDSAP256SHA256 = 13, /* RFC 6605 */
42         DNSSEC_ALGORITHM_ECDSAP384SHA384 = 14, /* RFC 6605 */
43         DNSSEC_ALGORITHM_ED25519 = 15,         /* RFC 8080 */
44         DNSSEC_ALGORITHM_ED448 = 16,           /* RFC 8080 */
45         DNSSEC_ALGORITHM_INDIRECT = 252,
46         DNSSEC_ALGORITHM_PRIVATEDNS,
47         DNSSEC_ALGORITHM_PRIVATEOID,
48         _DNSSEC_ALGORITHM_MAX_DEFINED
49 };
50 
51 /* DNSSEC digest identifiers, see
52  * https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
53 enum {
54         DNSSEC_DIGEST_SHA1 = 1,
55         DNSSEC_DIGEST_SHA256 = 2,              /* RFC 4509 */
56         DNSSEC_DIGEST_GOST_R_34_11_94 = 3,     /* RFC 5933 */
57         DNSSEC_DIGEST_SHA384 = 4,              /* RFC 6605 */
58         _DNSSEC_DIGEST_MAX_DEFINED
59 };
60 
61 /* DNSSEC NSEC3 hash algorithms, see
62  * https://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml */
63 enum {
64         NSEC3_ALGORITHM_SHA1 = 1,
65         _NSEC3_ALGORITHM_MAX_DEFINED
66 };
67 
68 struct DnsResourceKey {
69         unsigned n_ref; /* (unsigned -1) for const keys, see below */
70         uint16_t class, type;
71         char *_name; /* don't access directly, use dns_resource_key_name()! */
72 };
73 
74 /* Creates a temporary resource key. This is only useful to quickly
75  * look up something, without allocating a full DnsResourceKey object
76  * for it. Note that it is not OK to take references to this kind of
77  * resource key object. */
78 #define DNS_RESOURCE_KEY_CONST(c, t, n)                 \
79         ((DnsResourceKey) {                             \
80                 .n_ref = UINT_MAX,                      \
81                 .class = c,                             \
82                 .type = t,                              \
83                 ._name = (char*) n,                     \
84         })
85 
86 struct DnsTxtItem {
87         size_t length;
88         LIST_FIELDS(DnsTxtItem, items);
89         uint8_t data[];
90 };
91 
92 struct DnsResourceRecord {
93         unsigned n_ref;
94         uint32_t ttl;
95         usec_t expiry; /* RRSIG signature expiry */
96 
97         DnsResourceKey *key;
98 
99         char *to_string;
100 
101         /* How many labels to strip to determine "signer" of the RRSIG (aka, the zone). -1 if not signed. */
102         uint8_t n_skip_labels_signer;
103         /* How many labels to strip to determine "synthesizing source" of this RR, i.e. the wildcard's immediate parent. -1 if not signed. */
104         uint8_t n_skip_labels_source;
105 
106         bool unparsable;
107         bool wire_format_canonical;
108 
109         void *wire_format;
110         size_t wire_format_size;
111         size_t wire_format_rdata_offset;
112 
113         union {
114                 struct {
115                         void *data;
116                         size_t data_size;
117                 } generic, opt;
118 
119                 struct {
120                         char *name;
121                         uint16_t priority;
122                         uint16_t weight;
123                         uint16_t port;
124                 } srv;
125 
126                 struct {
127                         char *name;
128                 } ptr, ns, cname, dname;
129 
130                 struct {
131                         char *cpu;
132                         char *os;
133                 } hinfo;
134 
135                 struct {
136                         DnsTxtItem *items;
137                 } txt, spf;
138 
139                 struct {
140                         struct in_addr in_addr;
141                 } a;
142 
143                 struct {
144                         struct in6_addr in6_addr;
145                 } aaaa;
146 
147                 struct {
148                         char *mname;
149                         char *rname;
150                         uint32_t serial;
151                         uint32_t refresh;
152                         uint32_t retry;
153                         uint32_t expire;
154                         uint32_t minimum;
155                 } soa;
156 
157                 struct {
158                         char *exchange;
159                         uint16_t priority;
160                 } mx;
161 
162                 /* https://tools.ietf.org/html/rfc1876 */
163                 struct {
164                         uint8_t version;
165                         uint8_t size;
166                         uint8_t horiz_pre;
167                         uint8_t vert_pre;
168                         uint32_t latitude;
169                         uint32_t longitude;
170                         uint32_t altitude;
171                 } loc;
172 
173                 /* https://tools.ietf.org/html/rfc4255#section-3.1 */
174                 struct {
175                         void *fingerprint;
176                         size_t fingerprint_size;
177 
178                         uint8_t algorithm;
179                         uint8_t fptype;
180                 } sshfp;
181 
182                 /* http://tools.ietf.org/html/rfc4034#section-2.1 */
183                 struct {
184                         void* key;
185                         size_t key_size;
186 
187                         uint16_t flags;
188                         uint8_t protocol;
189                         uint8_t algorithm;
190                 } dnskey;
191 
192                 /* http://tools.ietf.org/html/rfc4034#section-3.1 */
193                 struct {
194                         char *signer;
195                         void *signature;
196                         size_t signature_size;
197 
198                         uint16_t type_covered;
199                         uint8_t algorithm;
200                         uint8_t labels;
201                         uint32_t original_ttl;
202                         uint32_t expiration;
203                         uint32_t inception;
204                         uint16_t key_tag;
205                 } rrsig;
206 
207                 /* https://tools.ietf.org/html/rfc4034#section-4.1 */
208                 struct {
209                         char *next_domain_name;
210                         Bitmap *types;
211                 } nsec;
212 
213                 /* https://tools.ietf.org/html/rfc4034#section-5.1 */
214                 struct {
215                         void *digest;
216                         size_t digest_size;
217 
218                         uint16_t key_tag;
219                         uint8_t algorithm;
220                         uint8_t digest_type;
221                 } ds;
222 
223                 struct {
224                         Bitmap *types;
225                         void *salt;
226                         size_t salt_size;
227                         void *next_hashed_name;
228                         size_t next_hashed_name_size;
229 
230                         uint8_t algorithm;
231                         uint8_t flags;
232                         uint16_t iterations;
233                 } nsec3;
234 
235                 /* https://tools.ietf.org/html/draft-ietf-dane-protocol-23 */
236                 struct {
237                         void *data;
238                         size_t data_size;
239 
240                         uint8_t cert_usage;
241                         uint8_t selector;
242                         uint8_t matching_type;
243                 } tlsa;
244 
245                 /* https://tools.ietf.org/html/rfc6844 */
246                 struct {
247                         char *tag;
248                         void *value;
249                         size_t value_size;
250 
251                         uint8_t flags;
252                 } caa;
253         };
254 
255         /* Note: fields should be ordered to minimize alignment gaps. Use pahole! */
256 };
257 
258 /* We use uint8_t for label counts above, and UINT8_MAX/-1 has special meaning. */
259 assert_cc(DNS_N_LABELS_MAX < UINT8_MAX);
260 
DNS_RESOURCE_RECORD_RDATA(const DnsResourceRecord * rr)261 static inline const void* DNS_RESOURCE_RECORD_RDATA(const DnsResourceRecord *rr) {
262         if (!rr)
263                 return NULL;
264 
265         if (!rr->wire_format)
266                 return NULL;
267 
268         assert(rr->wire_format_rdata_offset <= rr->wire_format_size);
269         return (uint8_t*) rr->wire_format + rr->wire_format_rdata_offset;
270 }
271 
DNS_RESOURCE_RECORD_RDATA_SIZE(const DnsResourceRecord * rr)272 static inline size_t DNS_RESOURCE_RECORD_RDATA_SIZE(const DnsResourceRecord *rr) {
273         if (!rr)
274                 return 0;
275         if (!rr->wire_format)
276                 return 0;
277 
278         assert(rr->wire_format_rdata_offset <= rr->wire_format_size);
279         return rr->wire_format_size - rr->wire_format_rdata_offset;
280 }
281 
DNS_RESOURCE_RECORD_OPT_VERSION_SUPPORTED(const DnsResourceRecord * rr)282 static inline uint8_t DNS_RESOURCE_RECORD_OPT_VERSION_SUPPORTED(const DnsResourceRecord *rr) {
283         assert(rr);
284         assert(rr->key->type == DNS_TYPE_OPT);
285 
286         return ((rr->ttl >> 16) & 0xFF) == 0;
287 }
288 
289 DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name);
290 DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const DnsResourceRecord *cname);
291 int dns_resource_key_new_append_suffix(DnsResourceKey **ret, DnsResourceKey *key, char *name);
292 DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name);
293 DnsResourceKey* dns_resource_key_ref(DnsResourceKey *key);
294 DnsResourceKey* dns_resource_key_unref(DnsResourceKey *key);
295 
296 #define DNS_RESOURCE_KEY_REPLACE(a, b)          \
297         do {                                    \
298                 typeof(a)* _a = &(a);           \
299                 typeof(b) _b = (b);             \
300                 dns_resource_key_unref(*_a);    \
301                 *_a = _b;                       \
302         } while(0)
303 
304 const char* dns_resource_key_name(const DnsResourceKey *key);
305 bool dns_resource_key_is_address(const DnsResourceKey *key);
306 bool dns_resource_key_is_dnssd_ptr(const DnsResourceKey *key);
307 int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b);
308 int dns_resource_key_match_rr(const DnsResourceKey *key, DnsResourceRecord *rr, const char *search_domain);
309 int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain);
310 int dns_resource_key_match_soa(const DnsResourceKey *key, const DnsResourceKey *soa);
311 
312 /* _DNS_{CLASS,TYPE}_STRING_MAX include one byte for NUL, which we use for space instead below.
313  * DNS_HOSTNAME_MAX does not include the NUL byte, so we need to add 1. */
314 #define DNS_RESOURCE_KEY_STRING_MAX (_DNS_CLASS_STRING_MAX + _DNS_TYPE_STRING_MAX + DNS_HOSTNAME_MAX + 1)
315 
316 char* dns_resource_key_to_string(const DnsResourceKey *key, char *buf, size_t buf_size);
317 ssize_t dns_resource_record_payload(DnsResourceRecord *rr, void **out);
318 
319 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceKey*, dns_resource_key_unref);
320 
dns_key_is_shared(const DnsResourceKey * key)321 static inline bool dns_key_is_shared(const DnsResourceKey *key) {
322         return IN_SET(key->type, DNS_TYPE_PTR);
323 }
324 
325 bool dns_resource_key_reduce(DnsResourceKey **a, DnsResourceKey **b);
326 
327 DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key);
328 DnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name);
329 DnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr);
330 DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr);
331 
332 #define DNS_RR_REPLACE(a, b)                    \
333         do {                                    \
334                 typeof(a)* _a = &(a);           \
335                 typeof(b) _b = (b);             \
336                 dns_resource_record_unref(*_a); \
337                 *_a = _b;                       \
338         } while(0)
339 
340 int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name);
341 int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name);
342 int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b);
343 int dns_resource_record_payload_equal(const DnsResourceRecord *a, const DnsResourceRecord *b);
344 
345 const char* dns_resource_record_to_string(DnsResourceRecord *rr);
346 DnsResourceRecord *dns_resource_record_copy(DnsResourceRecord *rr);
347 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceRecord*, dns_resource_record_unref);
348 
349 int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical);
350 
351 int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret);
352 int dns_resource_record_source(DnsResourceRecord *rr, const char **ret);
353 int dns_resource_record_is_signer(DnsResourceRecord *rr, const char *zone);
354 int dns_resource_record_is_synthetic(DnsResourceRecord *rr);
355 
356 int dns_resource_record_clamp_ttl(DnsResourceRecord **rr, uint32_t max_ttl);
357 
358 bool dns_resource_record_is_link_local_address(DnsResourceRecord *rr);
359 
360 int dns_resource_record_get_cname_target(DnsResourceKey *key, DnsResourceRecord *cname, char **ret);
361 
362 DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i);
363 bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b);
364 DnsTxtItem *dns_txt_item_copy(DnsTxtItem *i);
365 int dns_txt_item_new_empty(DnsTxtItem **ret);
366 
367 void dns_resource_record_hash_func(const DnsResourceRecord *i, struct siphash *state);
368 int dns_resource_record_compare_func(const DnsResourceRecord *x, const DnsResourceRecord *y);
369 
370 extern const struct hash_ops dns_resource_key_hash_ops;
371 extern const struct hash_ops dns_resource_record_hash_ops;
372 
373 int dnssec_algorithm_to_string_alloc(int i, char **ret);
374 int dnssec_algorithm_from_string(const char *s) _pure_;
375 
376 int dnssec_digest_to_string_alloc(int i, char **ret);
377 int dnssec_digest_from_string(const char *s) _pure_;
378