diff options
-rw-r--r-- | CHANGELOG | 7 | ||||
-rw-r--r-- | src/crypto.c | 2 | ||||
-rw-r--r-- | src/dnssec.c | 59 |
3 files changed, 44 insertions, 24 deletions
@@ -44,8 +44,13 @@ version 2.88 cases where is can be useful. Thanks to Dominik Derigs for the patch. + Handle DS records for unsupported crypto algorithms correctly. + Such a DS, as long as it is validated, should allow answers + in the domain is attests to be returned as unvalidated, and not + as a validation error. + -(version 2.87 +version 2.87 Allow arbitrary prefix lengths in --rev-server and --domain=....,local diff --git a/src/crypto.c b/src/crypto.c index d799037..2678683 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -452,7 +452,7 @@ char *algo_digest_name(int algo) case 8: return "sha256"; /* RSA/SHA-256 */ case 10: return "sha512"; /* RSA/SHA-512 */ #if MIN_VERSION(3, 6) - case 12: return "gosthash94cp"; /* ECC-GOST */ + case 12: return "gosthash94cp"; /* ECC-GOST */ #endif case 13: return "sha256"; /* ECDSAP256SHA256 */ case 14: return "sha384"; /* ECDSAP384SHA384 */ diff --git a/src/dnssec.c b/src/dnssec.c index daf679e..ce01b2e 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -979,10 +979,13 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch } /* The DNS packet is expected to contain the answer to a DS query - Put all DSs in the answer which are valid into the cache. + Put all DSs in the answer which are valid and have hash and signature algos + we support into the cache. Also handles replies which prove that there's no DS at this location, either because the zone is unsigned or this isn't a zone cut. These are cached too. + If none of the DS's are for supported algos, treat the answer as if + it's a proof of no DS at this location. RFC4035 para 5.2. return codes: STAT_OK At least one valid DS found and in cache. STAT_BOGUS no DS in reply or not signed, fails validation, bad packet. @@ -993,8 +996,8 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class) { unsigned char *p = (unsigned char *)(header+1); - int qtype, qclass, rc, i, neganswer, nons, neg_ttl = 0; - int aclass, atype, rdlen; + int qtype, qclass, rc, i, neganswer, nons, neg_ttl = 0, found_supported = 0; + int aclass, atype, rdlen, flags; unsigned long ttl; union all_addr a; @@ -1065,14 +1068,22 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char algo = *p++; digest = *p++; - if ((key = blockdata_alloc((char*)p, rdlen - 4))) + if (!ds_digest_name(digest) || !ds_digest_name(digest)) + { + a.log.keytag = keytag; + a.log.algo = algo; + a.log.digest = digest; + log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu (not supported)", 0); + neg_ttl = ttl; + } + else if ((key = blockdata_alloc((char*)p, rdlen - 4))) { a.ds.digest = digest; a.ds.keydata = key; a.ds.algo = algo; a.ds.keytag = keytag; a.ds.keylen = rdlen - 4; - + if (!cache_insert(name, &a, class, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)) { blockdata_free(key); @@ -1083,26 +1094,29 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char a.log.keytag = keytag; a.log.algo = algo; a.log.digest = digest; - if (ds_digest_name(digest) && algo_digest_name(algo)) - log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu", 0); - else - log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu (not supported)", 0); + log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu", 0); + found_supported = 1; } } p = psave; } + if (!ADD_RDLEN(header, p, plen, rdlen)) return STAT_BOGUS; /* bad packet */ } cache_end_insert(); + /* Fall through if no supported algo DS found. */ + if (found_supported) + return STAT_OK; } - else + + flags = F_FORWARD | F_DS | F_NEG | F_DNSSECOK; + + if (neganswer) { - int flags = F_FORWARD | F_DS | F_NEG | F_DNSSECOK; - if (RCODE(header) == NXDOMAIN) flags |= F_NXDOMAIN; @@ -1110,17 +1124,18 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char to store presence/absence of NS. */ if (nons) flags &= ~F_DNSSECOK; - - cache_start_insert(); - - /* Use TTL from NSEC for negative cache entries */ - if (!cache_insert(name, NULL, class, now, neg_ttl, flags)) - return STAT_BOGUS; - - cache_end_insert(); - - log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, nons ? "no DS/cut" : "no DS", 0); } + + cache_start_insert(); + + /* Use TTL from NSEC for negative cache entries */ + if (!cache_insert(name, NULL, class, now, neg_ttl, flags)) + return STAT_BOGUS; + + cache_end_insert(); + + if (neganswer) + log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, nons ? "no DS/cut" : "no DS", 0); return STAT_OK; } |