1 From dd4ad9ac7ea6d51dcc34a1f2cd2da14efbb87714 Mon Sep 17 00:00:00 2001
2 From: Simon Kelley <simon@thekelleys.org.uk>
3 Date: Thu, 17 Dec 2015 10:44:58 +0000
4 Subject: [PATCH] Tweaks to EDNS0 handling in DNS replies.
7 src/dnssec.c | 20 +++++++++-----------
8 src/rfc1035.c | 57 +++++++++++++++++++++++++++++++++------------------------
9 2 files changed, 42 insertions(+), 35 deletions(-)
11 diff --git a/src/dnssec.c b/src/dnssec.c
12 index dc563e0..012b2a6 100644
15 @@ -2129,18 +2129,16 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
16 /* Empty DS without NSECS */
21 + rc = zone_status(name, qclass, keyname, now);
22 + if (rc != STAT_SECURE)
24 - rc = zone_status(name, qclass, keyname, now);
25 - if (rc != STAT_SECURE)
28 - *class = qclass; /* Class for NEED_DS or NEED_DNSKEY */
32 - return STAT_BOGUS; /* signed zone, no NSECs */
35 + *class = qclass; /* Class for NEED_DS or NEED_DNSKEY */
39 + return STAT_BOGUS; /* signed zone, no NSECs */
42 if (nsec_type == T_NSEC)
43 diff --git a/src/rfc1035.c b/src/rfc1035.c
44 index def8fa0..188d05f 100644
47 @@ -1539,7 +1539,13 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
48 int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1;
49 struct mx_srv_record *rec;
53 + if (ntohs(header->ancount) != 0 ||
54 + ntohs(header->nscount) != 0 ||
55 + ntohs(header->qdcount) == 0 ||
56 + OPCODE(header) != QUERY )
59 /* Don't return AD set if checking disabled. */
60 if (header->hb4 & HB4_CD)
62 @@ -1548,33 +1554,32 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
63 *ad_reqd = header->hb4 & HB4_AD;
66 - /* If there is an RFC2671 pseudoheader then it will be overwritten by
67 + /* If there is an additional data section then it will be overwritten by
68 partial replies, so we have to do a dry run to see if we can answer
69 - the query. We check to see if the do bit is set, if so we always
70 - forward rather than answering from the cache, which doesn't include
71 - security information, unless we're in DNSSEC validation mode. */
74 - if (find_pseudoheader(header, qlen, NULL, &pheader, NULL))
76 - unsigned short flags;
78 - have_pseudoheader = 1;
79 + if (ntohs(header->arcount) != 0)
83 - pheader += 4; /* udp size, ext_rcode */
84 - GETSHORT(flags, pheader);
86 - if ((sec_reqd = flags & 0x8000))
88 - *do_bit = 1;/* do bit */
90 + /* If there's an additional section, there might be an EDNS(0) pseudoheader */
91 + if (find_pseudoheader(header, qlen, NULL, &pheader, NULL))
93 + unsigned short flags;
95 + have_pseudoheader = 1;
97 + pheader += 4; /* udp size, ext_rcode */
98 + GETSHORT(flags, pheader);
100 + if ((sec_reqd = flags & 0x8000))
102 + *do_bit = 1;/* do bit */
110 - if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
113 for (rec = daemon->mxnames; rec; rec = rec->next)
116 @@ -1730,8 +1735,12 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
118 else if ((crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
120 - /* Don't use cache when DNSSEC data required. */
121 - if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !sec_reqd || !(crecp->flags & F_DNSSECOK))
122 + /* Don't use cache when DNSSEC data required, unless we know that
123 + the zone is unsigned, which implies that we're doing
125 + if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
127 + (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))