Skip to content

Commit

Permalink
Handle DS records for unsupported crypto algorithms correctly.
Browse files Browse the repository at this point in the history
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.

Signed-off-by: DL6ER <[email protected]>
  • Loading branch information
simonkelley authored and DL6ER committed Nov 16, 2022
1 parent b6e61c2 commit bc1acb2
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/dnsmasq/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
59 changes: 37 additions & 22 deletions src/dnsmasq/dnssec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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;

Expand Down Expand Up @@ -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);
Expand All @@ -1083,44 +1094,48 @@ 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;

/* We only cache validated DS records, DNSSECOK flag hijacked
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;
}
Expand Down

0 comments on commit bc1acb2

Please sign in to comment.