Commit 0744ca66 authored by Simon Kelley's avatar Simon Kelley

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

parent 2d33bda2
...@@ -141,10 +141,18 @@ int main (int argc, char **argv) ...@@ -141,10 +141,18 @@ int main (int argc, char **argv)
} }
#endif #endif
if (option_bool(OPT_DNSSEC_VALID))
{
#ifdef HAVE_DNSSEC #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); 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 #endif
}
#ifndef HAVE_TFTP #ifndef HAVE_TFTP
if (option_bool(OPT_TFTP)) if (option_bool(OPT_TFTP))
......
...@@ -855,31 +855,22 @@ void reply_query(int fd, int family, time_t now) ...@@ -855,31 +855,22 @@ 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. 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, Once we get to the original answer (FREC_DNSSEC_QUERY not set) and it validates,
return it to the original requestor. */ return it to the original requestor. */
if (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY))
{
while (forward->dependent) while (forward->dependent)
{ {
struct frec *prev; struct frec *prev = forward->dependent;
if (status == STAT_SECURE)
{
if (forward->flags & FREC_DNSKEY_QUERY)
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); free_frec(forward);
forward = prev; forward = prev;
forward->blocking_query = NULL; /* already gone */ forward->blocking_query = NULL; /* already gone */
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header); blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
n = forward->stash_len; 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) if (status == STAT_SECURE)
{
if (forward->flags & FREC_DNSKEY_QUERY)
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);
else
status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class); status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class);
if (status == STAT_NEED_DS || status == STAT_NEED_KEY) if (status == STAT_NEED_DS || status == STAT_NEED_KEY)
...@@ -888,6 +879,7 @@ void reply_query(int fd, int family, time_t now) ...@@ -888,6 +879,7 @@ void reply_query(int fd, int family, time_t now)
status = STAT_INSECURE; status = STAT_INSECURE;
} }
} }
}
if (status == STAT_TRUNCATED) if (status == STAT_TRUNCATED)
header->hb3 |= HB3_TC; header->hb3 |= HB3_TC;
......
...@@ -1710,12 +1710,12 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, ...@@ -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))) 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 #ifdef HAVE_DNSSEC
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) && else if (crecp->flags & F_DNSSECOK)
(crecp->flags & F_DNSSECOK) &&
!(crecp->flags & F_NEG) &&
sec_reqd &&
option_bool(OPT_DNSSEC_VALID))
{ {
int gotsig = 0; int gotsig = 0;
...@@ -1737,6 +1737,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, ...@@ -1737,6 +1737,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
/* Need to re-run original cache search */ /* Need to re-run original cache search */
crecp = gotsig ? cache_find_by_addr(NULL, &addr, now, is_arpa) : NULL; crecp = gotsig ? cache_find_by_addr(NULL, &addr, now, is_arpa) : NULL;
} }
}
#endif #endif
if (crecp) if (crecp)
...@@ -1918,12 +1919,15 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, ...@@ -1918,12 +1919,15 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
crecp = save; 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 #ifdef HAVE_DNSSEC
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) && else if (crecp->flags & F_DNSSECOK)
(crecp->flags & F_DNSSECOK) &&
!(crecp->flags & F_NEG) &&
sec_reqd &&
option_bool(OPT_DNSSEC_VALID))
{ {
/* We're returning validated data, need to return the RRSIG too. */ /* 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, ...@@ -1953,7 +1957,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
/* Need to re-run original cache search */ /* Need to re-run original cache search */
crecp = gotsig ? cache_find_by_name(NULL, name, now, flag | F_CNAME) : NULL; crecp = gotsig ? cache_find_by_name(NULL, name, now, flag | F_CNAME) : NULL;
} }
}
#endif #endif
if (crecp) if (crecp)
do do
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment