More DNSSEC caching logic, and avoid repeated validation of DS/DNSKEY

This commit is contained in:
Simon Kelley
2014-01-25 16:40:15 +00:00
parent 2d33bda2e6
commit 0744ca66ad
4 changed files with 89 additions and 85 deletions

View File

@@ -141,10 +141,18 @@ int main (int argc, char **argv)
}
#endif
if (option_bool(OPT_DNSSEC_VALID))
{
#ifdef HAVE_DNSSEC
if (daemon->cachesize <CACHESIZ && option_bool(OPT_DNSSEC_VALID))
if (!daemon->dnskeys)
die(_("No trust anchors provided for DNSSEC"), NULL, EC_BADCONF);
if (daemon->cachesize < CACHESIZ)
die(_("Cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
#else
die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
#endif
}
#ifndef HAVE_TFTP
if (option_bool(OPT_TFTP))

View File

@@ -855,11 +855,14 @@ void reply_query(int fd, int family, time_t now)
and validate them with the new data. Failure to find needed data here is an internal error.
Once we get to the original answer (FREC_DNSSEC_QUERY not set) and it validates,
return it to the original requestor. */
if (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY))
{
while (forward->dependent)
{
struct frec *prev;
struct frec *prev = forward->dependent;
free_frec(forward);
forward = prev;
forward->blocking_query = NULL; /* already gone */
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
n = forward->stash_len;
if (status == STAT_SECURE)
{
@@ -867,19 +870,7 @@ void reply_query(int fd, int family, time_t now)
status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
else if (forward->flags & FREC_DS_QUERY)
status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
}
prev = forward->dependent;
free_frec(forward);
forward = prev;
forward->blocking_query = NULL; /* already gone */
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
n = forward->stash_len;
}
/* All DNSKEY and DS records done and in cache, now finally validate original
answer, provided last DNSKEY is OK. */
if (status == STAT_SECURE)
else
status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class);
if (status == STAT_NEED_DS || status == STAT_NEED_KEY)
@@ -888,6 +879,7 @@ void reply_query(int fd, int family, time_t now)
status = STAT_INSECURE;
}
}
}
if (status == STAT_TRUNCATED)
header->hb3 |= HB3_TC;

View File

@@ -1710,12 +1710,12 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
}
else if ((crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
{
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) && sec_reqd)
{
if (!option_bool(OPT_DNSSEC_VALID) || ((crecp->flags & F_NEG) && (crecp->flags & F_DNSSECOK)))
crecp = NULL;
#ifdef HAVE_DNSSEC
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) &&
(crecp->flags & F_DNSSECOK) &&
!(crecp->flags & F_NEG) &&
sec_reqd &&
option_bool(OPT_DNSSEC_VALID))
else if (crecp->flags & F_DNSSECOK)
{
int gotsig = 0;
@@ -1737,6 +1737,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
/* Need to re-run original cache search */
crecp = gotsig ? cache_find_by_addr(NULL, &addr, now, is_arpa) : NULL;
}
}
#endif
if (crecp)
@@ -1918,12 +1919,15 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
crecp = save;
}
/* If the client asked for DNSSEC and we can't provide RRSIGs, either
because we've not doing DNSSEC or the cached answer is signed by negative,
don't answer from the cache, forward instead. */
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) && sec_reqd)
{
if (!option_bool(OPT_DNSSEC_VALID) || ((crecp->flags & F_NEG) && (crecp->flags & F_DNSSECOK)))
crecp = NULL;
#ifdef HAVE_DNSSEC
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) &&
(crecp->flags & F_DNSSECOK) &&
!(crecp->flags & F_NEG) &&
sec_reqd &&
option_bool(OPT_DNSSEC_VALID))
else if (crecp->flags & F_DNSSECOK)
{
/* We're returning validated data, need to return the RRSIG too. */
@@ -1953,7 +1957,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
/* Need to re-run original cache search */
crecp = gotsig ? cache_find_by_name(NULL, name, now, flag | F_CNAME) : NULL;
}
}
#endif
if (crecp)
do