]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/dnsmasq/0113-Handle-CNAMEs-to-DS-records-when-confirming-absence-.patch
squid: Apply fix for Squid Advisory SQUID-2015:2
[ipfire-2.x.git] / src / patches / dnsmasq / 0113-Handle-CNAMEs-to-DS-records-when-confirming-absence-.patch
1 From e3ec6f0bd7323b043faa9dffa20f0c9151fae1e3 Mon Sep 17 00:00:00 2001
2 From: Simon Kelley <simon@thekelleys.org.uk>
3 Date: Fri, 12 Jun 2015 21:39:11 +0100
4 Subject: [PATCH 113/113] Handle CNAMEs to DS records when confirming absence
5 of DS for DNSSEC.
6
7 ---
8 src/dnssec.c | 40 ++++++++++++++++++++++++++++++++++------
9 src/forward.c | 38 ++++++++++++++++++++++++++++++++++----
10 2 files changed, 68 insertions(+), 10 deletions(-)
11
12 diff --git a/src/dnssec.c b/src/dnssec.c
13 index 93217b05a846..52d14548b8e2 100644
14 --- a/src/dnssec.c
15 +++ b/src/dnssec.c
16 @@ -1223,8 +1223,11 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
17 val = dnssec_validate_reply(now, header, plen, name, keyname, NULL, &neganswer, &nons);
18 /* Note dnssec_validate_reply() will have cached positive answers */
19
20 - if (val == STAT_NO_SIG || val == STAT_INSECURE)
21 + if (val == STAT_INSECURE)
22 val = STAT_BOGUS;
23 +
24 + if (val == STAT_NO_SIG)
25 + return val;
26
27 p = (unsigned char *)(header+1);
28 extract_name(header, plen, &p, name, 1, 4);
29 @@ -1875,11 +1878,14 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
30
31 if (neganswer && !have_answer)
32 *neganswer = 1;
33 -
34 +
35 /* No data, therefore no sigs */
36 if (ntohs(header->ancount) + ntohs(header->nscount) == 0)
37 - return STAT_NO_SIG;
38 -
39 + {
40 + *keyname = 0;
41 + return STAT_NO_SIG;
42 + }
43 +
44 for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
45 {
46 if (!extract_name(header, plen, &p1, name, 1, 10))
47 @@ -1948,6 +1954,19 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
48 {
49 if (class)
50 *class = class1; /* Class for DS or DNSKEY */
51 +
52 + if (rc == STAT_NO_SIG)
53 + {
54 + /* If we dropped off the end of a CNAME chain, return
55 + STAT_NO_SIG and the last name is keyname. This is used for proving non-existence
56 + if DS records in CNAME chains. */
57 + if (cname_count == CNAME_CHAIN || i < ntohs(header->ancount))
58 + /* No CNAME chain, or no sig in answer section, return empty name. */
59 + *keyname = 0;
60 + else if (!extract_name(header, plen, &qname, keyname, 1, 0))
61 + return STAT_BOGUS;
62 + }
63 +
64 return rc;
65 }
66
67 @@ -2060,8 +2079,17 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
68 /* NXDOMAIN or NODATA reply, prove that (name, class1, type1) can't exist */
69 /* First marshall the NSEC records, if we've not done it previously */
70 if (!nsec_type && !(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, qclass)))
71 - return STAT_NO_SIG; /* No NSECs, this is probably a dangling CNAME pointing into
72 - an unsigned zone. Return STAT_NO_SIG to cause this to be proved. */
73 + {
74 + /* No NSEC records. If we dropped off the end of a CNAME chain, return
75 + STAT_NO_SIG and the last name is keyname. This is used for proving non-existence
76 + if DS records in CNAME chains. */
77 + if (cname_count == CNAME_CHAIN) /* No CNAME chain, return empty name. */
78 + *keyname = 0;
79 + else if (!extract_name(header, plen, &qname, keyname, 1, 0))
80 + return STAT_BOGUS;
81 + return STAT_NO_SIG; /* No NSECs, this is probably a dangling CNAME pointing into
82 + an unsigned zone. Return STAT_NO_SIG to cause this to be proved. */
83 + }
84
85 /* Get name of missing answer */
86 if (!extract_name(header, plen, &qname, name, 1, 0))
87 diff --git a/src/forward.c b/src/forward.c
88 index 8c3e71cebe87..b40dda37eca2 100644
89 --- a/src/forward.c
90 +++ b/src/forward.c
91 @@ -851,7 +851,7 @@ void reply_query(int fd, int family, time_t now)
92 Avoid caching a reply with sigs if there's a vaildated break in the
93 DS chain, so we don't return replies from cache missing sigs. */
94 status = STAT_INSECURE_DS;
95 - else if (status == STAT_NO_NS)
96 + else if (status == STAT_NO_NS || status == STAT_NO_SIG)
97 status = STAT_BOGUS;
98 }
99 else if (forward->flags & FREC_CHECK_NOSIGN)
100 @@ -997,7 +997,7 @@ void reply_query(int fd, int family, time_t now)
101 Avoid caching a reply with sigs if there's a vaildated break in the
102 DS chain, so we don't return replies from cache missing sigs. */
103 status = STAT_INSECURE_DS;
104 - else if (status == STAT_NO_NS)
105 + else if (status == STAT_NO_NS || status == STAT_NO_SIG)
106 status = STAT_BOGUS;
107 }
108 else if (forward->flags & FREC_CHECK_NOSIGN)
109 @@ -1456,6 +1456,21 @@ static int do_check_sign(struct frec *forward, int status, time_t now, char *nam
110 if (status == STAT_BOGUS)
111 return STAT_BOGUS;
112
113 + if (status == STAT_NO_SIG && *keyname != 0)
114 + {
115 + /* There is a validated CNAME chain that doesn't end in a DS record. Start
116 + the search again in that domain. */
117 + blockdata_free(forward->orig_domain);
118 + forward->name_start = strlen(keyname);
119 + forward->name_len = forward->name_start + 1;
120 + if (!(forward->orig_domain = blockdata_alloc(keyname, forward->name_len)))
121 + return STAT_BOGUS;
122 +
123 + strcpy(name, keyname);
124 + status = 0; /* force to cache when we iterate. */
125 + continue;
126 + }
127 +
128 /* There's a proven DS record, or we're within a zone, where there doesn't need
129 to be a DS record. Add a name and try again.
130 If we've already tried the whole name, then fail */
131 @@ -1572,6 +1587,21 @@ static int tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, s
132 return STAT_INSECURE;
133 }
134
135 + if (status == STAT_NO_SIG && *keyname != 0)
136 + {
137 + /* There is a validated CNAME chain that doesn't end in a DS record. Start
138 + the search again in that domain. */
139 + blockdata_free(block);
140 + name_len = strlen(keyname) + 1;
141 + name_start = name + name_len - 1;
142 +
143 + if (!(block = blockdata_alloc(keyname, name_len)))
144 + return STAT_BOGUS;
145 +
146 + strcpy(name, keyname);
147 + continue;
148 + }
149 +
150 if (status == STAT_BOGUS)
151 {
152 free(packet);
153 @@ -1627,7 +1657,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
154 {
155 if (new_status == STAT_NO_DS)
156 new_status = STAT_INSECURE_DS;
157 - else if (new_status == STAT_NO_NS)
158 + else if (new_status == STAT_NO_NS || new_status == STAT_NO_SIG)
159 new_status = STAT_BOGUS;
160 }
161 }
162 @@ -1692,7 +1722,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
163 {
164 if (new_status == STAT_NO_DS)
165 new_status = STAT_INSECURE_DS;
166 - else if (new_status == STAT_NO_NS)
167 + else if (new_status == STAT_NO_NS || new_status == STAT_NO_SIG)
168 new_status = STAT_BOGUS; /* Validated no DS */
169 }
170 }
171 --
172 2.1.0
173