Commit d389e019 authored by Simon Kelley's avatar Simon Kelley

DNSSEC fix: correct logic for signed records in unsigned DNS space.

parent d3699bb6
...@@ -1226,16 +1226,20 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char ...@@ -1226,16 +1226,20 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
if (val == STAT_INSECURE) if (val == STAT_INSECURE)
val = STAT_BOGUS; val = STAT_BOGUS;
if (val == STAT_NO_SIG)
return val;
p = (unsigned char *)(header+1); p = (unsigned char *)(header+1);
extract_name(header, plen, &p, name, 1, 4); extract_name(header, plen, &p, name, 1, 4);
p += 4; /* qtype, qclass */ p += 4; /* qtype, qclass */
if (!(p = skip_section(p, ntohs(header->ancount), header, plen))) if (!(p = skip_section(p, ntohs(header->ancount), header, plen)))
val = STAT_BOGUS; val = STAT_BOGUS;
/* If we return STAT_NO_SIG, name contains the name of the DS query */
if (val == STAT_NO_SIG)
{
*keyname = 0;
return val;
}
/* If the key needed to validate the DS is on the same domain as the DS, we'll /* If the key needed to validate the DS is on the same domain as the DS, we'll
loop getting nowhere. Stop that now. This can happen of the DS answer comes loop getting nowhere. Stop that now. This can happen of the DS answer comes
from the DS's zone, and not the parent zone. */ from the DS's zone, and not the parent zone. */
......
...@@ -850,8 +850,19 @@ void reply_query(int fd, int family, time_t now) ...@@ -850,8 +850,19 @@ void reply_query(int fd, int family, time_t now)
/* We only cache sigs when we've validated a reply. /* We only cache sigs when we've validated a reply.
Avoid caching a reply with sigs if there's a vaildated break in the Avoid caching a reply with sigs if there's a vaildated break in the
DS chain, so we don't return replies from cache missing sigs. */ DS chain, so we don't return replies from cache missing sigs. */
status = STAT_INSECURE_DS; status = STAT_INSECURE_DS;
else if (status == STAT_NO_NS || status == STAT_NO_SIG) else if (status == STAT_NO_SIG)
{
if (option_bool(OPT_DNSSEC_NO_SIGN))
{
status = send_check_sign(forward, now, header, n, daemon->namebuff, daemon->keyname);
if (status == STAT_INSECURE)
status = STAT_INSECURE_DS;
}
else
status = STAT_INSECURE_DS;
}
else if (status == STAT_NO_NS)
status = STAT_BOGUS; status = STAT_BOGUS;
} }
else if (forward->flags & FREC_CHECK_NOSIGN) else if (forward->flags & FREC_CHECK_NOSIGN)
...@@ -997,8 +1008,19 @@ void reply_query(int fd, int family, time_t now) ...@@ -997,8 +1008,19 @@ void reply_query(int fd, int family, time_t now)
Avoid caching a reply with sigs if there's a vaildated break in the Avoid caching a reply with sigs if there's a vaildated break in the
DS chain, so we don't return replies from cache missing sigs. */ DS chain, so we don't return replies from cache missing sigs. */
status = STAT_INSECURE_DS; status = STAT_INSECURE_DS;
else if (status == STAT_NO_NS || status == STAT_NO_SIG) else if (status == STAT_NO_SIG)
status = STAT_BOGUS; {
if (option_bool(OPT_DNSSEC_NO_SIGN))
{
status = send_check_sign(forward, now, header, n, daemon->namebuff, daemon->keyname);
if (status == STAT_INSECURE)
status = STAT_INSECURE_DS;
}
else
status = STAT_INSECURE_DS;
}
else if (status == STAT_NO_NS)
status = STAT_BOGUS;
} }
else if (forward->flags & FREC_CHECK_NOSIGN) else if (forward->flags & FREC_CHECK_NOSIGN)
{ {
...@@ -1418,7 +1440,7 @@ static int send_check_sign(struct frec *forward, time_t now, struct dns_header * ...@@ -1418,7 +1440,7 @@ static int send_check_sign(struct frec *forward, time_t now, struct dns_header *
static int do_check_sign(struct frec *forward, int status, time_t now, char *name, char *keyname) static int do_check_sign(struct frec *forward, int status, time_t now, char *name, char *keyname)
{ {
/* get domain we're checking back from blockdata store, it's stored on the original query. */ /* get domain we're checking back from blockdata store, it's stored on the original query. */
while (forward->dependent) while (forward->dependent && !forward->orig_domain)
forward = forward->dependent; forward = forward->dependent;
blockdata_retrieve(forward->orig_domain, forward->name_len, name); blockdata_retrieve(forward->orig_domain, forward->name_len, name);
...@@ -1451,7 +1473,7 @@ static int do_check_sign(struct frec *forward, int status, time_t now, char *nam ...@@ -1451,7 +1473,7 @@ static int do_check_sign(struct frec *forward, int status, time_t now, char *nam
/* Have entered non-signed part of DNS tree. */ /* Have entered non-signed part of DNS tree. */
if (status == STAT_NO_DS) if (status == STAT_NO_DS)
return STAT_INSECURE; return forward->dependent ? STAT_INSECURE_DS : STAT_INSECURE;
if (status == STAT_BOGUS) if (status == STAT_BOGUS)
return STAT_BOGUS; return STAT_BOGUS;
...@@ -1657,7 +1679,18 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si ...@@ -1657,7 +1679,18 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
{ {
if (new_status == STAT_NO_DS) if (new_status == STAT_NO_DS)
new_status = STAT_INSECURE_DS; new_status = STAT_INSECURE_DS;
else if (new_status == STAT_NO_NS || new_status == STAT_NO_SIG) if (new_status == STAT_NO_SIG)
{
if (option_bool(OPT_DNSSEC_NO_SIGN))
{
new_status = tcp_check_for_unsigned_zone(now, header, n, class, name, keyname, server, keycount);
if (new_status == STAT_INSECURE)
new_status = STAT_INSECURE_DS;
}
else
new_status = STAT_INSECURE_DS;
}
else if (new_status == STAT_NO_NS)
new_status = STAT_BOGUS; new_status = STAT_BOGUS;
} }
} }
...@@ -1722,8 +1755,19 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si ...@@ -1722,8 +1755,19 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
{ {
if (new_status == STAT_NO_DS) if (new_status == STAT_NO_DS)
new_status = STAT_INSECURE_DS; new_status = STAT_INSECURE_DS;
else if (new_status == STAT_NO_NS || new_status == STAT_NO_SIG) else if (new_status == STAT_NO_SIG)
new_status = STAT_BOGUS; /* Validated no DS */ {
if (option_bool(OPT_DNSSEC_NO_SIGN))
{
new_status = tcp_check_for_unsigned_zone(now, header, n, class, name, keyname, server, keycount);
if (new_status == STAT_INSECURE)
new_status = STAT_INSECURE_DS;
}
else
new_status = STAT_INSECURE_DS;
}
else if (new_status == STAT_NO_NS)
new_status = STAT_BOGUS;
} }
} }
else if (status == STAT_CHASE_CNAME) else if (status == STAT_CHASE_CNAME)
......
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