diff options
author | Alexander Tsoy <alexander@tsoy.me> | 2019-01-23 16:33:50 +0300 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2019-02-18 18:34:53 +0100 |
commit | 13e6f3831d986dffbcf2ff5628f53bf1ecf0c22b (patch) | |
tree | decdd36c4481306969ad717a28c5dfac8653b443 /src/resolve/resolved-dns-dnssec.c | |
parent | 4b05f0c9d9f6df4e0dab518f8e1ae537bf948f92 (diff) | |
download | systemd-13e6f3831d986dffbcf2ff5628f53bf1ecf0c22b.tar.gz |
resolved: correctly prove the non-existense of wildcard
* Current logic:
For each NSEC RR find the common suffix between the owner name and
the next name, append asterisk to that suffix and check that
generated wildcard is covered by the NSEC RR in question.
* New logic:
Find NSEC RR covering queried name, generate wildcard as
<asterisk>.<closest encloser> using this RR, then check if any
of the NSEC RRs covers generated wildcard.
Diffstat (limited to 'src/resolve/resolved-dns-dnssec.c')
-rw-r--r-- | src/resolve/resolved-dns-dnssec.c | 72 |
1 files changed, 44 insertions, 28 deletions
diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c index 14acc4e77d..3be18de841 100644 --- a/src/resolve/resolved-dns-dnssec.c +++ b/src/resolve/resolved-dns-dnssec.c @@ -1797,22 +1797,14 @@ static int dnssec_nsec_covers(DnsResourceRecord *rr, const char *name) { return dns_name_between(dns_resource_key_name(rr->key), name, rr->nsec.next_domain_name); } -static int dnssec_nsec_covers_wildcard(DnsResourceRecord *rr, const char *name) { - _cleanup_free_ char *wc = NULL; - const char *common_suffix, *signer; - int r; +static int dnssec_nsec_generate_wildcard(DnsResourceRecord *rr, const char *name, char **wc) { + const char *common_suffix1, *common_suffix2, *signer; + int r, labels1, labels2; assert(rr); assert(rr->key->type == DNS_TYPE_NSEC); - /* Checks whether the "Wildcard at the Closest Encloser" is within the space covered by the specified - * RR. Specifically, checks whether 'name' has the common suffix of the NSEC RR's owner and next names as - * suffix, and whether the NSEC covers the name generated by that suffix prepended with an asterisk label. - * - * NSEC bar → waldo.foo.bar: indicates that *.bar and *.foo.bar do not exist - * NSEC waldo.foo.bar → yyy.zzz.xoo.bar: indicates that *.xoo.bar and *.zzz.xoo.bar do not exist (and more ...) - * NSEC yyy.zzz.xoo.bar → bar: indicates that a number of wildcards don#t exist either... - */ + /* Generates "Wildcard at the Closest Encloser" for the given name and NSEC RR. */ r = dns_resource_record_signer(rr, &signer); if (r < 0) @@ -1822,23 +1814,31 @@ static int dnssec_nsec_covers_wildcard(DnsResourceRecord *rr, const char *name) if (r <= 0) return r; - r = dns_name_endswith(name, dns_resource_key_name(rr->key)); + r = dns_name_common_suffix(name, dns_resource_key_name(rr->key), &common_suffix1); if (r < 0) return r; - if (r > 0) /* If the name we are interested in is a child of the NSEC RR, then append the asterisk to the NSEC - * RR's name. */ - r = dns_name_concat("*", dns_resource_key_name(rr->key), 0, &wc); - else { - r = dns_name_common_suffix(dns_resource_key_name(rr->key), rr->nsec.next_domain_name, &common_suffix); - if (r < 0) - return r; - r = dns_name_concat("*", common_suffix, 0, &wc); - } + r = dns_name_common_suffix(name, rr->nsec.next_domain_name, &common_suffix2); + if (r < 0) + return r; + + labels1 = dns_name_count_labels(common_suffix1); + if (labels1 < 0) + return labels1; + + labels2 = dns_name_count_labels(common_suffix2); + if (labels2 < 0) + return labels2; + + if (labels1 > labels2) + r = dns_name_concat("*", common_suffix1, 0, wc); + else + r = dns_name_concat("*", common_suffix2, 0, wc); + if (r < 0) return r; - return dns_name_between(dns_resource_key_name(rr->key), wc, rr->nsec.next_domain_name); + return 0; } int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) { @@ -1942,14 +1942,30 @@ int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r covering_rr = rr; covering_rr_authenticated = flags & DNS_ANSWER_AUTHENTICATED; } + } - /* Check if this NSEC RR proves the absence of a wildcard RR under this name */ - r = dnssec_nsec_covers_wildcard(rr, name); + if (covering_rr) { + _cleanup_free_ char *wc = NULL; + r = dnssec_nsec_generate_wildcard(covering_rr, name, &wc); if (r < 0) return r; - if (r > 0 && (!wildcard_rr || !wildcard_rr_authenticated)) { - wildcard_rr = rr; - wildcard_rr_authenticated = flags & DNS_ANSWER_AUTHENTICATED; + + DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { + + if (rr->key->class != key->class) + continue; + + if (rr->key->type != DNS_TYPE_NSEC) + continue; + + /* Check if this NSEC RR proves the nonexistence of the wildcard */ + r = dnssec_nsec_covers(rr, wc); + if (r < 0) + return r; + if (r > 0 && (!wildcard_rr || !wildcard_rr_authenticated)) { + wildcard_rr = rr; + wildcard_rr_authenticated = flags & DNS_ANSWER_AUTHENTICATED; + } } } |