]>
Commit | Line | Data |
---|---|---|
1e1b03d5 MF |
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. | |
5 | ||
6 | --- | |
7 | src/dnssec.c | 20 +++++++++----------- | |
8 | src/rfc1035.c | 57 +++++++++++++++++++++++++++++++++------------------------ | |
9 | 2 files changed, 42 insertions(+), 35 deletions(-) | |
10 | ||
11 | diff --git a/src/dnssec.c b/src/dnssec.c | |
12 | index dc563e0..012b2a6 100644 | |
13 | --- a/src/dnssec.c | |
14 | +++ b/src/dnssec.c | |
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 */ | |
17 | if (qtype == T_DS) | |
18 | return STAT_BOGUS; | |
19 | - else | |
20 | + | |
21 | + rc = zone_status(name, qclass, keyname, now); | |
22 | + if (rc != STAT_SECURE) | |
23 | { | |
24 | - rc = zone_status(name, qclass, keyname, now); | |
25 | - if (rc != STAT_SECURE) | |
26 | - { | |
27 | - if (class) | |
28 | - *class = qclass; /* Class for NEED_DS or NEED_DNSKEY */ | |
29 | - return rc; | |
30 | - } | |
31 | - | |
32 | - return STAT_BOGUS; /* signed zone, no NSECs */ | |
33 | - } | |
34 | + if (class) | |
35 | + *class = qclass; /* Class for NEED_DS or NEED_DNSKEY */ | |
36 | + return rc; | |
37 | + } | |
38 | + | |
39 | + return STAT_BOGUS; /* signed zone, no NSECs */ | |
40 | } | |
41 | ||
42 | if (nsec_type == T_NSEC) | |
43 | diff --git a/src/rfc1035.c b/src/rfc1035.c | |
44 | index def8fa0..188d05f 100644 | |
45 | --- a/src/rfc1035.c | |
46 | +++ b/src/rfc1035.c | |
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; | |
50 | size_t len; | |
51 | - | |
52 | + | |
53 | + if (ntohs(header->ancount) != 0 || | |
54 | + ntohs(header->nscount) != 0 || | |
55 | + ntohs(header->qdcount) == 0 || | |
56 | + OPCODE(header) != QUERY ) | |
57 | + return 0; | |
58 | + | |
59 | /* Don't return AD set if checking disabled. */ | |
60 | if (header->hb4 & HB4_CD) | |
61 | sec_data = 0; | |
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; | |
64 | *do_bit = 0; | |
65 | ||
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. */ | |
72 | + the query. */ | |
73 | ||
74 | - if (find_pseudoheader(header, qlen, NULL, &pheader, NULL)) | |
75 | - { | |
76 | - unsigned short flags; | |
77 | - | |
78 | - have_pseudoheader = 1; | |
79 | + if (ntohs(header->arcount) != 0) | |
80 | + { | |
81 | + dryrun = 1; | |
82 | ||
83 | - pheader += 4; /* udp size, ext_rcode */ | |
84 | - GETSHORT(flags, pheader); | |
85 | - | |
86 | - if ((sec_reqd = flags & 0x8000)) | |
87 | - { | |
88 | - *do_bit = 1;/* do bit */ | |
89 | - *ad_reqd = 1; | |
90 | + /* If there's an additional section, there might be an EDNS(0) pseudoheader */ | |
91 | + if (find_pseudoheader(header, qlen, NULL, &pheader, NULL)) | |
92 | + { | |
93 | + unsigned short flags; | |
94 | + | |
95 | + have_pseudoheader = 1; | |
96 | + | |
97 | + pheader += 4; /* udp size, ext_rcode */ | |
98 | + GETSHORT(flags, pheader); | |
99 | + | |
100 | + if ((sec_reqd = flags & 0x8000)) | |
101 | + { | |
102 | + *do_bit = 1;/* do bit */ | |
103 | + *ad_reqd = 1; | |
104 | + } | |
105 | } | |
106 | - | |
107 | - dryrun = 1; | |
108 | } | |
109 | ||
110 | - if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY ) | |
111 | - return 0; | |
112 | - | |
113 | for (rec = daemon->mxnames; rec; rec = rec->next) | |
114 | rec->offset = 0; | |
115 | ||
116 | @@ -1730,8 +1735,12 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, | |
117 | } | |
118 | else if ((crecp = cache_find_by_addr(NULL, &addr, now, is_arpa))) | |
119 | { | |
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 | |
124 | + validation. */ | |
125 | + if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || | |
126 | + !sec_reqd || | |
127 | + (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))) | |
128 | { | |
129 | do | |
130 | { | |
131 | -- | |
132 | 1.7.10.4 | |
133 |