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