]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-dnssec.c
util: split out memcmp()/memset() related calls into memory-util.[ch]
[thirdparty/systemd.git] / src / resolve / resolved-dns-dnssec.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <stdio_ext.h>
4
5 #if HAVE_GCRYPT
6 #include <gcrypt.h>
7 #endif
8
9 #include "alloc-util.h"
10 #include "dns-domain.h"
11 #include "fd-util.h"
12 #include "fileio.h"
13 #include "gcrypt-util.h"
14 #include "hexdecoct.h"
15 #include "memory-util.h"
16 #include "resolved-dns-dnssec.h"
17 #include "resolved-dns-packet.h"
18 #include "string-table.h"
19
20 #define VERIFY_RRS_MAX 256
21 #define MAX_KEY_SIZE (32*1024)
22
23 /* Permit a maximum clock skew of 1h 10min. This should be enough to deal with DST confusion */
24 #define SKEW_MAX (1*USEC_PER_HOUR + 10*USEC_PER_MINUTE)
25
26 /* Maximum number of NSEC3 iterations we'll do. RFC5155 says 2500 shall be the maximum useful value */
27 #define NSEC3_ITERATIONS_MAX 2500
28
29 /*
30 * The DNSSEC Chain of trust:
31 *
32 * Normal RRs are protected via RRSIG RRs in combination with DNSKEY RRs, all in the same zone
33 * DNSKEY RRs are either protected like normal RRs, or via a DS from a zone "higher" up the tree
34 * DS RRs are protected like normal RRs
35 *
36 * Example chain:
37 * Normal RR → RRSIG/DNSKEY+ → DS → RRSIG/DNSKEY+ → DS → ... → DS → RRSIG/DNSKEY+ → DS
38 */
39
40 uint16_t dnssec_keytag(DnsResourceRecord *dnskey, bool mask_revoke) {
41 const uint8_t *p;
42 uint32_t sum, f;
43 size_t i;
44
45 /* The algorithm from RFC 4034, Appendix B. */
46
47 assert(dnskey);
48 assert(dnskey->key->type == DNS_TYPE_DNSKEY);
49
50 f = (uint32_t) dnskey->dnskey.flags;
51
52 if (mask_revoke)
53 f &= ~DNSKEY_FLAG_REVOKE;
54
55 sum = f + ((((uint32_t) dnskey->dnskey.protocol) << 8) + (uint32_t) dnskey->dnskey.algorithm);
56
57 p = dnskey->dnskey.key;
58
59 for (i = 0; i < dnskey->dnskey.key_size; i++)
60 sum += (i & 1) == 0 ? (uint32_t) p[i] << 8 : (uint32_t) p[i];
61
62 sum += (sum >> 16) & UINT32_C(0xFFFF);
63
64 return sum & UINT32_C(0xFFFF);
65 }
66
67 int dnssec_canonicalize(const char *n, char *buffer, size_t buffer_max) {
68 size_t c = 0;
69 int r;
70
71 /* Converts the specified hostname into DNSSEC canonicalized
72 * form. */
73
74 if (buffer_max < 2)
75 return -ENOBUFS;
76
77 for (;;) {
78 r = dns_label_unescape(&n, buffer, buffer_max, 0);
79 if (r < 0)
80 return r;
81 if (r == 0)
82 break;
83
84 if (buffer_max < (size_t) r + 2)
85 return -ENOBUFS;
86
87 /* The DNSSEC canonical form is not clear on what to
88 * do with dots appearing in labels, the way DNS-SD
89 * does it. Refuse it for now. */
90
91 if (memchr(buffer, '.', r))
92 return -EINVAL;
93
94 ascii_strlower_n(buffer, (size_t) r);
95 buffer[r] = '.';
96
97 buffer += r + 1;
98 c += r + 1;
99
100 buffer_max -= r + 1;
101 }
102
103 if (c <= 0) {
104 /* Not even a single label: this is the root domain name */
105
106 assert(buffer_max > 2);
107 buffer[0] = '.';
108 buffer[1] = 0;
109
110 return 1;
111 }
112
113 return (int) c;
114 }
115
116 #if HAVE_GCRYPT
117
118 static int rr_compare(DnsResourceRecord * const *a, DnsResourceRecord * const *b) {
119 const DnsResourceRecord *x = *a, *y = *b;
120 size_t m;
121 int r;
122
123 /* Let's order the RRs according to RFC 4034, Section 6.3 */
124
125 assert(x);
126 assert(x->wire_format);
127 assert(y);
128 assert(y->wire_format);
129
130 m = MIN(DNS_RESOURCE_RECORD_RDATA_SIZE(x), DNS_RESOURCE_RECORD_RDATA_SIZE(y));
131
132 r = memcmp(DNS_RESOURCE_RECORD_RDATA(x), DNS_RESOURCE_RECORD_RDATA(y), m);
133 if (r != 0)
134 return r;
135
136 return CMP(DNS_RESOURCE_RECORD_RDATA_SIZE(x), DNS_RESOURCE_RECORD_RDATA_SIZE(y));
137 }
138
139 static int dnssec_rsa_verify_raw(
140 const char *hash_algorithm,
141 const void *signature, size_t signature_size,
142 const void *data, size_t data_size,
143 const void *exponent, size_t exponent_size,
144 const void *modulus, size_t modulus_size) {
145
146 gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL;
147 gcry_mpi_t n = NULL, e = NULL, s = NULL;
148 gcry_error_t ge;
149 int r;
150
151 assert(hash_algorithm);
152
153 ge = gcry_mpi_scan(&s, GCRYMPI_FMT_USG, signature, signature_size, NULL);
154 if (ge != 0) {
155 r = -EIO;
156 goto finish;
157 }
158
159 ge = gcry_mpi_scan(&e, GCRYMPI_FMT_USG, exponent, exponent_size, NULL);
160 if (ge != 0) {
161 r = -EIO;
162 goto finish;
163 }
164
165 ge = gcry_mpi_scan(&n, GCRYMPI_FMT_USG, modulus, modulus_size, NULL);
166 if (ge != 0) {
167 r = -EIO;
168 goto finish;
169 }
170
171 ge = gcry_sexp_build(&signature_sexp,
172 NULL,
173 "(sig-val (rsa (s %m)))",
174 s);
175
176 if (ge != 0) {
177 r = -EIO;
178 goto finish;
179 }
180
181 ge = gcry_sexp_build(&data_sexp,
182 NULL,
183 "(data (flags pkcs1) (hash %s %b))",
184 hash_algorithm,
185 (int) data_size,
186 data);
187 if (ge != 0) {
188 r = -EIO;
189 goto finish;
190 }
191
192 ge = gcry_sexp_build(&public_key_sexp,
193 NULL,
194 "(public-key (rsa (n %m) (e %m)))",
195 n,
196 e);
197 if (ge != 0) {
198 r = -EIO;
199 goto finish;
200 }
201
202 ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp);
203 if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE)
204 r = 0;
205 else if (ge != 0) {
206 log_debug("RSA signature check failed: %s", gpg_strerror(ge));
207 r = -EIO;
208 } else
209 r = 1;
210
211 finish:
212 if (e)
213 gcry_mpi_release(e);
214 if (n)
215 gcry_mpi_release(n);
216 if (s)
217 gcry_mpi_release(s);
218
219 if (public_key_sexp)
220 gcry_sexp_release(public_key_sexp);
221 if (signature_sexp)
222 gcry_sexp_release(signature_sexp);
223 if (data_sexp)
224 gcry_sexp_release(data_sexp);
225
226 return r;
227 }
228
229 static int dnssec_rsa_verify(
230 const char *hash_algorithm,
231 const void *hash, size_t hash_size,
232 DnsResourceRecord *rrsig,
233 DnsResourceRecord *dnskey) {
234
235 size_t exponent_size, modulus_size;
236 void *exponent, *modulus;
237
238 assert(hash_algorithm);
239 assert(hash);
240 assert(hash_size > 0);
241 assert(rrsig);
242 assert(dnskey);
243
244 if (*(uint8_t*) dnskey->dnskey.key == 0) {
245 /* exponent is > 255 bytes long */
246
247 exponent = (uint8_t*) dnskey->dnskey.key + 3;
248 exponent_size =
249 ((size_t) (((uint8_t*) dnskey->dnskey.key)[1]) << 8) |
250 ((size_t) ((uint8_t*) dnskey->dnskey.key)[2]);
251
252 if (exponent_size < 256)
253 return -EINVAL;
254
255 if (3 + exponent_size >= dnskey->dnskey.key_size)
256 return -EINVAL;
257
258 modulus = (uint8_t*) dnskey->dnskey.key + 3 + exponent_size;
259 modulus_size = dnskey->dnskey.key_size - 3 - exponent_size;
260
261 } else {
262 /* exponent is <= 255 bytes long */
263
264 exponent = (uint8_t*) dnskey->dnskey.key + 1;
265 exponent_size = (size_t) ((uint8_t*) dnskey->dnskey.key)[0];
266
267 if (exponent_size <= 0)
268 return -EINVAL;
269
270 if (1 + exponent_size >= dnskey->dnskey.key_size)
271 return -EINVAL;
272
273 modulus = (uint8_t*) dnskey->dnskey.key + 1 + exponent_size;
274 modulus_size = dnskey->dnskey.key_size - 1 - exponent_size;
275 }
276
277 return dnssec_rsa_verify_raw(
278 hash_algorithm,
279 rrsig->rrsig.signature, rrsig->rrsig.signature_size,
280 hash, hash_size,
281 exponent, exponent_size,
282 modulus, modulus_size);
283 }
284
285 static int dnssec_ecdsa_verify_raw(
286 const char *hash_algorithm,
287 const char *curve,
288 const void *signature_r, size_t signature_r_size,
289 const void *signature_s, size_t signature_s_size,
290 const void *data, size_t data_size,
291 const void *key, size_t key_size) {
292
293 gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL;
294 gcry_mpi_t q = NULL, r = NULL, s = NULL;
295 gcry_error_t ge;
296 int k;
297
298 assert(hash_algorithm);
299
300 ge = gcry_mpi_scan(&r, GCRYMPI_FMT_USG, signature_r, signature_r_size, NULL);
301 if (ge != 0) {
302 k = -EIO;
303 goto finish;
304 }
305
306 ge = gcry_mpi_scan(&s, GCRYMPI_FMT_USG, signature_s, signature_s_size, NULL);
307 if (ge != 0) {
308 k = -EIO;
309 goto finish;
310 }
311
312 ge = gcry_mpi_scan(&q, GCRYMPI_FMT_USG, key, key_size, NULL);
313 if (ge != 0) {
314 k = -EIO;
315 goto finish;
316 }
317
318 ge = gcry_sexp_build(&signature_sexp,
319 NULL,
320 "(sig-val (ecdsa (r %m) (s %m)))",
321 r,
322 s);
323 if (ge != 0) {
324 k = -EIO;
325 goto finish;
326 }
327
328 ge = gcry_sexp_build(&data_sexp,
329 NULL,
330 "(data (flags rfc6979) (hash %s %b))",
331 hash_algorithm,
332 (int) data_size,
333 data);
334 if (ge != 0) {
335 k = -EIO;
336 goto finish;
337 }
338
339 ge = gcry_sexp_build(&public_key_sexp,
340 NULL,
341 "(public-key (ecc (curve %s) (q %m)))",
342 curve,
343 q);
344 if (ge != 0) {
345 k = -EIO;
346 goto finish;
347 }
348
349 ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp);
350 if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE)
351 k = 0;
352 else if (ge != 0) {
353 log_debug("ECDSA signature check failed: %s", gpg_strerror(ge));
354 k = -EIO;
355 } else
356 k = 1;
357 finish:
358 if (r)
359 gcry_mpi_release(r);
360 if (s)
361 gcry_mpi_release(s);
362 if (q)
363 gcry_mpi_release(q);
364
365 if (public_key_sexp)
366 gcry_sexp_release(public_key_sexp);
367 if (signature_sexp)
368 gcry_sexp_release(signature_sexp);
369 if (data_sexp)
370 gcry_sexp_release(data_sexp);
371
372 return k;
373 }
374
375 static int dnssec_ecdsa_verify(
376 const char *hash_algorithm,
377 int algorithm,
378 const void *hash, size_t hash_size,
379 DnsResourceRecord *rrsig,
380 DnsResourceRecord *dnskey) {
381
382 const char *curve;
383 size_t key_size;
384 uint8_t *q;
385
386 assert(hash);
387 assert(hash_size);
388 assert(rrsig);
389 assert(dnskey);
390
391 if (algorithm == DNSSEC_ALGORITHM_ECDSAP256SHA256) {
392 key_size = 32;
393 curve = "NIST P-256";
394 } else if (algorithm == DNSSEC_ALGORITHM_ECDSAP384SHA384) {
395 key_size = 48;
396 curve = "NIST P-384";
397 } else
398 return -EOPNOTSUPP;
399
400 if (dnskey->dnskey.key_size != key_size * 2)
401 return -EINVAL;
402
403 if (rrsig->rrsig.signature_size != key_size * 2)
404 return -EINVAL;
405
406 q = newa(uint8_t, key_size*2 + 1);
407 q[0] = 0x04; /* Prepend 0x04 to indicate an uncompressed key */
408 memcpy(q+1, dnskey->dnskey.key, key_size*2);
409
410 return dnssec_ecdsa_verify_raw(
411 hash_algorithm,
412 curve,
413 rrsig->rrsig.signature, key_size,
414 (uint8_t*) rrsig->rrsig.signature + key_size, key_size,
415 hash, hash_size,
416 q, key_size*2+1);
417 }
418
419 #if GCRYPT_VERSION_NUMBER >= 0x010600
420 static int dnssec_eddsa_verify_raw(
421 const char *curve,
422 const void *signature_r, size_t signature_r_size,
423 const void *signature_s, size_t signature_s_size,
424 const void *data, size_t data_size,
425 const void *key, size_t key_size) {
426
427 gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL;
428 gcry_error_t ge;
429 int k;
430
431 ge = gcry_sexp_build(&signature_sexp,
432 NULL,
433 "(sig-val (eddsa (r %b) (s %b)))",
434 (int) signature_r_size,
435 signature_r,
436 (int) signature_s_size,
437 signature_s);
438 if (ge != 0) {
439 k = -EIO;
440 goto finish;
441 }
442
443 ge = gcry_sexp_build(&data_sexp,
444 NULL,
445 "(data (flags eddsa) (hash-algo sha512) (value %b))",
446 (int) data_size,
447 data);
448 if (ge != 0) {
449 k = -EIO;
450 goto finish;
451 }
452
453 ge = gcry_sexp_build(&public_key_sexp,
454 NULL,
455 "(public-key (ecc (curve %s) (flags eddsa) (q %b)))",
456 curve,
457 (int) key_size,
458 key);
459 if (ge != 0) {
460 k = -EIO;
461 goto finish;
462 }
463
464 ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp);
465 if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE)
466 k = 0;
467 else if (ge != 0) {
468 log_debug("EdDSA signature check failed: %s", gpg_strerror(ge));
469 k = -EIO;
470 } else
471 k = 1;
472 finish:
473 if (public_key_sexp)
474 gcry_sexp_release(public_key_sexp);
475 if (signature_sexp)
476 gcry_sexp_release(signature_sexp);
477 if (data_sexp)
478 gcry_sexp_release(data_sexp);
479
480 return k;
481 }
482
483 static int dnssec_eddsa_verify(
484 int algorithm,
485 const void *data, size_t data_size,
486 DnsResourceRecord *rrsig,
487 DnsResourceRecord *dnskey) {
488 const char *curve;
489 size_t key_size;
490
491 if (algorithm == DNSSEC_ALGORITHM_ED25519) {
492 curve = "Ed25519";
493 key_size = 32;
494 } else
495 return -EOPNOTSUPP;
496
497 if (dnskey->dnskey.key_size != key_size)
498 return -EINVAL;
499
500 if (rrsig->rrsig.signature_size != key_size * 2)
501 return -EINVAL;
502
503 return dnssec_eddsa_verify_raw(
504 curve,
505 rrsig->rrsig.signature, key_size,
506 (uint8_t*) rrsig->rrsig.signature + key_size, key_size,
507 data, data_size,
508 dnskey->dnskey.key, key_size);
509 }
510 #endif
511
512 static void md_add_uint8(gcry_md_hd_t md, uint8_t v) {
513 gcry_md_write(md, &v, sizeof(v));
514 }
515
516 static void md_add_uint16(gcry_md_hd_t md, uint16_t v) {
517 v = htobe16(v);
518 gcry_md_write(md, &v, sizeof(v));
519 }
520
521 static void fwrite_uint8(FILE *fp, uint8_t v) {
522 fwrite(&v, sizeof(v), 1, fp);
523 }
524
525 static void fwrite_uint16(FILE *fp, uint16_t v) {
526 v = htobe16(v);
527 fwrite(&v, sizeof(v), 1, fp);
528 }
529
530 static void fwrite_uint32(FILE *fp, uint32_t v) {
531 v = htobe32(v);
532 fwrite(&v, sizeof(v), 1, fp);
533 }
534
535 static int dnssec_rrsig_prepare(DnsResourceRecord *rrsig) {
536 int n_key_labels, n_signer_labels;
537 const char *name;
538 int r;
539
540 /* Checks whether the specified RRSIG RR is somewhat valid, and initializes the .n_skip_labels_source and
541 * .n_skip_labels_signer fields so that we can use them later on. */
542
543 assert(rrsig);
544 assert(rrsig->key->type == DNS_TYPE_RRSIG);
545
546 /* Check if this RRSIG RR is already prepared */
547 if (rrsig->n_skip_labels_source != (unsigned) -1)
548 return 0;
549
550 if (rrsig->rrsig.inception > rrsig->rrsig.expiration)
551 return -EINVAL;
552
553 name = dns_resource_key_name(rrsig->key);
554
555 n_key_labels = dns_name_count_labels(name);
556 if (n_key_labels < 0)
557 return n_key_labels;
558 if (rrsig->rrsig.labels > n_key_labels)
559 return -EINVAL;
560
561 n_signer_labels = dns_name_count_labels(rrsig->rrsig.signer);
562 if (n_signer_labels < 0)
563 return n_signer_labels;
564 if (n_signer_labels > rrsig->rrsig.labels)
565 return -EINVAL;
566
567 r = dns_name_skip(name, n_key_labels - n_signer_labels, &name);
568 if (r < 0)
569 return r;
570 if (r == 0)
571 return -EINVAL;
572
573 /* Check if the signer is really a suffix of us */
574 r = dns_name_equal(name, rrsig->rrsig.signer);
575 if (r < 0)
576 return r;
577 if (r == 0)
578 return -EINVAL;
579
580 rrsig->n_skip_labels_source = n_key_labels - rrsig->rrsig.labels;
581 rrsig->n_skip_labels_signer = n_key_labels - n_signer_labels;
582
583 return 0;
584 }
585
586 static int dnssec_rrsig_expired(DnsResourceRecord *rrsig, usec_t realtime) {
587 usec_t expiration, inception, skew;
588
589 assert(rrsig);
590 assert(rrsig->key->type == DNS_TYPE_RRSIG);
591
592 if (realtime == USEC_INFINITY)
593 realtime = now(CLOCK_REALTIME);
594
595 expiration = rrsig->rrsig.expiration * USEC_PER_SEC;
596 inception = rrsig->rrsig.inception * USEC_PER_SEC;
597
598 /* Consider inverted validity intervals as expired */
599 if (inception > expiration)
600 return true;
601
602 /* Permit a certain amount of clock skew of 10% of the valid
603 * time range. This takes inspiration from unbound's
604 * resolver. */
605 skew = (expiration - inception) / 10;
606 if (skew > SKEW_MAX)
607 skew = SKEW_MAX;
608
609 if (inception < skew)
610 inception = 0;
611 else
612 inception -= skew;
613
614 if (expiration + skew < expiration)
615 expiration = USEC_INFINITY;
616 else
617 expiration += skew;
618
619 return realtime < inception || realtime > expiration;
620 }
621
622 static int algorithm_to_gcrypt_md(uint8_t algorithm) {
623
624 /* Translates a DNSSEC signature algorithm into a gcrypt
625 * digest identifier.
626 *
627 * Note that we implement all algorithms listed as "Must
628 * implement" and "Recommended to Implement" in RFC6944. We
629 * don't implement any algorithms that are listed as
630 * "Optional" or "Must Not Implement". Specifically, we do not
631 * implement RSAMD5, DSASHA1, DH, DSA-NSEC3-SHA1, and
632 * GOST-ECC. */
633
634 switch (algorithm) {
635
636 case DNSSEC_ALGORITHM_RSASHA1:
637 case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1:
638 return GCRY_MD_SHA1;
639
640 case DNSSEC_ALGORITHM_RSASHA256:
641 case DNSSEC_ALGORITHM_ECDSAP256SHA256:
642 return GCRY_MD_SHA256;
643
644 case DNSSEC_ALGORITHM_ECDSAP384SHA384:
645 return GCRY_MD_SHA384;
646
647 case DNSSEC_ALGORITHM_RSASHA512:
648 return GCRY_MD_SHA512;
649
650 default:
651 return -EOPNOTSUPP;
652 }
653 }
654
655 static void dnssec_fix_rrset_ttl(
656 DnsResourceRecord *list[],
657 unsigned n,
658 DnsResourceRecord *rrsig,
659 usec_t realtime) {
660
661 unsigned k;
662
663 assert(list);
664 assert(n > 0);
665 assert(rrsig);
666
667 for (k = 0; k < n; k++) {
668 DnsResourceRecord *rr = list[k];
669
670 /* Pick the TTL as the minimum of the RR's TTL, the
671 * RR's original TTL according to the RRSIG and the
672 * RRSIG's own TTL, see RFC 4035, Section 5.3.3 */
673 rr->ttl = MIN3(rr->ttl, rrsig->rrsig.original_ttl, rrsig->ttl);
674 rr->expiry = rrsig->rrsig.expiration * USEC_PER_SEC;
675
676 /* Copy over information about the signer and wildcard source of synthesis */
677 rr->n_skip_labels_source = rrsig->n_skip_labels_source;
678 rr->n_skip_labels_signer = rrsig->n_skip_labels_signer;
679 }
680
681 rrsig->expiry = rrsig->rrsig.expiration * USEC_PER_SEC;
682 }
683
684 int dnssec_verify_rrset(
685 DnsAnswer *a,
686 const DnsResourceKey *key,
687 DnsResourceRecord *rrsig,
688 DnsResourceRecord *dnskey,
689 usec_t realtime,
690 DnssecResult *result) {
691
692 uint8_t wire_format_name[DNS_WIRE_FORMAT_HOSTNAME_MAX];
693 DnsResourceRecord **list, *rr;
694 const char *source, *name;
695 _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
696 int r, md_algorithm;
697 size_t k, n = 0;
698 size_t sig_size = 0;
699 _cleanup_free_ char *sig_data = NULL;
700 _cleanup_fclose_ FILE *f = NULL;
701 size_t hash_size;
702 void *hash;
703 bool wildcard;
704
705 assert(key);
706 assert(rrsig);
707 assert(dnskey);
708 assert(result);
709 assert(rrsig->key->type == DNS_TYPE_RRSIG);
710 assert(dnskey->key->type == DNS_TYPE_DNSKEY);
711
712 /* Verifies that the RRSet matches the specified "key" in "a",
713 * using the signature "rrsig" and the key "dnskey". It's
714 * assumed that RRSIG and DNSKEY match. */
715
716 r = dnssec_rrsig_prepare(rrsig);
717 if (r == -EINVAL) {
718 *result = DNSSEC_INVALID;
719 return r;
720 }
721 if (r < 0)
722 return r;
723
724 r = dnssec_rrsig_expired(rrsig, realtime);
725 if (r < 0)
726 return r;
727 if (r > 0) {
728 *result = DNSSEC_SIGNATURE_EXPIRED;
729 return 0;
730 }
731
732 name = dns_resource_key_name(key);
733
734 /* Some keys may only appear signed in the zone apex, and are invalid anywhere else. (SOA, NS...) */
735 if (dns_type_apex_only(rrsig->rrsig.type_covered)) {
736 r = dns_name_equal(rrsig->rrsig.signer, name);
737 if (r < 0)
738 return r;
739 if (r == 0) {
740 *result = DNSSEC_INVALID;
741 return 0;
742 }
743 }
744
745 /* OTOH DS RRs may not appear in the zone apex, but are valid everywhere else. */
746 if (rrsig->rrsig.type_covered == DNS_TYPE_DS) {
747 r = dns_name_equal(rrsig->rrsig.signer, name);
748 if (r < 0)
749 return r;
750 if (r > 0) {
751 *result = DNSSEC_INVALID;
752 return 0;
753 }
754 }
755
756 /* Determine the "Source of Synthesis" and whether this is a wildcard RRSIG */
757 r = dns_name_suffix(name, rrsig->rrsig.labels, &source);
758 if (r < 0)
759 return r;
760 if (r > 0 && !dns_type_may_wildcard(rrsig->rrsig.type_covered)) {
761 /* We refuse to validate NSEC3 or SOA RRs that are synthesized from wildcards */
762 *result = DNSSEC_INVALID;
763 return 0;
764 }
765 if (r == 1) {
766 /* If we stripped a single label, then let's see if that maybe was "*". If so, we are not really
767 * synthesized from a wildcard, we are the wildcard itself. Treat that like a normal name. */
768 r = dns_name_startswith(name, "*");
769 if (r < 0)
770 return r;
771 if (r > 0)
772 source = name;
773
774 wildcard = r == 0;
775 } else
776 wildcard = r > 0;
777
778 /* Collect all relevant RRs in a single array, so that we can look at the RRset */
779 list = newa(DnsResourceRecord *, dns_answer_size(a));
780
781 DNS_ANSWER_FOREACH(rr, a) {
782 r = dns_resource_key_equal(key, rr->key);
783 if (r < 0)
784 return r;
785 if (r == 0)
786 continue;
787
788 /* We need the wire format for ordering, and digest calculation */
789 r = dns_resource_record_to_wire_format(rr, true);
790 if (r < 0)
791 return r;
792
793 list[n++] = rr;
794
795 if (n > VERIFY_RRS_MAX)
796 return -E2BIG;
797 }
798
799 if (n <= 0)
800 return -ENODATA;
801
802 /* Bring the RRs into canonical order */
803 typesafe_qsort(list, n, rr_compare);
804
805 f = open_memstream(&sig_data, &sig_size);
806 if (!f)
807 return -ENOMEM;
808 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
809
810 fwrite_uint16(f, rrsig->rrsig.type_covered);
811 fwrite_uint8(f, rrsig->rrsig.algorithm);
812 fwrite_uint8(f, rrsig->rrsig.labels);
813 fwrite_uint32(f, rrsig->rrsig.original_ttl);
814 fwrite_uint32(f, rrsig->rrsig.expiration);
815 fwrite_uint32(f, rrsig->rrsig.inception);
816 fwrite_uint16(f, rrsig->rrsig.key_tag);
817
818 r = dns_name_to_wire_format(rrsig->rrsig.signer, wire_format_name, sizeof(wire_format_name), true);
819 if (r < 0)
820 return r;
821 fwrite(wire_format_name, 1, r, f);
822
823 /* Convert the source of synthesis into wire format */
824 r = dns_name_to_wire_format(source, wire_format_name, sizeof(wire_format_name), true);
825 if (r < 0)
826 return r;
827
828 for (k = 0; k < n; k++) {
829 size_t l;
830
831 rr = list[k];
832
833 /* Hash the source of synthesis. If this is a wildcard, then prefix it with the *. label */
834 if (wildcard)
835 fwrite((uint8_t[]) { 1, '*'}, sizeof(uint8_t), 2, f);
836 fwrite(wire_format_name, 1, r, f);
837
838 fwrite_uint16(f, rr->key->type);
839 fwrite_uint16(f, rr->key->class);
840 fwrite_uint32(f, rrsig->rrsig.original_ttl);
841
842 l = DNS_RESOURCE_RECORD_RDATA_SIZE(rr);
843 assert(l <= 0xFFFF);
844
845 fwrite_uint16(f, (uint16_t) l);
846 fwrite(DNS_RESOURCE_RECORD_RDATA(rr), 1, l, f);
847 }
848
849 r = fflush_and_check(f);
850 if (r < 0)
851 return r;
852
853 initialize_libgcrypt(false);
854
855 switch (rrsig->rrsig.algorithm) {
856 #if GCRYPT_VERSION_NUMBER >= 0x010600
857 case DNSSEC_ALGORITHM_ED25519:
858 break;
859 #else
860 case DNSSEC_ALGORITHM_ED25519:
861 #endif
862 case DNSSEC_ALGORITHM_ED448:
863 *result = DNSSEC_UNSUPPORTED_ALGORITHM;
864 return 0;
865 default:
866 /* OK, the RRs are now in canonical order. Let's calculate the digest */
867 md_algorithm = algorithm_to_gcrypt_md(rrsig->rrsig.algorithm);
868 if (md_algorithm == -EOPNOTSUPP) {
869 *result = DNSSEC_UNSUPPORTED_ALGORITHM;
870 return 0;
871 }
872 if (md_algorithm < 0)
873 return md_algorithm;
874
875 gcry_md_open(&md, md_algorithm, 0);
876 if (!md)
877 return -EIO;
878
879 hash_size = gcry_md_get_algo_dlen(md_algorithm);
880 assert(hash_size > 0);
881
882 gcry_md_write(md, sig_data, sig_size);
883
884 hash = gcry_md_read(md, 0);
885 if (!hash)
886 return -EIO;
887 }
888
889 switch (rrsig->rrsig.algorithm) {
890
891 case DNSSEC_ALGORITHM_RSASHA1:
892 case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1:
893 case DNSSEC_ALGORITHM_RSASHA256:
894 case DNSSEC_ALGORITHM_RSASHA512:
895 r = dnssec_rsa_verify(
896 gcry_md_algo_name(md_algorithm),
897 hash, hash_size,
898 rrsig,
899 dnskey);
900 break;
901
902 case DNSSEC_ALGORITHM_ECDSAP256SHA256:
903 case DNSSEC_ALGORITHM_ECDSAP384SHA384:
904 r = dnssec_ecdsa_verify(
905 gcry_md_algo_name(md_algorithm),
906 rrsig->rrsig.algorithm,
907 hash, hash_size,
908 rrsig,
909 dnskey);
910 break;
911 #if GCRYPT_VERSION_NUMBER >= 0x010600
912 case DNSSEC_ALGORITHM_ED25519:
913 r = dnssec_eddsa_verify(
914 rrsig->rrsig.algorithm,
915 sig_data, sig_size,
916 rrsig,
917 dnskey);
918 break;
919 #endif
920 }
921 if (r < 0)
922 return r;
923
924 /* Now, fix the ttl, expiry, and remember the synthesizing source and the signer */
925 if (r > 0)
926 dnssec_fix_rrset_ttl(list, n, rrsig, realtime);
927
928 if (r == 0)
929 *result = DNSSEC_INVALID;
930 else if (wildcard)
931 *result = DNSSEC_VALIDATED_WILDCARD;
932 else
933 *result = DNSSEC_VALIDATED;
934
935 return 0;
936 }
937
938 int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok) {
939
940 assert(rrsig);
941 assert(dnskey);
942
943 /* Checks if the specified DNSKEY RR matches the key used for
944 * the signature in the specified RRSIG RR */
945
946 if (rrsig->key->type != DNS_TYPE_RRSIG)
947 return -EINVAL;
948
949 if (dnskey->key->type != DNS_TYPE_DNSKEY)
950 return 0;
951 if (dnskey->key->class != rrsig->key->class)
952 return 0;
953 if ((dnskey->dnskey.flags & DNSKEY_FLAG_ZONE_KEY) == 0)
954 return 0;
955 if (!revoked_ok && (dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE))
956 return 0;
957 if (dnskey->dnskey.protocol != 3)
958 return 0;
959 if (dnskey->dnskey.algorithm != rrsig->rrsig.algorithm)
960 return 0;
961
962 if (dnssec_keytag(dnskey, false) != rrsig->rrsig.key_tag)
963 return 0;
964
965 return dns_name_equal(dns_resource_key_name(dnskey->key), rrsig->rrsig.signer);
966 }
967
968 int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) {
969 assert(key);
970 assert(rrsig);
971
972 /* Checks if the specified RRSIG RR protects the RRSet of the specified RR key. */
973
974 if (rrsig->key->type != DNS_TYPE_RRSIG)
975 return 0;
976 if (rrsig->key->class != key->class)
977 return 0;
978 if (rrsig->rrsig.type_covered != key->type)
979 return 0;
980
981 return dns_name_equal(dns_resource_key_name(rrsig->key), dns_resource_key_name(key));
982 }
983
984 int dnssec_verify_rrset_search(
985 DnsAnswer *a,
986 const DnsResourceKey *key,
987 DnsAnswer *validated_dnskeys,
988 usec_t realtime,
989 DnssecResult *result,
990 DnsResourceRecord **ret_rrsig) {
991
992 bool found_rrsig = false, found_invalid = false, found_expired_rrsig = false, found_unsupported_algorithm = false;
993 DnsResourceRecord *rrsig;
994 int r;
995
996 assert(key);
997 assert(result);
998
999 /* Verifies all RRs from "a" that match the key "key" against DNSKEYs in "validated_dnskeys" */
1000
1001 if (!a || a->n_rrs <= 0)
1002 return -ENODATA;
1003
1004 /* Iterate through each RRSIG RR. */
1005 DNS_ANSWER_FOREACH(rrsig, a) {
1006 DnsResourceRecord *dnskey;
1007 DnsAnswerFlags flags;
1008
1009 /* Is this an RRSIG RR that applies to RRs matching our key? */
1010 r = dnssec_key_match_rrsig(key, rrsig);
1011 if (r < 0)
1012 return r;
1013 if (r == 0)
1014 continue;
1015
1016 found_rrsig = true;
1017
1018 /* Look for a matching key */
1019 DNS_ANSWER_FOREACH_FLAGS(dnskey, flags, validated_dnskeys) {
1020 DnssecResult one_result;
1021
1022 if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
1023 continue;
1024
1025 /* Is this a DNSKEY RR that matches they key of our RRSIG? */
1026 r = dnssec_rrsig_match_dnskey(rrsig, dnskey, false);
1027 if (r < 0)
1028 return r;
1029 if (r == 0)
1030 continue;
1031
1032 /* Take the time here, if it isn't set yet, so
1033 * that we do all validations with the same
1034 * time. */
1035 if (realtime == USEC_INFINITY)
1036 realtime = now(CLOCK_REALTIME);
1037
1038 /* Yay, we found a matching RRSIG with a matching
1039 * DNSKEY, awesome. Now let's verify all entries of
1040 * the RRSet against the RRSIG and DNSKEY
1041 * combination. */
1042
1043 r = dnssec_verify_rrset(a, key, rrsig, dnskey, realtime, &one_result);
1044 if (r < 0)
1045 return r;
1046
1047 switch (one_result) {
1048
1049 case DNSSEC_VALIDATED:
1050 case DNSSEC_VALIDATED_WILDCARD:
1051 /* Yay, the RR has been validated,
1052 * return immediately, but fix up the expiry */
1053 if (ret_rrsig)
1054 *ret_rrsig = rrsig;
1055
1056 *result = one_result;
1057 return 0;
1058
1059 case DNSSEC_INVALID:
1060 /* If the signature is invalid, let's try another
1061 key and/or signature. After all they
1062 key_tags and stuff are not unique, and
1063 might be shared by multiple keys. */
1064 found_invalid = true;
1065 continue;
1066
1067 case DNSSEC_UNSUPPORTED_ALGORITHM:
1068 /* If the key algorithm is
1069 unsupported, try another
1070 RRSIG/DNSKEY pair, but remember we
1071 encountered this, so that we can
1072 return a proper error when we
1073 encounter nothing better. */
1074 found_unsupported_algorithm = true;
1075 continue;
1076
1077 case DNSSEC_SIGNATURE_EXPIRED:
1078 /* If the signature is expired, try
1079 another one, but remember it, so
1080 that we can return this */
1081 found_expired_rrsig = true;
1082 continue;
1083
1084 default:
1085 assert_not_reached("Unexpected DNSSEC validation result");
1086 }
1087 }
1088 }
1089
1090 if (found_expired_rrsig)
1091 *result = DNSSEC_SIGNATURE_EXPIRED;
1092 else if (found_unsupported_algorithm)
1093 *result = DNSSEC_UNSUPPORTED_ALGORITHM;
1094 else if (found_invalid)
1095 *result = DNSSEC_INVALID;
1096 else if (found_rrsig)
1097 *result = DNSSEC_MISSING_KEY;
1098 else
1099 *result = DNSSEC_NO_SIGNATURE;
1100
1101 if (ret_rrsig)
1102 *ret_rrsig = NULL;
1103
1104 return 0;
1105 }
1106
1107 int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) {
1108 DnsResourceRecord *rr;
1109 int r;
1110
1111 /* Checks whether there's at least one RRSIG in 'a' that proctects RRs of the specified key */
1112
1113 DNS_ANSWER_FOREACH(rr, a) {
1114 r = dnssec_key_match_rrsig(key, rr);
1115 if (r < 0)
1116 return r;
1117 if (r > 0)
1118 return 1;
1119 }
1120
1121 return 0;
1122 }
1123
1124 static int digest_to_gcrypt_md(uint8_t algorithm) {
1125
1126 /* Translates a DNSSEC digest algorithm into a gcrypt digest identifier */
1127
1128 switch (algorithm) {
1129
1130 case DNSSEC_DIGEST_SHA1:
1131 return GCRY_MD_SHA1;
1132
1133 case DNSSEC_DIGEST_SHA256:
1134 return GCRY_MD_SHA256;
1135
1136 case DNSSEC_DIGEST_SHA384:
1137 return GCRY_MD_SHA384;
1138
1139 default:
1140 return -EOPNOTSUPP;
1141 }
1142 }
1143
1144 int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke) {
1145 uint8_t wire_format[DNS_WIRE_FORMAT_HOSTNAME_MAX];
1146 _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
1147 size_t hash_size;
1148 int md_algorithm, r;
1149 void *result;
1150
1151 assert(dnskey);
1152 assert(ds);
1153
1154 /* Implements DNSKEY verification by a DS, according to RFC 4035, section 5.2 */
1155
1156 if (dnskey->key->type != DNS_TYPE_DNSKEY)
1157 return -EINVAL;
1158 if (ds->key->type != DNS_TYPE_DS)
1159 return -EINVAL;
1160 if ((dnskey->dnskey.flags & DNSKEY_FLAG_ZONE_KEY) == 0)
1161 return -EKEYREJECTED;
1162 if (!mask_revoke && (dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE))
1163 return -EKEYREJECTED;
1164 if (dnskey->dnskey.protocol != 3)
1165 return -EKEYREJECTED;
1166
1167 if (dnskey->dnskey.algorithm != ds->ds.algorithm)
1168 return 0;
1169 if (dnssec_keytag(dnskey, mask_revoke) != ds->ds.key_tag)
1170 return 0;
1171
1172 initialize_libgcrypt(false);
1173
1174 md_algorithm = digest_to_gcrypt_md(ds->ds.digest_type);
1175 if (md_algorithm < 0)
1176 return md_algorithm;
1177
1178 hash_size = gcry_md_get_algo_dlen(md_algorithm);
1179 assert(hash_size > 0);
1180
1181 if (ds->ds.digest_size != hash_size)
1182 return 0;
1183
1184 r = dns_name_to_wire_format(dns_resource_key_name(dnskey->key), wire_format, sizeof(wire_format), true);
1185 if (r < 0)
1186 return r;
1187
1188 gcry_md_open(&md, md_algorithm, 0);
1189 if (!md)
1190 return -EIO;
1191
1192 gcry_md_write(md, wire_format, r);
1193 if (mask_revoke)
1194 md_add_uint16(md, dnskey->dnskey.flags & ~DNSKEY_FLAG_REVOKE);
1195 else
1196 md_add_uint16(md, dnskey->dnskey.flags);
1197 md_add_uint8(md, dnskey->dnskey.protocol);
1198 md_add_uint8(md, dnskey->dnskey.algorithm);
1199 gcry_md_write(md, dnskey->dnskey.key, dnskey->dnskey.key_size);
1200
1201 result = gcry_md_read(md, 0);
1202 if (!result)
1203 return -EIO;
1204
1205 return memcmp(result, ds->ds.digest, ds->ds.digest_size) == 0;
1206 }
1207
1208 int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) {
1209 DnsResourceRecord *ds;
1210 DnsAnswerFlags flags;
1211 int r;
1212
1213 assert(dnskey);
1214
1215 if (dnskey->key->type != DNS_TYPE_DNSKEY)
1216 return 0;
1217
1218 DNS_ANSWER_FOREACH_FLAGS(ds, flags, validated_ds) {
1219
1220 if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
1221 continue;
1222
1223 if (ds->key->type != DNS_TYPE_DS)
1224 continue;
1225 if (ds->key->class != dnskey->key->class)
1226 continue;
1227
1228 r = dns_name_equal(dns_resource_key_name(dnskey->key), dns_resource_key_name(ds->key));
1229 if (r < 0)
1230 return r;
1231 if (r == 0)
1232 continue;
1233
1234 r = dnssec_verify_dnskey_by_ds(dnskey, ds, false);
1235 if (IN_SET(r, -EKEYREJECTED, -EOPNOTSUPP))
1236 return 0; /* The DNSKEY is revoked or otherwise invalid, or we don't support the digest algorithm */
1237 if (r < 0)
1238 return r;
1239 if (r > 0)
1240 return 1;
1241 }
1242
1243 return 0;
1244 }
1245
1246 static int nsec3_hash_to_gcrypt_md(uint8_t algorithm) {
1247
1248 /* Translates a DNSSEC NSEC3 hash algorithm into a gcrypt digest identifier */
1249
1250 switch (algorithm) {
1251
1252 case NSEC3_ALGORITHM_SHA1:
1253 return GCRY_MD_SHA1;
1254
1255 default:
1256 return -EOPNOTSUPP;
1257 }
1258 }
1259
1260 int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
1261 uint8_t wire_format[DNS_WIRE_FORMAT_HOSTNAME_MAX];
1262 gcry_md_hd_t md = NULL;
1263 size_t hash_size;
1264 int algorithm;
1265 void *result;
1266 unsigned k;
1267 int r;
1268
1269 assert(nsec3);
1270 assert(name);
1271 assert(ret);
1272
1273 if (nsec3->key->type != DNS_TYPE_NSEC3)
1274 return -EINVAL;
1275
1276 if (nsec3->nsec3.iterations > NSEC3_ITERATIONS_MAX)
1277 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1278 "Ignoring NSEC3 RR %s with excessive number of iterations.",
1279 dns_resource_record_to_string(nsec3));
1280
1281 algorithm = nsec3_hash_to_gcrypt_md(nsec3->nsec3.algorithm);
1282 if (algorithm < 0)
1283 return algorithm;
1284
1285 initialize_libgcrypt(false);
1286
1287 hash_size = gcry_md_get_algo_dlen(algorithm);
1288 assert(hash_size > 0);
1289
1290 if (nsec3->nsec3.next_hashed_name_size != hash_size)
1291 return -EINVAL;
1292
1293 r = dns_name_to_wire_format(name, wire_format, sizeof(wire_format), true);
1294 if (r < 0)
1295 return r;
1296
1297 gcry_md_open(&md, algorithm, 0);
1298 if (!md)
1299 return -EIO;
1300
1301 gcry_md_write(md, wire_format, r);
1302 gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
1303
1304 result = gcry_md_read(md, 0);
1305 if (!result) {
1306 r = -EIO;
1307 goto finish;
1308 }
1309
1310 for (k = 0; k < nsec3->nsec3.iterations; k++) {
1311 uint8_t tmp[hash_size];
1312 memcpy(tmp, result, hash_size);
1313
1314 gcry_md_reset(md);
1315 gcry_md_write(md, tmp, hash_size);
1316 gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
1317
1318 result = gcry_md_read(md, 0);
1319 if (!result) {
1320 r = -EIO;
1321 goto finish;
1322 }
1323 }
1324
1325 memcpy(ret, result, hash_size);
1326 r = (int) hash_size;
1327
1328 finish:
1329 gcry_md_close(md);
1330 return r;
1331 }
1332
1333 static int nsec3_is_good(DnsResourceRecord *rr, DnsResourceRecord *nsec3) {
1334 const char *a, *b;
1335 int r;
1336
1337 assert(rr);
1338
1339 if (rr->key->type != DNS_TYPE_NSEC3)
1340 return 0;
1341
1342 /* RFC 5155, Section 8.2 says we MUST ignore NSEC3 RRs with flags != 0 or 1 */
1343 if (!IN_SET(rr->nsec3.flags, 0, 1))
1344 return 0;
1345
1346 /* Ignore NSEC3 RRs whose algorithm we don't know */
1347 if (nsec3_hash_to_gcrypt_md(rr->nsec3.algorithm) < 0)
1348 return 0;
1349 /* Ignore NSEC3 RRs with an excessive number of required iterations */
1350 if (rr->nsec3.iterations > NSEC3_ITERATIONS_MAX)
1351 return 0;
1352
1353 /* Ignore NSEC3 RRs generated from wildcards. If these NSEC3 RRs weren't correctly signed we can't make this
1354 * check (since rr->n_skip_labels_source is -1), but that's OK, as we won't trust them anyway in that case. */
1355 if (!IN_SET(rr->n_skip_labels_source, 0, (unsigned) -1))
1356 return 0;
1357 /* Ignore NSEC3 RRs that are located anywhere else than one label below the zone */
1358 if (!IN_SET(rr->n_skip_labels_signer, 1, (unsigned) -1))
1359 return 0;
1360
1361 if (!nsec3)
1362 return 1;
1363
1364 /* If a second NSEC3 RR is specified, also check if they are from the same zone. */
1365
1366 if (nsec3 == rr) /* Shortcut */
1367 return 1;
1368
1369 if (rr->key->class != nsec3->key->class)
1370 return 0;
1371 if (rr->nsec3.algorithm != nsec3->nsec3.algorithm)
1372 return 0;
1373 if (rr->nsec3.iterations != nsec3->nsec3.iterations)
1374 return 0;
1375 if (rr->nsec3.salt_size != nsec3->nsec3.salt_size)
1376 return 0;
1377 if (memcmp_safe(rr->nsec3.salt, nsec3->nsec3.salt, rr->nsec3.salt_size) != 0)
1378 return 0;
1379
1380 a = dns_resource_key_name(rr->key);
1381 r = dns_name_parent(&a); /* strip off hash */
1382 if (r <= 0)
1383 return r;
1384
1385 b = dns_resource_key_name(nsec3->key);
1386 r = dns_name_parent(&b); /* strip off hash */
1387 if (r <= 0)
1388 return r;
1389
1390 /* Make sure both have the same parent */
1391 return dns_name_equal(a, b);
1392 }
1393
1394 static int nsec3_hashed_domain_format(const uint8_t *hashed, size_t hashed_size, const char *zone, char **ret) {
1395 _cleanup_free_ char *l = NULL;
1396 char *j;
1397
1398 assert(hashed);
1399 assert(hashed_size > 0);
1400 assert(zone);
1401 assert(ret);
1402
1403 l = base32hexmem(hashed, hashed_size, false);
1404 if (!l)
1405 return -ENOMEM;
1406
1407 j = strjoin(l, ".", zone);
1408 if (!j)
1409 return -ENOMEM;
1410
1411 *ret = j;
1412 return (int) hashed_size;
1413 }
1414
1415 static int nsec3_hashed_domain_make(DnsResourceRecord *nsec3, const char *domain, const char *zone, char **ret) {
1416 uint8_t hashed[DNSSEC_HASH_SIZE_MAX];
1417 int hashed_size;
1418
1419 assert(nsec3);
1420 assert(domain);
1421 assert(zone);
1422 assert(ret);
1423
1424 hashed_size = dnssec_nsec3_hash(nsec3, domain, hashed);
1425 if (hashed_size < 0)
1426 return hashed_size;
1427
1428 return nsec3_hashed_domain_format(hashed, (size_t) hashed_size, zone, ret);
1429 }
1430
1431 /* See RFC 5155, Section 8
1432 * First try to find a NSEC3 record that matches our query precisely, if that fails, find the closest
1433 * enclosure. Secondly, find a proof that there is no closer enclosure and either a proof that there
1434 * is no wildcard domain as a direct descendant of the closest enclosure, or find an NSEC3 record that
1435 * matches the wildcard domain.
1436 *
1437 * Based on this we can prove either the existence of the record in @key, or NXDOMAIN or NODATA, or
1438 * that there is no proof either way. The latter is the case if a the proof of non-existence of a given
1439 * name uses an NSEC3 record with the opt-out bit set. Lastly, if we are given insufficient NSEC3 records
1440 * to conclude anything we indicate this by returning NO_RR. */
1441 static int dnssec_test_nsec3(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) {
1442 _cleanup_free_ char *next_closer_domain = NULL, *wildcard_domain = NULL;
1443 const char *zone, *p, *pp = NULL, *wildcard;
1444 DnsResourceRecord *rr, *enclosure_rr, *zone_rr, *wildcard_rr = NULL;
1445 DnsAnswerFlags flags;
1446 int hashed_size, r;
1447 bool a, no_closer = false, no_wildcard = false, optout = false;
1448
1449 assert(key);
1450 assert(result);
1451
1452 /* First step, find the zone name and the NSEC3 parameters of the zone.
1453 * it is sufficient to look for the longest common suffix we find with
1454 * any NSEC3 RR in the response. Any NSEC3 record will do as all NSEC3
1455 * records from a given zone in a response must use the same
1456 * parameters. */
1457 zone = dns_resource_key_name(key);
1458 for (;;) {
1459 DNS_ANSWER_FOREACH_FLAGS(zone_rr, flags, answer) {
1460 r = nsec3_is_good(zone_rr, NULL);
1461 if (r < 0)
1462 return r;
1463 if (r == 0)
1464 continue;
1465
1466 r = dns_name_equal_skip(dns_resource_key_name(zone_rr->key), 1, zone);
1467 if (r < 0)
1468 return r;
1469 if (r > 0)
1470 goto found_zone;
1471 }
1472
1473 /* Strip one label from the front */
1474 r = dns_name_parent(&zone);
1475 if (r < 0)
1476 return r;
1477 if (r == 0)
1478 break;
1479 }
1480
1481 *result = DNSSEC_NSEC_NO_RR;
1482 return 0;
1483
1484 found_zone:
1485 /* Second step, find the closest encloser NSEC3 RR in 'answer' that matches 'key' */
1486 p = dns_resource_key_name(key);
1487 for (;;) {
1488 _cleanup_free_ char *hashed_domain = NULL;
1489
1490 hashed_size = nsec3_hashed_domain_make(zone_rr, p, zone, &hashed_domain);
1491 if (hashed_size == -EOPNOTSUPP) {
1492 *result = DNSSEC_NSEC_UNSUPPORTED_ALGORITHM;
1493 return 0;
1494 }
1495 if (hashed_size < 0)
1496 return hashed_size;
1497
1498 DNS_ANSWER_FOREACH_FLAGS(enclosure_rr, flags, answer) {
1499
1500 r = nsec3_is_good(enclosure_rr, zone_rr);
1501 if (r < 0)
1502 return r;
1503 if (r == 0)
1504 continue;
1505
1506 if (enclosure_rr->nsec3.next_hashed_name_size != (size_t) hashed_size)
1507 continue;
1508
1509 r = dns_name_equal(dns_resource_key_name(enclosure_rr->key), hashed_domain);
1510 if (r < 0)
1511 return r;
1512 if (r > 0) {
1513 a = flags & DNS_ANSWER_AUTHENTICATED;
1514 goto found_closest_encloser;
1515 }
1516 }
1517
1518 /* We didn't find the closest encloser with this name,
1519 * but let's remember this domain name, it might be
1520 * the next closer name */
1521
1522 pp = p;
1523
1524 /* Strip one label from the front */
1525 r = dns_name_parent(&p);
1526 if (r < 0)
1527 return r;
1528 if (r == 0)
1529 break;
1530 }
1531
1532 *result = DNSSEC_NSEC_NO_RR;
1533 return 0;
1534
1535 found_closest_encloser:
1536 /* We found a closest encloser in 'p'; next closer is 'pp' */
1537
1538 if (!pp) {
1539 /* We have an exact match! If we area looking for a DS RR, then we must insist that we got the NSEC3 RR
1540 * from the parent. Otherwise the one from the child. Do so, by checking whether SOA and NS are
1541 * appropriately set. */
1542
1543 if (key->type == DNS_TYPE_DS) {
1544 if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA))
1545 return -EBADMSG;
1546 } else {
1547 if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_NS) &&
1548 !bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA))
1549 return -EBADMSG;
1550 }
1551
1552 /* No next closer NSEC3 RR. That means there's a direct NSEC3 RR for our key. */
1553 if (bitmap_isset(enclosure_rr->nsec3.types, key->type))
1554 *result = DNSSEC_NSEC_FOUND;
1555 else if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_CNAME))
1556 *result = DNSSEC_NSEC_CNAME;
1557 else
1558 *result = DNSSEC_NSEC_NODATA;
1559
1560 if (authenticated)
1561 *authenticated = a;
1562 if (ttl)
1563 *ttl = enclosure_rr->ttl;
1564
1565 return 0;
1566 }
1567
1568 /* Ensure this is not a DNAME domain, see RFC5155, section 8.3. */
1569 if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_DNAME))
1570 return -EBADMSG;
1571
1572 /* Ensure that this data is from the delegated domain
1573 * (i.e. originates from the "lower" DNS server), and isn't
1574 * just glue records (i.e. doesn't originate from the "upper"
1575 * DNS server). */
1576 if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_NS) &&
1577 !bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA))
1578 return -EBADMSG;
1579
1580 /* Prove that there is no next closer and whether or not there is a wildcard domain. */
1581
1582 wildcard = strjoina("*.", p);
1583 r = nsec3_hashed_domain_make(enclosure_rr, wildcard, zone, &wildcard_domain);
1584 if (r < 0)
1585 return r;
1586 if (r != hashed_size)
1587 return -EBADMSG;
1588
1589 r = nsec3_hashed_domain_make(enclosure_rr, pp, zone, &next_closer_domain);
1590 if (r < 0)
1591 return r;
1592 if (r != hashed_size)
1593 return -EBADMSG;
1594
1595 DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
1596 _cleanup_free_ char *next_hashed_domain = NULL;
1597
1598 r = nsec3_is_good(rr, zone_rr);
1599 if (r < 0)
1600 return r;
1601 if (r == 0)
1602 continue;
1603
1604 r = nsec3_hashed_domain_format(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, zone, &next_hashed_domain);
1605 if (r < 0)
1606 return r;
1607
1608 r = dns_name_between(dns_resource_key_name(rr->key), next_closer_domain, next_hashed_domain);
1609 if (r < 0)
1610 return r;
1611 if (r > 0) {
1612 if (rr->nsec3.flags & 1)
1613 optout = true;
1614
1615 a = a && (flags & DNS_ANSWER_AUTHENTICATED);
1616
1617 no_closer = true;
1618 }
1619
1620 r = dns_name_equal(dns_resource_key_name(rr->key), wildcard_domain);
1621 if (r < 0)
1622 return r;
1623 if (r > 0) {
1624 a = a && (flags & DNS_ANSWER_AUTHENTICATED);
1625
1626 wildcard_rr = rr;
1627 }
1628
1629 r = dns_name_between(dns_resource_key_name(rr->key), wildcard_domain, next_hashed_domain);
1630 if (r < 0)
1631 return r;
1632 if (r > 0) {
1633 if (rr->nsec3.flags & 1)
1634 /* This only makes sense if we have a wildcard delegation, which is
1635 * very unlikely, see RFC 4592, Section 4.2, but we cannot rely on
1636 * this not happening, so hence cannot simply conclude NXDOMAIN as
1637 * we would wish */
1638 optout = true;
1639
1640 a = a && (flags & DNS_ANSWER_AUTHENTICATED);
1641
1642 no_wildcard = true;
1643 }
1644 }
1645
1646 if (wildcard_rr && no_wildcard)
1647 return -EBADMSG;
1648
1649 if (!no_closer) {
1650 *result = DNSSEC_NSEC_NO_RR;
1651 return 0;
1652 }
1653
1654 if (wildcard_rr) {
1655 /* A wildcard exists that matches our query. */
1656 if (optout)
1657 /* This is not specified in any RFC to the best of my knowledge, but
1658 * if the next closer enclosure is covered by an opt-out NSEC3 RR
1659 * it means that we cannot prove that the source of synthesis is
1660 * correct, as there may be a closer match. */
1661 *result = DNSSEC_NSEC_OPTOUT;
1662 else if (bitmap_isset(wildcard_rr->nsec3.types, key->type))
1663 *result = DNSSEC_NSEC_FOUND;
1664 else if (bitmap_isset(wildcard_rr->nsec3.types, DNS_TYPE_CNAME))
1665 *result = DNSSEC_NSEC_CNAME;
1666 else
1667 *result = DNSSEC_NSEC_NODATA;
1668 } else {
1669 if (optout)
1670 /* The RFC only specifies that we have to care for optout for NODATA for
1671 * DS records. However, children of an insecure opt-out delegation should
1672 * also be considered opt-out, rather than verified NXDOMAIN.
1673 * Note that we do not require a proof of wildcard non-existence if the
1674 * next closer domain is covered by an opt-out, as that would not provide
1675 * any additional information. */
1676 *result = DNSSEC_NSEC_OPTOUT;
1677 else if (no_wildcard)
1678 *result = DNSSEC_NSEC_NXDOMAIN;
1679 else {
1680 *result = DNSSEC_NSEC_NO_RR;
1681
1682 return 0;
1683 }
1684 }
1685
1686 if (authenticated)
1687 *authenticated = a;
1688
1689 if (ttl)
1690 *ttl = enclosure_rr->ttl;
1691
1692 return 0;
1693 }
1694
1695 static int dnssec_nsec_wildcard_equal(DnsResourceRecord *rr, const char *name) {
1696 char label[DNS_LABEL_MAX];
1697 const char *n;
1698 int r;
1699
1700 assert(rr);
1701 assert(rr->key->type == DNS_TYPE_NSEC);
1702
1703 /* Checks whether the specified RR has a name beginning in "*.", and if the rest is a suffix of our name */
1704
1705 if (rr->n_skip_labels_source != 1)
1706 return 0;
1707
1708 n = dns_resource_key_name(rr->key);
1709 r = dns_label_unescape(&n, label, sizeof label, 0);
1710 if (r <= 0)
1711 return r;
1712 if (r != 1 || label[0] != '*')
1713 return 0;
1714
1715 return dns_name_endswith(name, n);
1716 }
1717
1718 static int dnssec_nsec_in_path(DnsResourceRecord *rr, const char *name) {
1719 const char *nn, *common_suffix;
1720 int r;
1721
1722 assert(rr);
1723 assert(rr->key->type == DNS_TYPE_NSEC);
1724
1725 /* Checks whether the specified nsec RR indicates that name is an empty non-terminal (ENT)
1726 *
1727 * A couple of examples:
1728 *
1729 * NSEC bar → waldo.foo.bar: indicates that foo.bar exists and is an ENT
1730 * NSEC waldo.foo.bar → yyy.zzz.xoo.bar: indicates that xoo.bar and zzz.xoo.bar exist and are ENTs
1731 * NSEC yyy.zzz.xoo.bar → bar: indicates pretty much nothing about ENTs
1732 */
1733
1734 /* First, determine parent of next domain. */
1735 nn = rr->nsec.next_domain_name;
1736 r = dns_name_parent(&nn);
1737 if (r <= 0)
1738 return r;
1739
1740 /* If the name we just determined is not equal or child of the name we are interested in, then we can't say
1741 * anything at all. */
1742 r = dns_name_endswith(nn, name);
1743 if (r <= 0)
1744 return r;
1745
1746 /* If the name we are interested in is not a prefix of the common suffix of the NSEC RR's owner and next domain names, then we can't say anything either. */
1747 r = dns_name_common_suffix(dns_resource_key_name(rr->key), rr->nsec.next_domain_name, &common_suffix);
1748 if (r < 0)
1749 return r;
1750
1751 return dns_name_endswith(name, common_suffix);
1752 }
1753
1754 static int dnssec_nsec_from_parent_zone(DnsResourceRecord *rr, const char *name) {
1755 int r;
1756
1757 assert(rr);
1758 assert(rr->key->type == DNS_TYPE_NSEC);
1759
1760 /* Checks whether this NSEC originates to the parent zone or the child zone. */
1761
1762 r = dns_name_parent(&name);
1763 if (r <= 0)
1764 return r;
1765
1766 r = dns_name_equal(name, dns_resource_key_name(rr->key));
1767 if (r <= 0)
1768 return r;
1769
1770 /* DNAME, and NS without SOA is an indication for a delegation. */
1771 if (bitmap_isset(rr->nsec.types, DNS_TYPE_DNAME))
1772 return 1;
1773
1774 if (bitmap_isset(rr->nsec.types, DNS_TYPE_NS) && !bitmap_isset(rr->nsec.types, DNS_TYPE_SOA))
1775 return 1;
1776
1777 return 0;
1778 }
1779
1780 static int dnssec_nsec_covers(DnsResourceRecord *rr, const char *name) {
1781 const char *signer;
1782 int r;
1783
1784 assert(rr);
1785 assert(rr->key->type == DNS_TYPE_NSEC);
1786
1787 /* Checks whether the name is covered by this NSEC RR. This means, that the name is somewhere below the NSEC's
1788 * signer name, and between the NSEC's two names. */
1789
1790 r = dns_resource_record_signer(rr, &signer);
1791 if (r < 0)
1792 return r;
1793
1794 r = dns_name_endswith(name, signer); /* this NSEC isn't suitable the name is not in the signer's domain */
1795 if (r <= 0)
1796 return r;
1797
1798 return dns_name_between(dns_resource_key_name(rr->key), name, rr->nsec.next_domain_name);
1799 }
1800
1801 static int dnssec_nsec_generate_wildcard(DnsResourceRecord *rr, const char *name, char **wc) {
1802 const char *common_suffix1, *common_suffix2, *signer;
1803 int r, labels1, labels2;
1804
1805 assert(rr);
1806 assert(rr->key->type == DNS_TYPE_NSEC);
1807
1808 /* Generates "Wildcard at the Closest Encloser" for the given name and NSEC RR. */
1809
1810 r = dns_resource_record_signer(rr, &signer);
1811 if (r < 0)
1812 return r;
1813
1814 r = dns_name_endswith(name, signer); /* this NSEC isn't suitable the name is not in the signer's domain */
1815 if (r <= 0)
1816 return r;
1817
1818 r = dns_name_common_suffix(name, dns_resource_key_name(rr->key), &common_suffix1);
1819 if (r < 0)
1820 return r;
1821
1822 r = dns_name_common_suffix(name, rr->nsec.next_domain_name, &common_suffix2);
1823 if (r < 0)
1824 return r;
1825
1826 labels1 = dns_name_count_labels(common_suffix1);
1827 if (labels1 < 0)
1828 return labels1;
1829
1830 labels2 = dns_name_count_labels(common_suffix2);
1831 if (labels2 < 0)
1832 return labels2;
1833
1834 if (labels1 > labels2)
1835 r = dns_name_concat("*", common_suffix1, 0, wc);
1836 else
1837 r = dns_name_concat("*", common_suffix2, 0, wc);
1838
1839 if (r < 0)
1840 return r;
1841
1842 return 0;
1843 }
1844
1845 int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) {
1846 bool have_nsec3 = false, covering_rr_authenticated = false, wildcard_rr_authenticated = false;
1847 DnsResourceRecord *rr, *covering_rr = NULL, *wildcard_rr = NULL;
1848 DnsAnswerFlags flags;
1849 const char *name;
1850 int r;
1851
1852 assert(key);
1853 assert(result);
1854
1855 /* Look for any NSEC/NSEC3 RRs that say something about the specified key. */
1856
1857 name = dns_resource_key_name(key);
1858
1859 DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
1860
1861 if (rr->key->class != key->class)
1862 continue;
1863
1864 have_nsec3 = have_nsec3 || (rr->key->type == DNS_TYPE_NSEC3);
1865
1866 if (rr->key->type != DNS_TYPE_NSEC)
1867 continue;
1868
1869 /* The following checks only make sense for NSEC RRs that are not expanded from a wildcard */
1870 r = dns_resource_record_is_synthetic(rr);
1871 if (r < 0)
1872 return r;
1873 if (r > 0)
1874 continue;
1875
1876 /* Check if this is a direct match. If so, we have encountered a NODATA case */
1877 r = dns_name_equal(dns_resource_key_name(rr->key), name);
1878 if (r < 0)
1879 return r;
1880 if (r == 0) {
1881 /* If it's not a direct match, maybe it's a wild card match? */
1882 r = dnssec_nsec_wildcard_equal(rr, name);
1883 if (r < 0)
1884 return r;
1885 }
1886 if (r > 0) {
1887 if (key->type == DNS_TYPE_DS) {
1888 /* If we look for a DS RR and the server sent us the NSEC RR of the child zone
1889 * we have a problem. For DS RRs we want the NSEC RR from the parent */
1890 if (bitmap_isset(rr->nsec.types, DNS_TYPE_SOA))
1891 continue;
1892 } else {
1893 /* For all RR types, ensure that if NS is set SOA is set too, so that we know
1894 * we got the child's NSEC. */
1895 if (bitmap_isset(rr->nsec.types, DNS_TYPE_NS) &&
1896 !bitmap_isset(rr->nsec.types, DNS_TYPE_SOA))
1897 continue;
1898 }
1899
1900 if (bitmap_isset(rr->nsec.types, key->type))
1901 *result = DNSSEC_NSEC_FOUND;
1902 else if (bitmap_isset(rr->nsec.types, DNS_TYPE_CNAME))
1903 *result = DNSSEC_NSEC_CNAME;
1904 else
1905 *result = DNSSEC_NSEC_NODATA;
1906
1907 if (authenticated)
1908 *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
1909 if (ttl)
1910 *ttl = rr->ttl;
1911
1912 return 0;
1913 }
1914
1915 /* Check if the name we are looking for is an empty non-terminal within the owner or next name
1916 * of the NSEC RR. */
1917 r = dnssec_nsec_in_path(rr, name);
1918 if (r < 0)
1919 return r;
1920 if (r > 0) {
1921 *result = DNSSEC_NSEC_NODATA;
1922
1923 if (authenticated)
1924 *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
1925 if (ttl)
1926 *ttl = rr->ttl;
1927
1928 return 0;
1929 }
1930
1931 /* The following two "covering" checks, are not useful if the NSEC is from the parent */
1932 r = dnssec_nsec_from_parent_zone(rr, name);
1933 if (r < 0)
1934 return r;
1935 if (r > 0)
1936 continue;
1937
1938 /* Check if this NSEC RR proves the absence of an explicit RR under this name */
1939 r = dnssec_nsec_covers(rr, name);
1940 if (r < 0)
1941 return r;
1942 if (r > 0 && (!covering_rr || !covering_rr_authenticated)) {
1943 covering_rr = rr;
1944 covering_rr_authenticated = flags & DNS_ANSWER_AUTHENTICATED;
1945 }
1946 }
1947
1948 if (covering_rr) {
1949 _cleanup_free_ char *wc = NULL;
1950 r = dnssec_nsec_generate_wildcard(covering_rr, name, &wc);
1951 if (r < 0)
1952 return r;
1953
1954 DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
1955
1956 if (rr->key->class != key->class)
1957 continue;
1958
1959 if (rr->key->type != DNS_TYPE_NSEC)
1960 continue;
1961
1962 /* Check if this NSEC RR proves the nonexistence of the wildcard */
1963 r = dnssec_nsec_covers(rr, wc);
1964 if (r < 0)
1965 return r;
1966 if (r > 0 && (!wildcard_rr || !wildcard_rr_authenticated)) {
1967 wildcard_rr = rr;
1968 wildcard_rr_authenticated = flags & DNS_ANSWER_AUTHENTICATED;
1969 }
1970 }
1971 }
1972
1973 if (covering_rr && wildcard_rr) {
1974 /* If we could prove that neither the name itself, nor the wildcard at the closest encloser exists, we
1975 * proved the NXDOMAIN case. */
1976 *result = DNSSEC_NSEC_NXDOMAIN;
1977
1978 if (authenticated)
1979 *authenticated = covering_rr_authenticated && wildcard_rr_authenticated;
1980 if (ttl)
1981 *ttl = MIN(covering_rr->ttl, wildcard_rr->ttl);
1982
1983 return 0;
1984 }
1985
1986 /* OK, this was not sufficient. Let's see if NSEC3 can help. */
1987 if (have_nsec3)
1988 return dnssec_test_nsec3(answer, key, result, authenticated, ttl);
1989
1990 /* No approproate NSEC RR found, report this. */
1991 *result = DNSSEC_NSEC_NO_RR;
1992 return 0;
1993 }
1994
1995 static int dnssec_nsec_test_enclosed(DnsAnswer *answer, uint16_t type, const char *name, const char *zone, bool *authenticated) {
1996 DnsResourceRecord *rr;
1997 DnsAnswerFlags flags;
1998 int r;
1999
2000 assert(name);
2001 assert(zone);
2002
2003 /* Checks whether there's an NSEC/NSEC3 that proves that the specified 'name' is non-existing in the specified
2004 * 'zone'. The 'zone' must be a suffix of the 'name'. */
2005
2006 DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
2007 bool found = false;
2008
2009 if (rr->key->type != type && type != DNS_TYPE_ANY)
2010 continue;
2011
2012 switch (rr->key->type) {
2013
2014 case DNS_TYPE_NSEC:
2015
2016 /* We only care for NSEC RRs from the indicated zone */
2017 r = dns_resource_record_is_signer(rr, zone);
2018 if (r < 0)
2019 return r;
2020 if (r == 0)
2021 continue;
2022
2023 r = dns_name_between(dns_resource_key_name(rr->key), name, rr->nsec.next_domain_name);
2024 if (r < 0)
2025 return r;
2026
2027 found = r > 0;
2028 break;
2029
2030 case DNS_TYPE_NSEC3: {
2031 _cleanup_free_ char *hashed_domain = NULL, *next_hashed_domain = NULL;
2032
2033 /* We only care for NSEC3 RRs from the indicated zone */
2034 r = dns_resource_record_is_signer(rr, zone);
2035 if (r < 0)
2036 return r;
2037 if (r == 0)
2038 continue;
2039
2040 r = nsec3_is_good(rr, NULL);
2041 if (r < 0)
2042 return r;
2043 if (r == 0)
2044 break;
2045
2046 /* Format the domain we are testing with the NSEC3 RR's hash function */
2047 r = nsec3_hashed_domain_make(
2048 rr,
2049 name,
2050 zone,
2051 &hashed_domain);
2052 if (r < 0)
2053 return r;
2054 if ((size_t) r != rr->nsec3.next_hashed_name_size)
2055 break;
2056
2057 /* Format the NSEC3's next hashed name as proper domain name */
2058 r = nsec3_hashed_domain_format(
2059 rr->nsec3.next_hashed_name,
2060 rr->nsec3.next_hashed_name_size,
2061 zone,
2062 &next_hashed_domain);
2063 if (r < 0)
2064 return r;
2065
2066 r = dns_name_between(dns_resource_key_name(rr->key), hashed_domain, next_hashed_domain);
2067 if (r < 0)
2068 return r;
2069
2070 found = r > 0;
2071 break;
2072 }
2073
2074 default:
2075 continue;
2076 }
2077
2078 if (found) {
2079 if (authenticated)
2080 *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
2081 return 1;
2082 }
2083 }
2084
2085 return 0;
2086 }
2087
2088 static int dnssec_test_positive_wildcard_nsec3(
2089 DnsAnswer *answer,
2090 const char *name,
2091 const char *source,
2092 const char *zone,
2093 bool *authenticated) {
2094
2095 const char *next_closer = NULL;
2096 int r;
2097
2098 /* Run a positive NSEC3 wildcard proof. Specifically:
2099 *
2100 * A proof that the "next closer" of the generating wildcard does not exist.
2101 *
2102 * Note a key difference between the NSEC3 and NSEC versions of the proof. NSEC RRs don't have to exist for
2103 * empty non-transients. NSEC3 RRs however have to. This means it's sufficient to check if the next closer name
2104 * exists for the NSEC3 RR and we are done.
2105 *
2106 * To prove that a.b.c.d.e.f is rightfully synthesized from a wildcard *.d.e.f all we have to check is that
2107 * c.d.e.f does not exist. */
2108
2109 for (;;) {
2110 next_closer = name;
2111 r = dns_name_parent(&name);
2112 if (r <= 0)
2113 return r;
2114
2115 r = dns_name_equal(name, source);
2116 if (r < 0)
2117 return r;
2118 if (r > 0)
2119 break;
2120 }
2121
2122 return dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC3, next_closer, zone, authenticated);
2123 }
2124
2125 static int dnssec_test_positive_wildcard_nsec(
2126 DnsAnswer *answer,
2127 const char *name,
2128 const char *source,
2129 const char *zone,
2130 bool *_authenticated) {
2131
2132 bool authenticated = true;
2133 int r;
2134
2135 /* Run a positive NSEC wildcard proof. Specifically:
2136 *
2137 * A proof that there's neither a wildcard name nor a non-wildcard name that is a suffix of the name "name" and
2138 * a prefix of the synthesizing source "source" in the zone "zone".
2139 *
2140 * See RFC 5155, Section 8.8 and RFC 4035, Section 5.3.4
2141 *
2142 * Note that if we want to prove that a.b.c.d.e.f is rightfully synthesized from a wildcard *.d.e.f, then we
2143 * have to prove that none of the following exist:
2144 *
2145 * 1) a.b.c.d.e.f
2146 * 2) *.b.c.d.e.f
2147 * 3) b.c.d.e.f
2148 * 4) *.c.d.e.f
2149 * 5) c.d.e.f
2150 */
2151
2152 for (;;) {
2153 _cleanup_free_ char *wc = NULL;
2154 bool a = false;
2155
2156 /* Check if there's an NSEC or NSEC3 RR that proves that the mame we determined is really non-existing,
2157 * i.e between the owner name and the next name of an NSEC RR. */
2158 r = dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC, name, zone, &a);
2159 if (r <= 0)
2160 return r;
2161
2162 authenticated = authenticated && a;
2163
2164 /* Strip one label off */
2165 r = dns_name_parent(&name);
2166 if (r <= 0)
2167 return r;
2168
2169 /* Did we reach the source of synthesis? */
2170 r = dns_name_equal(name, source);
2171 if (r < 0)
2172 return r;
2173 if (r > 0) {
2174 /* Successful exit */
2175 *_authenticated = authenticated;
2176 return 1;
2177 }
2178
2179 /* Safety check, that the source of synthesis is still our suffix */
2180 r = dns_name_endswith(name, source);
2181 if (r < 0)
2182 return r;
2183 if (r == 0)
2184 return -EBADMSG;
2185
2186 /* Replace the label we stripped off with an asterisk */
2187 wc = strappend("*.", name);
2188 if (!wc)
2189 return -ENOMEM;
2190
2191 /* And check if the proof holds for the asterisk name, too */
2192 r = dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC, wc, zone, &a);
2193 if (r <= 0)
2194 return r;
2195
2196 authenticated = authenticated && a;
2197 /* In the next iteration we'll check the non-asterisk-prefixed version */
2198 }
2199 }
2200
2201 int dnssec_test_positive_wildcard(
2202 DnsAnswer *answer,
2203 const char *name,
2204 const char *source,
2205 const char *zone,
2206 bool *authenticated) {
2207
2208 int r;
2209
2210 assert(name);
2211 assert(source);
2212 assert(zone);
2213 assert(authenticated);
2214
2215 r = dns_answer_contains_zone_nsec3(answer, zone);
2216 if (r < 0)
2217 return r;
2218 if (r > 0)
2219 return dnssec_test_positive_wildcard_nsec3(answer, name, source, zone, authenticated);
2220 else
2221 return dnssec_test_positive_wildcard_nsec(answer, name, source, zone, authenticated);
2222 }
2223
2224 #else
2225
2226 int dnssec_verify_rrset(
2227 DnsAnswer *a,
2228 const DnsResourceKey *key,
2229 DnsResourceRecord *rrsig,
2230 DnsResourceRecord *dnskey,
2231 usec_t realtime,
2232 DnssecResult *result) {
2233
2234 return -EOPNOTSUPP;
2235 }
2236
2237 int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok) {
2238
2239 return -EOPNOTSUPP;
2240 }
2241
2242 int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) {
2243
2244 return -EOPNOTSUPP;
2245 }
2246
2247 int dnssec_verify_rrset_search(
2248 DnsAnswer *a,
2249 const DnsResourceKey *key,
2250 DnsAnswer *validated_dnskeys,
2251 usec_t realtime,
2252 DnssecResult *result,
2253 DnsResourceRecord **ret_rrsig) {
2254
2255 return -EOPNOTSUPP;
2256 }
2257
2258 int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) {
2259
2260 return -EOPNOTSUPP;
2261 }
2262
2263 int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke) {
2264
2265 return -EOPNOTSUPP;
2266 }
2267
2268 int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) {
2269
2270 return -EOPNOTSUPP;
2271 }
2272
2273 int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
2274
2275 return -EOPNOTSUPP;
2276 }
2277
2278 int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) {
2279
2280 return -EOPNOTSUPP;
2281 }
2282
2283 int dnssec_test_positive_wildcard(
2284 DnsAnswer *answer,
2285 const char *name,
2286 const char *source,
2287 const char *zone,
2288 bool *authenticated) {
2289
2290 return -EOPNOTSUPP;
2291 }
2292
2293 #endif
2294
2295 static const char* const dnssec_result_table[_DNSSEC_RESULT_MAX] = {
2296 [DNSSEC_VALIDATED] = "validated",
2297 [DNSSEC_VALIDATED_WILDCARD] = "validated-wildcard",
2298 [DNSSEC_INVALID] = "invalid",
2299 [DNSSEC_SIGNATURE_EXPIRED] = "signature-expired",
2300 [DNSSEC_UNSUPPORTED_ALGORITHM] = "unsupported-algorithm",
2301 [DNSSEC_NO_SIGNATURE] = "no-signature",
2302 [DNSSEC_MISSING_KEY] = "missing-key",
2303 [DNSSEC_UNSIGNED] = "unsigned",
2304 [DNSSEC_FAILED_AUXILIARY] = "failed-auxiliary",
2305 [DNSSEC_NSEC_MISMATCH] = "nsec-mismatch",
2306 [DNSSEC_INCOMPATIBLE_SERVER] = "incompatible-server",
2307 };
2308 DEFINE_STRING_TABLE_LOOKUP(dnssec_result, DnssecResult);
2309
2310 static const char* const dnssec_verdict_table[_DNSSEC_VERDICT_MAX] = {
2311 [DNSSEC_SECURE] = "secure",
2312 [DNSSEC_INSECURE] = "insecure",
2313 [DNSSEC_BOGUS] = "bogus",
2314 [DNSSEC_INDETERMINATE] = "indeterminate",
2315 };
2316 DEFINE_STRING_TABLE_LOOKUP(dnssec_verdict, DnssecVerdict);